/***************************************************************************
* Copyright ( C ) 1999 by Jonas Nordin *
* jonas . nordin @ syncom . se *
* Copyright ( C ) 2000 - 2001 by Bernd Gehrmann *
* bernd @ kdevelop . org *
* Copyright ( C ) 2002 - 2003 by Roberto Raggi *
* roberto @ kdevelop . org *
* Copyright ( C ) 2003 - 2004 by Alexander Dymo *
* adymo @ mksat . net *
* *
* 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 "cppsupportpart.h"
# include "cppsupport_events.h"
# include "problemreporter.h"
# include "backgroundparser.h"
# include "store_walker.h"
# include "ast.h"
# include "ast_utils.h"
# include "cppcodecompletion.h"
# include "ccconfigwidget.h"
# include "KDevCppSupportIface.h"
# include "cppsupportfactory.h"
# include "catalog.h"
# include "cpp_tags.h"
# include "kdevdriver.h"
# include "cppcodecompletionconfig.h"
# include "cppsplitheadersourceconfig.h"
# include "tag_creator.h"
# include "cppsupport_utils.h"
# include "classgeneratorconfig.h"
# include "urlutil.h"
# include "creategettersetterconfiguration.h"
# include "kdevsourceformatter.h"
# include "kdevcreatefile.h"
# include "qtbuildconfig.h"
# include "kdeveditorutil.h"
# include <tdetexteditor/viewcursorinterface.h>
# include <tdepopupmenu.h>
// wizards
# include "cppnewclassdlg.h"
# include "subclassingdlg.h"
# include "addmethoddialog.h"
# include "addattributedialog.h"
# include "creategettersetterdialog.h"
// designer integration
# include "qtdesignercppintegration.h"
# include "cppimplementationwidget.h"
# include "configproblemreporter.h"
# include "codeinformationrepository.h"
# include <tqeventloop.h>
# include <tqheader.h>
# include <tqdir.h>
# include <tqdom.h>
# include <tqfileinfo.h>
# include <tqguardedptr.h>
# include <tqpopupmenu.h>
# include <tqprogressdialog.h>
# include <tqstringlist.h>
# include <tqtimer.h>
# include <tqstatusbar.h>
# include <tqprogressbar.h>
# include <tqregexp.h>
# include <tqlabel.h>
# include <tqvbox.h>
# include <tdemessagebox.h>
# include <tdeaction.h>
# include <tdeapplication.h>
# include <kdebug.h>
# include <kdialogbase.h>
# include <kgenericfactory.h>
# include <tdelocale.h>
# include <tdemessagebox.h>
# include <tdemainwindow.h>
# include <kstatusbar.h>
# include <tdeconfig.h>
# include <tdeversion.h>
# include <kstandarddirs.h>
# include <kiconloader.h>
# include <tdetexteditor/document.h>
# include <tdetexteditor/editinterface.h>
# include <tdetexteditor/view.h>
# include <tdetexteditor/selectioninterface.h>
# include <tdetexteditor/viewcursorinterface.h>
# include <tdetexteditor/clipboardinterface.h>
# include <tdetexteditor/texthintinterface.h>
# include <kdevcore.h>
# include <kdevproject.h>
# include <kdevmainwindow.h>
# include <kdevpartcontroller.h>
# include <kdevmakefrontend.h>
# include <kdevcoderepository.h>
# include <codemodel_utils.h>
# include <kdevplugininfo.h>
# include <domutil.h>
# include <config.h>
const bool alwaysParseInBackground = true ;
enum { KDEV_DB_VERSION = 21 } ;
enum { KDEV_PCS_VERSION = 18 } ;
TQStringList CppSupportPart : : m_sourceMimeTypes = TQStringList ( ) < < " text/x-csrc " < < " text/x-c++src " ;
TQStringList CppSupportPart : : m_headerMimeTypes = TQStringList ( ) < < " text/x-chdr " < < " text/x-c++hdr " ;
TQStringList CppSupportPart : : m_sourceExtensions = TQStringList : : split ( " , " , " c,C,cc,cpp,c++,cxx,m,mm,M " ) ;
TQStringList CppSupportPart : : m_headerExtensions = TQStringList : : split ( " , " , " h,H,hh,h++,hxx,hpp,inl,tlh,diff,ui.h " ) ;
class CppDriver : public KDevDriver
{
public :
CppDriver ( CppSupportPart * cppSupport ) : KDevDriver ( cppSupport , true )
{ }
void fileParsed ( ParsedFile & fileName )
{
//kdDebug(9007) << "-----> file " << fileName << " parsed!" << endl;
ParsedFilePointer ast = takeTranslationUnit ( fileName . fileName ( ) ) ;
if ( cppSupport ( ) - > problemReporter ( ) )
{
cppSupport ( ) - > problemReporter ( ) - > removeAllProblems ( fileName . fileName ( ) ) ;
TQValueList < Problem > pl = problems ( fileName . fileName ( ) ) ;
TQValueList < Problem > : : ConstIterator it = pl . begin ( ) ;
while ( it ! = pl . end ( ) )
{
const Problem & p = * it + + ;
cppSupport ( ) - > problemReporter ( ) - > reportProblem ( fileName . fileName ( ) , p ) ;
}
}
StoreWalker walker ( fileName . fileName ( ) , cppSupport ( ) - > codeModel ( ) ) ;
if ( cppSupport ( ) - > codeModel ( ) - > hasFile ( fileName . fileName ( ) ) )
{
FileDom file = cppSupport ( ) - > codeModel ( ) - > fileByName ( fileName . fileName ( ) ) ;
cppSupport ( ) - > removeWithReferences ( fileName . fileName ( ) ) ;
}
walker . parseTranslationUnit ( * ast ) ;
cppSupport ( ) - > codeModel ( ) - > addFile ( walker . file ( ) ) ;
remove
( fileName . fileName ( ) ) ;
if ( cppSupport ( ) - > _jd ) {
cppSupport ( ) - > _jd - > backgroundState + + ;
cppSupport ( ) - > _jd - > lastParse = TQTime : : currentTime ( ) ;
}
TQFileInfo fileInfo ( fileName . fileName ( ) ) ;
TQString path = URLUtil : : canonicalPath ( fileName . fileName ( ) ) ;
cppSupport ( ) - > m_timestamp [ path ] = fileInfo . lastModified ( ) ;
cppSupport ( ) - > emitSynchronousParseReady ( fileName . fileName ( ) , ast ) ;
}
} ;
// ProblemReporter doesn't really depend on background parsing, so it's a bit of a mixup to
// handle them together, but it's the same config widget so...
class BackgroundParserConfig
{
bool m_useProblemReporter ;
bool m_useBackgroundParser ;
int m_backgroundParseDelay ;
public :
void readConfig ( )
{
TDEConfig * config = kapp - > config ( ) ;
config - > setGroup ( " General Options " ) ;
m_useProblemReporter = config - > readBoolEntry ( " EnableProblemReporter " , true ) ;
m_useBackgroundParser = config - > readBoolEntry ( " EnableCppBgParser " , true ) ;
m_backgroundParseDelay = config - > readNumEntry ( " BgParserDelay " , 500 ) ;
}
bool useProblemReporter ( ) { return m_useProblemReporter ; }
bool useBackgroundParser ( ) { return m_useBackgroundParser ; }
int backgroudParseDelay ( ) { return m_backgroundParseDelay ; }
} ;
CppSupportPart : : CppSupportPart ( TQObject * parent , const char * name , const TQStringList & args )
: KDevLanguageSupport ( CppSupportFactory : : info ( ) , parent , name ? name : " KDevCppSupport " ) , m_backgroundParser ( 0 ) ,
m_activeDocument ( 0 ) , m_activeView ( 0 ) , m_activeSelection ( 0 ) , m_activeEditor ( 0 ) , m_activeViewCursor ( 0 ) ,
m_projectClosed ( true ) , m_projectClosing ( false ) , m_valid ( false ) , m_isTyping ( false ) , m_hadErrors ( false ) ,
_jd ( 0 )
{
setInstance ( CppSupportFactory : : instance ( ) ) ;
m_pCompletionConfig = new CppCodeCompletionConfig ( this , projectDom ( ) ) ;
m_pSplitHeaderSourceConfig = new CppSplitHeaderSourceConfig ( this , projectDom ( ) ) ;
m_pCreateGetterSetterConfiguration = new CreateGetterSetterConfiguration ( this ) ; connect ( m_pSplitHeaderSourceConfig , TQT_SIGNAL ( stored ( ) ) ,
this , TQT_SLOT ( splitHeaderSourceConfigStored ( ) ) ) ;
connect ( m_pCompletionConfig , TQT_SIGNAL ( stored ( ) ) ,
this , TQT_SLOT ( codeCompletionConfigStored ( ) ) ) ;
m_qtBuildConfig = new QtBuildConfig ( this , projectDom ( ) ) ;
m_qtBuildConfig - > store ( ) ;
m_backgroundParserConfig = new BackgroundParserConfig ;
m_backgroundParserConfig - > readConfig ( ) ;
m_driver = new CppDriver ( this ) ;
m_problemReporter = 0 ;
m_textChangedTimer = new TQTimer ( this ) ;
connect ( m_textChangedTimer , TQT_SIGNAL ( timeout ( ) ) , this , TQT_SLOT ( slotParseCurrentFile ( ) ) ) ;
m_cursorMovedTimer = new TQTimer ( this ) ;
connect ( m_cursorMovedTimer , TQT_SIGNAL ( timeout ( ) ) , this , TQT_SLOT ( slotCursorPositionChanged ( ) ) ) ;
// m_deleteParserStoreTimer = new TQTimer( this );
m_saveMemoryTimer = new TQTimer ( this ) ;
m_buildSafeFileSetTimer = new TQTimer ( this ) ;
// m_functionHintTimer = new TQTimer( this );
connect ( m_buildSafeFileSetTimer , TQT_SIGNAL ( timeout ( ) ) , this , TQT_SLOT ( buildSafeFileSet ( ) ) ) ;
connect ( m_saveMemoryTimer , TQT_SIGNAL ( timeout ( ) ) , this , TQT_SLOT ( slotSaveMemory ( ) ) ) ;
// connect( m_deleteParserStoreTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(slotDeleteParserStore()) );
resetParserStoreTimer ( ) ;
m_saveMemoryTimer - > start ( 240000 , false ) ; //Free some memory every 4 minutes
// connect( m_functionHintTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(slotFunctionHint()) );
setXMLFile ( " kdevcppsupport.rc " ) ;
m_catalogList . setAutoDelete ( true ) ;
connect ( core ( ) , TQT_SIGNAL ( projectOpened ( ) ) , this , TQT_SLOT ( projectOpened ( ) ) ) ;
connect ( core ( ) , TQT_SIGNAL ( projectClosed ( ) ) , this , TQT_SLOT ( projectClosed ( ) ) ) ;
connect ( core ( ) , TQT_SIGNAL ( languageChanged ( ) ) , this , TQT_SLOT ( projectOpened ( ) ) ) ;
connect ( partController ( ) , TQT_SIGNAL ( savedFile ( const KURL & ) ) ,
this , TQT_SLOT ( savedFile ( const KURL & ) ) ) ;
connect ( core ( ) , TQT_SIGNAL ( contextMenu ( TQPopupMenu * , const Context * ) ) ,
this , TQT_SLOT ( contextMenu ( TQPopupMenu * , const Context * ) ) ) ;
connect ( partController ( ) , TQT_SIGNAL ( activePartChanged ( KParts : : Part * ) ) ,
this , TQT_SLOT ( activePartChanged ( KParts : : Part * ) ) ) ;
connect ( partController ( ) , TQT_SIGNAL ( partRemoved ( KParts : : Part * ) ) ,
this , TQT_SLOT ( partRemoved ( KParts : : Part * ) ) ) ;
connect ( core ( ) , TQT_SIGNAL ( configWidget ( KDialogBase * ) ) ,
this , TQT_SLOT ( configWidget ( KDialogBase * ) ) ) ;
m_switchHeaderSourceAction = new TDEAction ( i18n ( " Switch Header/Implementation " ) , SHIFT + Key_F12 ,
this , TQT_SLOT ( slotSwitchHeader ( ) ) ,
actionCollection ( ) , " edit_switchheader " ) ;
m_switchHeaderSourceAction - > setToolTip ( i18n ( " Switch between header and implementation files " ) ) ;
m_switchHeaderSourceAction - > setWhatsThis ( i18n ( " <b>Switch Header/Implementation</b><p> "
" If you are currently looking at a header file, this "
" brings you to the corresponding implementation file. "
" If you are looking at an implementation file (.cpp etc.), "
" this brings you to the corresponding header file. " ) ) ;
m_switchHeaderSourceAction - > setEnabled ( false ) ;
TDEAction * action ;
action = new TDEAction ( i18n ( " Complete Text " ) , CTRL + Key_Space ,
this , TQT_SLOT ( slotCompleteText ( ) ) ,
actionCollection ( ) , " edit_complete_text " ) ;
action - > setToolTip ( i18n ( " Complete current expression " ) ) ;
action - > setWhatsThis ( i18n ( " <b>Complete Text</p><p>Completes current expression using "
" memory class store for the current project and persistent class stores "
" for external libraries. " ) ) ;
action - > setEnabled ( false ) ;
m_createGetterSetterAction = new TDEAction ( i18n ( " Create Accessor Methods " ) , 0 ,
this , TQT_SLOT ( slotCreateAccessMethods ( ) ) , actionCollection ( ) ,
" edit_create_getter_setter " ) ;
action = new TDEAction ( i18n ( " Make Member " ) , 0 , Key_F2 ,
this , TQT_SLOT ( slotMakeMember ( ) ) ,
actionCollection ( ) , " edit_make_member " ) ;
action - > setToolTip ( i18n ( " Make member " ) ) ;
action - > setWhatsThis ( i18n ( " <b>Make member</b><p>Creates a class member function in implementation file "
" based on the member declaration at the current line. " ) ) ;
action - > plug ( & m_DummyActionWidget ) ;
action = new TDEAction ( i18n ( " Navigation Menu " ) , 0 , CTRL + ALT + Key_Space ,
this , TQT_SLOT ( slotNavigate ( ) ) ,
actionCollection ( ) , " edit_navigate " ) ;
action - > setToolTip ( i18n ( " Show the navigation-menu " ) ) ;
action - > setWhatsThis ( i18n ( " <b>Navigate</b><p>Shows a navigation-menu based on the type-evaluation of the item under the cursor. " ) ) ;
action - > plug ( & m_DummyActionWidget ) ;
action = new TDEAction ( i18n ( " New Class... " ) , " classnew " , 0 ,
this , TQT_SLOT ( slotNewClass ( ) ) ,
actionCollection ( ) , " project_newclass " ) ;
action - > setToolTip ( i18n ( " Generate a new class " ) ) ;
action - > setWhatsThis ( i18n ( " <b>New Class</b><p>Calls the <b>New Class</b> wizard. " ) ) ;
m_pCompletion = 0 ;
withcpp = false ;
if ( args . count ( ) = = 1 & & args [ 0 ] = = " Cpp " )
withcpp = true ;
// daniel
connect ( core ( ) , TQT_SIGNAL ( projectConfigWidget ( KDialogBase * ) ) , this ,
TQT_SLOT ( projectConfigWidget ( KDialogBase * ) ) ) ;
new KDevCppSupportIface ( this ) ;
//(void) dcopClient();
m_lockupTester = new UIBlockTester ( 100 ) ;
}
CppSupportPart : : ~ CppSupportPart ( )
{
delete m_lockupTester ;
if ( ! m_projectClosed )
projectClosed ( ) ;
delete ( m_driver ) ;
m_driver = 0 ;
if ( m_backgroundParser )
{
m_backgroundParser - > close ( ) ;
// m_backgroundParser->wait();
delete m_backgroundParser ;
m_backgroundParser = 0 ;
}
codeRepository ( ) - > setMainCatalog ( 0 ) ;
TQPtrListIterator < Catalog > it ( m_catalogList ) ;
while ( Catalog * catalog = it . current ( ) )
{
+ + it ;
codeRepository ( ) - > unregisterCatalog ( catalog ) ;
}
delete m_backgroundParserConfig ;
m_backgroundParserConfig = 0 ;
delete m_pCompletion ;
m_pCompletion = 0 ;
/* mainWindow()->removeView( m_problemReporter );
delete m_problemReporter ;
m_problemReporter = 0 ;
*/
delete _jd ;
_jd = 0 ;
kdDebug ( 9007 ) < < k_funcinfo < < endl ;
}
void CppSupportPart : : customEvent ( TQCustomEvent * ev )
{
kdDebug ( 9007 ) < < " CppSupportPart::customEvent( " < < ev - > type ( ) < < " ) " < < endl ;
TQTime t ;
t . start ( ) ;
bool fromDisk = false ;
if ( ev - > type ( ) = = int ( Event_FileParsed ) )
{
resetParserStoreTimer ( ) ;
FileParsedEvent * event = ( FileParsedEvent * ) ev ;
fromDisk = event - > fromDisk ( ) ;
TQString fileName = event - > fileName ( ) ;
bool hasErrors = false ;
if ( m_problemReporter )
{
m_problemReporter - > removeAllProblems ( fileName ) ;
TQValueList < Problem > problems = event - > problems ( ) ;
TQValueList < Problem > : : ConstIterator it = problems . begin ( ) ;
while ( it ! = problems . end ( ) )
{
const Problem & p = * it + + ;
if ( p . level ( ) = = Problem : : Level_Error )
hasErrors = true ;
m_problemReporter - > reportProblem ( fileName , p ) ;
}
}
ParsedFilePointer p = m_backgroundParser - > translationUnit ( fileName ) ;
if ( p & & ! p - > includedFrom ( ) . isEmpty ( ) ) {
kdDebug ( 9007 ) < < " customEvent() parsed included file \" " < < fileName < < " \" included from \" " < < p - > includedFrom ( ) < < " \" " < < endl ;
} else {
kdDebug ( 9007 ) < < " customEvent() parsed file \" " < < fileName < < " \" " < < endl ;
}
if ( p & & ! p - > includedFrom ( ) . isEmpty ( ) ) {
if ( ! project ( ) - > isProjectFile ( fileName ) ) {
//The file was parsed to resolve a dependency, and is not a project file
addToRepository ( p ) ;
} else {
//It is a project-file that was parsed for whatever reason to resolve a dependency(currently it isn't handled this way)
}
} else if ( ! project ( ) - > isProjectFile ( fileName ) | | ! m_parseEmitWaiting . reject ( fileName ) ) {
ParseEmitWaiting : : Processed p = m_parseEmitWaiting . processFile ( fileName , ( ! m_hadErrors & & hasErrors & & ! fromDisk & & m_isTyping & & fileName = = m_activeFileName ) ? ParseEmitWaiting : : HadErrors : ParseEmitWaiting : : None ) ;
parseEmit ( p ) ;
//Increase status-bar
if ( p . hasFlag ( ParseEmitWaiting : : Silent ) & & _jd ) {
_jd - > backgroundState + + ;
_jd - > lastParse = TQTime : : currentTime ( ) ;
}
} else {
ParseEmitWaiting : : Processed p = m_fileParsedEmitWaiting . processFile ( fileName ) ;
if ( ! p . hasFlag ( ParseEmitWaiting : : Silent ) )
emitFileParsed ( p ) ;
//Increase status-bar
if ( p . hasFlag ( ParseEmitWaiting : : Silent ) & & _jd ) {
_jd - > backgroundState + + ;
_jd - > lastParse = TQTime : : currentTime ( ) ;
}
}
}
}
void CppSupportPart : : projectConfigWidget ( KDialogBase * dlg )
{
TQVBox * vbox = 0 ;
vbox = dlg - > addVBoxPage ( i18n ( " C++ Support " ) , i18n ( " C++ Support " ) ,
BarIcon ( info ( ) - > icon ( ) , TDEIcon : : SizeMedium ) ) ;
CCConfigWidget * w = new CCConfigWidget ( this , vbox ) ;
connect ( dlg , TQT_SIGNAL ( okClicked ( ) ) , w , TQT_SLOT ( accept ( ) ) ) ;
}
void CppSupportPart : : configWidget ( KDialogBase * dlg )
{
TQVBox * vbox = dlg - > addVBoxPage ( i18n ( " C++ Class Generator " ) , i18n ( " C++ Class Generator " ) ,
BarIcon ( info ( ) - > icon ( ) , TDEIcon : : SizeMedium ) ) ;
ClassGeneratorConfig * w = new ClassGeneratorConfig ( vbox , " classgenerator config widget " ) ;
connect ( dlg , TQT_SIGNAL ( okClicked ( ) ) , w , TQT_SLOT ( storeConfig ( ) ) ) ;
vbox = dlg - > addVBoxPage ( i18n ( " C++ Parsing " ) , i18n ( " C++ Parsing " ) ,
BarIcon ( " text-x-c++src " , TDEIcon : : SizeMedium ) ) ;
ConfigureProblemReporter * ww = new ConfigureProblemReporter ( vbox ) ;
ww - > setPart ( this ) ;
connect ( dlg , TQT_SIGNAL ( okClicked ( ) ) , ww , TQT_SLOT ( accept ( ) ) ) ;
}
void CppSupportPart : : activePartChanged ( KParts : : Part * part )
{
kdDebug ( 9032 ) < < " CppSupportPart::activePartChanged() " < < endl ;
bool enabled = false ;
// m_functionHintTimer->stop();
if ( m_activeView )
{
disconnect ( m_activeView , TQT_SIGNAL ( cursorPositionChanged ( ) ) , this , 0 ) ;
}
if ( m_activeDocument )
{
disconnect ( m_activeDocument , TQT_SIGNAL ( textChanged ( ) ) , this , 0 ) ;
}
m_isTyping = false ;
m_hadErrors = true ;
m_activeDocument = dynamic_cast < KTextEditor : : Document * > ( part ) ;
m_activeView = part ? dynamic_cast < KTextEditor : : View * > ( part - > widget ( ) ) : 0 ;
m_activeEditor = dynamic_cast < KTextEditor : : EditInterface * > ( part ) ;
m_activeSelection = dynamic_cast < KTextEditor : : SelectionInterface * > ( part ) ;
m_activeViewCursor = dynamic_cast < KTextEditor : : ViewCursorInterface * > ( m_activeView ) ;
m_activeFileName = TQString ( ) ;
if ( m_activeDocument )
{
m_activeFileName = URLUtil : : canonicalPath ( m_activeDocument - > url ( ) . path ( ) ) ;
TQFileInfo fi ( m_activeFileName ) ;
TQString ext = fi . extension ( ) ;
if ( isSource ( m_activeFileName ) | | isHeader ( m_activeFileName ) )
enabled = true ;
}
actionCollection ( ) - > action ( " edit_switchheader " ) - > setEnabled ( enabled ) ;
actionCollection ( ) - > action ( " edit_complete_text " ) - > setEnabled ( enabled ) ;
actionCollection ( ) - > action ( " edit_make_member " ) - > setEnabled ( enabled ) ;
if ( ! part | | ! part - > widget ( ) )
return ;
if ( m_activeDocument )
{
connect ( m_activeDocument , TQT_SIGNAL ( textChanged ( ) ) , this , TQT_SLOT ( slotTextChanged ( ) ) ) ;
m_textChangedTimer - > start ( 250 , true ) ; // kick the parse timer, we might want to parse the current file
}
if ( m_activeViewCursor )
{
connect ( m_activeView , TQT_SIGNAL ( cursorPositionChanged ( ) ) , this , TQT_SLOT ( slotCursorMoved ( ) ) ) ;
// this, TQT_SLOT( slotCursorPositionChanged() ) );
}
#if 0
KTextEditor : : TextHintInterface * textHintIface = dynamic_cast < KTextEditor : : TextHintInterface * > ( m_activeView ) ;
if ( ! textHintIface )
return ;
connect ( view , TQT_SIGNAL ( needTextHint ( int , int , TQString & ) ) ,
this , TQT_SLOT ( slotNeedTextHint ( int , int , TQString & ) ) ) ;
textHintIface - > enableTextHints ( 1000 ) ;
# endif
}
void CppSupportPart : : setTyping ( bool typing ) {
m_isTyping = typing ;
if ( m_problemReporter ) {
m_hadErrors & = m_problemReporter - > hasErrors ( m_activeFileName ) ; ///m_hadErrors generally stores whether there was an error-free state of the file.
}
}
void CppSupportPart : : projectOpened ( )
{
kdDebug ( 9007 ) < < " projectOpened( ) " < < endl ;
m_backgroundParser = new BackgroundParser ( this , & m_eventConsumed ) ;
m_backgroundParser - > start ( TQThread : : IdlePriority ) ;
// setup the driver
TQString conf_file_name = specialHeaderName ( ) ;
if ( TQFile : : exists ( conf_file_name ) )
m_driver - > parseFile ( conf_file_name , true , true , true ) ;
m_projectDirectory = URLUtil : : canonicalPath ( project ( ) - > projectDirectory ( ) ) ;
m_projectFileList = project ( ) - > allFiles ( ) ;
setupCatalog ( ) ;
embedProblemReporter ( ) ;
connect ( core ( ) , TQT_SIGNAL ( configWidget ( KDialogBase * ) ) ,
m_problemReporter , TQT_SLOT ( configWidget ( KDialogBase * ) ) ) ;
connect ( project ( ) , TQT_SIGNAL ( addedFilesToProject ( const TQStringList & ) ) ,
this , TQT_SLOT ( addedFilesToProject ( const TQStringList & ) ) ) ;
connect ( project ( ) , TQT_SIGNAL ( removedFilesFromProject ( const TQStringList & ) ) ,
this , TQT_SLOT ( removedFilesFromProject ( const TQStringList & ) ) ) ;
connect ( project ( ) , TQT_SIGNAL ( changedFilesInProject ( const TQStringList & ) ) ,
this , TQT_SLOT ( changedFilesInProject ( const TQStringList & ) ) ) ;
connect ( project ( ) , TQT_SIGNAL ( projectCompiled ( ) ) ,
this , TQT_SLOT ( slotProjectCompiled ( ) ) ) ;
m_timestamp . clear ( ) ;
m_parseEmitWaiting . clear ( ) ;
m_fileParsedEmitWaiting . clear ( ) ;
m_pCompletion = new CppCodeCompletion ( this ) ;
m_projectClosed = false ;
m_buildSafeFileSetTimer - > start ( 500 , true ) ;
updateParserConfiguration ( ) ; //Necessary to respect custom include-paths and such
TQTimer : : singleShot ( 500 , this , TQT_SLOT ( initialParse ( ) ) ) ;
}
void CppSupportPart : : embedProblemReporter ( bool force )
{
if ( force | | m_backgroundParserConfig - > useProblemReporter ( ) )
{
m_problemReporter = new ProblemReporter ( this , 0 , " problemReporterWidget " ) ;
m_problemReporter - > setIcon ( SmallIcon ( " application-vnd.tde.info " ) ) ;
m_problemReporter - > setCaption ( i18n ( " Problem Reporter " ) ) ;
mainWindow ( ) - > embedOutputView ( m_problemReporter , i18n ( " Problems " ) , i18n ( " Problem reporter " ) ) ;
}
}
void CppSupportPart : : removeProblemReporter ( )
{
mainWindow ( ) - > removeView ( m_problemReporter ) ;
delete m_problemReporter ;
m_problemReporter = 0 ;
}
void CppSupportPart : : projectClosed ( )
{
kdDebug ( 9007 ) < < " projectClosed( ) " < < endl ;
m_projectClosing = true ;
TQStringList enabledPCSs ;
TQValueList < Catalog * > catalogs = codeRepository ( ) - > registeredCatalogs ( ) ;
for ( TQValueList < Catalog * > : : Iterator it = catalogs . begin ( ) ; it ! = catalogs . end ( ) ; + + it )
{
Catalog * c = * it ;
if ( c - > enabled ( ) )
enabledPCSs . push_back ( TQFileInfo ( c - > dbName ( ) ) . baseName ( true ) ) ;
}
DomUtil : : writeListEntry ( * project ( ) - > projectDom ( ) , " kdevcppsupport/references " , " pcs " , enabledPCSs ) ;
for ( TQMap < KInterfaceDesigner : : DesignerType , KDevDesignerIntegration * > : : const_iterator it = m_designers . begin ( ) ;
it ! = m_designers . end ( ) ; + + it )
{
kdDebug ( 9007 ) < < " calling save settings fro designer integration " < < endl ;
it . data ( ) - > saveSettings ( * project ( ) - > projectDom ( ) , " kdevcppsupport/designerintegration " ) ;
}
saveProjectSourceInfo ( ) ;
m_pCompletionConfig - > store ( ) ;
delete _jd ;
_jd = 0 ;
removeProblemReporter ( ) ;
delete m_pCompletion ;
m_parseEmitWaiting . clear ( ) ;
m_fileParsedEmitWaiting . clear ( ) ;
m_pCompletion = 0 ;
m_projectClosed = true ;
m_projectClosing = false ;
}
void CppSupportPart : : slotNavigate ( ) {
if ( codeCompletion ( ) & & m_activeView & & m_activeViewCursor ) {
unsigned int curLine = 0 , curCol = 0 ;
m_activeViewCursor - > cursorPositionReal ( & curLine , & curCol ) ;
if ( m_navigationMenu ) delete ( TDEPopupMenu * ) m_navigationMenu ;
m_navigationMenu = new TDEPopupMenu ( m_activeView ) ;
codeCompletion ( ) - > contextEvaluationMenus ( m_navigationMenu , 0 , curLine , curCol ) ;
m_navigationMenu - > move ( m_activeView - > mapToGlobal ( m_activeViewCursor - > cursorCoordinates ( ) ) ) ;
if ( m_navigationMenu - > count ( ) > 0 )
{
m_navigationMenu - > show ( ) ;
}
}
}
void CppSupportPart : : contextMenu ( TQPopupMenu * popup , const Context * context )
{
m_activeClass = 0 ;
m_activeFunction = 0 ;
m_activeVariable = 0 ;
m_curAttribute = 0 ;
m_curClass = 0 ;
if ( context - > hasType ( Context : : EditorContext ) )
{
int id ;
m_switchHeaderSourceAction - > plug ( popup ) ;
// CodeModelItemContext
if ( context - > type ( ) = = Context : : EditorContext )
{
m_curClass = currentClass ( ) ;
if ( m_curClass ! = 0 )
{
m_curAttribute = currentAttribute ( m_curClass ) ;
if ( m_curAttribute ! = 0 )
m_createGetterSetterAction - > plug ( popup ) ;
}
}
TQString text ;
int atline , atcol ;
MakeMemberHelper ( text , atline , atcol ) ;
if ( ! text . isEmpty ( ) )
{
id = popup - > insertItem ( i18n ( " Make Member " ) , this , TQT_SLOT ( slotMakeMember ( ) ) ) ;
popup - > setWhatsThis ( id , i18n ( " <b>Make member</b><p>Creates a class member function in implementation file "
" based on the member declaration at the current line. " ) ) ;
}
kdDebug ( 9007 ) < < " ======> code model has the file: " < < m_activeFileName < < " = " < < codeModel ( ) - > hasFile ( m_activeFileName ) < < endl ;
bool showContextMenuExplosion = false ;
bool showContextTypeEvaluation = false ;
TDEConfig * config = CppSupportFactory : : instance ( ) - > config ( ) ;
if ( config )
{
config - > setGroup ( " General " ) ;
showContextMenuExplosion = config - > readBoolEntry ( " ShowContextMenuExplosion " , false ) ;
config - > setGroup ( " General " ) ;
showContextTypeEvaluation = config - > readBoolEntry ( " ShowContextTypeEvaluation " , true ) ;
}
if ( codeModel ( ) - > hasFile ( m_activeFileName ) ) {
if ( showContextTypeEvaluation & & m_activeViewCursor ! = 0 ) {
if ( codeCompletion ( ) ) {
unsigned int curLine = 0 , curCol = 0 ;
m_activeViewCursor - > cursorPositionReal ( & curLine , & curCol ) ;
codeCompletion ( ) - > contextEvaluationMenus ( popup , context , curLine , curCol ) ;
}
}
if ( showContextMenuExplosion )
{
//kdDebug( 9007 ) << "CppSupportPart::contextMenu 1" << endl;
TQString candidate ;
if ( isSource ( m_activeFileName ) )
candidate = sourceOrHeaderCandidate ( ) ;
else
candidate = m_activeFileName ;
unsigned int curLine = 0 , curCol = 0 ;
if ( m_activeViewCursor ! = 0 )
m_activeViewCursor - > cursorPositionReal ( & curLine , & curCol ) ;
//kdDebug( 9007 ) << "CppSupportPart::contextMenu 2: candidate: " << candidate << endl;
if ( ! candidate . isEmpty ( ) & & codeModel ( ) - > hasFile ( candidate ) )
{
TQPopupMenu * m2 = new TQPopupMenu ( popup ) ;
id = popup - > insertItem ( i18n ( " Go to Declaration " ) , m2 ) ;
popup - > setWhatsThis ( id , i18n ( " <b>Go to declaration</b><p>Provides a menu to select available function declarations "
" in the current file and in the corresponding header (if the current file is an implementation) or source (if the current file is a header) file. " ) ) ;
FileDom file2 = codeModel ( ) - > fileByName ( candidate ) ;
//kdDebug( 9007 ) << "CppSupportPart::contextMenu 3: " << file2->name() << endl;
FunctionList functionList2 = CodeModelUtils : : allFunctions ( file2 ) ;
for ( FunctionList : : ConstIterator it = functionList2 . begin ( ) ; it ! = functionList2 . end ( ) ; + + it )
{
TQString text = ( * it ) - > scope ( ) . join ( " :: " ) ;
//kdDebug( 9007 ) << "CppSupportPart::contextMenu 3 text: " << text << endl;
if ( ! text . isEmpty ( ) )
{
text + = " :: " ;
}
text + = formatModelItem ( * it , true ) ;
text = text . replace ( TQString : : fromLatin1 ( " & " ) , TQString : : fromLatin1 ( " && " ) ) ;
int id = m2 - > insertItem ( text , this , TQT_SLOT ( gotoDeclarationLine ( int ) ) ) ;
int line , column ;
( * it ) - > getStartPosition ( & line , & column ) ;
m2 - > setItemParameter ( id , line ) ;
}
if ( m2 - > count ( ) = = 0 )
{
popup - > removeItem ( id ) ;
}
//kdDebug( 9007 ) << "CppSupportPart::contextMenu 4" << endl;
}
TQString candidate1 ;
if ( isHeader ( m_activeFileName ) )
{
candidate1 = sourceOrHeaderCandidate ( ) ;
}
else
{
candidate1 = m_activeFileName ;
}
//kdDebug( 9007 ) << "CppSupportPart::go to definition in " << candidate1 << endl;
if ( codeModel ( ) - > hasFile ( candidate1 ) )
{
TQPopupMenu * m = new TQPopupMenu ( popup ) ;
id = popup - > insertItem ( i18n ( " Go to Definition " ) , m ) ;
popup - > setWhatsThis ( id , i18n ( " <b>Go to definition</b><p>Provides a menu to select available function definitions "
" in the current file and in the corresponding header (if the current file is an implementation) or source (if the current file is a header) file. " ) ) ;
const FileDom file = codeModel ( ) - > fileByName ( candidate1 ) ;
const FunctionDefinitionList functionDefinitionList = CodeModelUtils : : allFunctionDefinitionsDetailed ( file ) . functionList ;
for ( FunctionDefinitionList : : ConstIterator it = functionDefinitionList . begin ( ) ; it ! = functionDefinitionList . end ( ) ; + + it )
{
TQString text = ( * it ) - > scope ( ) . join ( " :: " ) ;
if ( ! text . isEmpty ( ) )
{
text + = " :: " ;
}
text + = formatModelItem ( * it , true ) ;
text = text . replace ( TQString : : fromLatin1 ( " & " ) , TQString : : fromLatin1 ( " && " ) ) ;
int id = m - > insertItem ( text , this , TQT_SLOT ( gotoLine ( int ) ) ) ;
int line , column ;
( * it ) - > getStartPosition ( & line , & column ) ;
m - > setItemParameter ( id , line ) ;
}
if ( m - > count ( ) = = 0 )
{
popup - > removeItem ( id ) ;
}
}
}
}
const EditorContext * econtext = static_cast < const EditorContext * > ( context ) ;
TQString str = econtext - > currentLine ( ) ;
if ( str . isEmpty ( ) )
return ;
}
else if ( context - > hasType ( Context : : CodeModelItemContext ) )
{
const CodeModelItemContext * mcontext = static_cast < const CodeModelItemContext * > ( context ) ;
if ( mcontext - > item ( ) - > isClass ( ) )
{
m_activeClass = ( ClassModel * ) mcontext - > item ( ) ;
int id = popup - > insertItem ( i18n ( " Extract Interface... " ) , this , TQT_SLOT ( slotExtractInterface ( ) ) ) ;
popup - > setWhatsThis ( id , i18n ( " <b>Extract interface</b><p>Extracts interface from the selected class and creates a new class with this interface. "
" No implementation code is extracted and no implementation code is created. " ) ) ;
}
else if ( mcontext - > item ( ) - > isFunction ( ) )
{
m_activeFunction = ( FunctionModel * ) mcontext - > item ( ) ;
}
}
else if ( context - > hasType ( Context : : FileContext ) )
{
const FileContext * fc = static_cast < const FileContext * > ( context ) ;
//this is a .ui file and only selection contains only one such file
KURL url = fc - > urls ( ) . first ( ) ;
kdDebug ( 9007 ) < < " file context with " < < url . path ( ) < < endl ;
if ( url . fileName ( ) . endsWith ( " .ui " ) )
{
m_contextFileName = url . path ( ) ;
int id = popup - > insertItem ( i18n ( " Create or Select Implementation... " ) , this , TQT_SLOT ( slotCreateSubclass ( ) ) ) ;
popup - > setWhatsThis ( id , i18n ( " <b>Create or select implementation</b><p>Creates or selects a subclass of selected form for use with integrated KDevDesigner. " ) ) ;
}
}
}
TQStringList makeListUnique ( const TQStringList & rhs ) {
TQMap < TQString , bool > map ;
TQStringList ret ;
for ( TQStringList : : const_iterator it = rhs . begin ( ) ; it ! = rhs . end ( ) ; + + it ) {
if ( map . find ( * it ) = = map . end ( ) ) {
ret < < * it ;
map . insert ( * it , true ) ;
}
}
return ret ;
}
// Makes sure that header files come first
TQStringList CppSupportPart : : reorder ( const TQStringList & list )
{
TQStringList headers , others ;
TQStringList headerExtensions = TQStringList : : split ( " , " , " h,H,hh,hxx,hpp,tlh " ) ;
TQString projectPath = project ( ) - > projectDirectory ( ) ;
TQStringList : : ConstIterator it ;
for ( it = list . begin ( ) ; it ! = list . end ( ) ; + + it )
{
TQString filePath = * it ;
// brilliant stuff.. this method is apparently called both with
// relative and absolute paths..
if ( ! filePath . startsWith ( " / " ) )
{
filePath = projectPath + " / " + filePath ;
}
if ( ! isValidSource ( filePath ) ) continue ;
if ( headerExtensions . contains ( TQFileInfo ( filePath ) . extension ( ) ) )
headers < < ( filePath ) ;
else
others < < ( filePath ) ;
}
return makeListUnique ( headers + others ) ;
}
void CppSupportPart : : addedFilesToProject ( const TQStringList & fileList )
{
m_projectFileList = project ( ) - > allFiles ( ) ;
TQStringList files = reorder ( fileList ) ;
for ( TQStringList : : ConstIterator it = files . begin ( ) ; it ! = files . end ( ) ; + + it )
{
TQString path = * it ;
if ( ! path . startsWith ( " / " ) )
path = URLUtil : : canonicalPath ( m_projectDirectory + " / " + ( * it ) ) ;
maybeParse ( path ) ;
//emit addedSourceInfo( path );
}
m_buildSafeFileSetTimer - > start ( 500 , true ) ;
}
void CppSupportPart : : removedFilesFromProject ( const TQStringList & fileList )
{
m_projectFileList = project ( ) - > allFiles ( ) ;
for ( TQStringList : : ConstIterator it = fileList . begin ( ) ; it ! = fileList . end ( ) ; + + it )
{
TQString path = URLUtil : : canonicalPath ( m_projectDirectory + " / " + * it ) ;
kdDebug ( 9007 ) < < " =====================> remove file: " < < path < < endl ;
removeWithReferences ( path ) ;
m_backgroundParser - > removeFile ( path ) ;
}
m_buildSafeFileSetTimer - > start ( 500 , true ) ;
}
void CppSupportPart : : changedFilesInProject ( const TQStringList & fileList )
{
TQStringList files = reorder ( fileList ) ;
for ( TQStringList : : ConstIterator it = files . begin ( ) ; it ! = files . end ( ) ; + + it )
{
TQString path = URLUtil : : canonicalPath ( m_projectDirectory + " / " + * it ) ;
maybeParse ( path ) ;
//emit addedSourceInfo( path );
}
}
void CppSupportPart : : savedFile ( const KURL & file )
{
if ( file . path ( ) = = m_activeFileName ) {
m_isTyping = false ;
m_hadErrors = false ;
maybeParse ( file . path ( ) ) ;
}
Q_UNUSED ( file . path ( ) ) ;
#if 0 // not needed anymore
kdDebug ( 9007 ) < < " savedFile(): " < < fileName . mid ( m_projectDirectory . length ( ) + 1 ) < < endl ;
if ( m_projectFileList . contains ( fileName . mid ( m_projectDirectory . length ( ) + 1 ) ) )
{
maybeParse ( fileName ) ;
emit addedSourceInfo ( fileName ) ;
}
# endif
}
TQString CppSupportPart : : findSourceFile ( )
{
// get the path of the currently active document
TQFileInfo fi ( m_activeFileName ) ;
TQString path = fi . filePath ( ) ;
TQString ext = fi . extension ( ) ;
// extract the base path (full path without '.' and extension)
TQString base = path . left ( path . length ( ) - ext . length ( ) - 1 ) ;
TQStringList candidates ;
if ( TQStringList : : split ( ' , ' , " h,H,hh,hxx,hpp,tlh " ) . contains ( ext ) )
{
candidates < < ( base + " .c " ) ;
candidates < < ( base + " .cc " ) ;
candidates < < ( base + " .cpp " ) ;
candidates < < ( base + " .c++ " ) ;
candidates < < ( base + " .cxx " ) ;
candidates < < ( base + " .C " ) ;
candidates < < ( base + " .m " ) ;
candidates < < ( base + " .mm " ) ;
candidates < < ( base + " .M " ) ;
candidates < < ( base + " .inl " ) ;
candidates < < ( base + " _impl.h " ) ;
}
TQStringList : : ConstIterator it ;
for ( it = candidates . begin ( ) ; it ! = candidates . end ( ) ; + + it )
{
kdDebug ( 9007 ) < < " Trying " < < ( * it ) < < endl ;
if ( TQFileInfo ( * it ) . exists ( ) )
{
return * it ;
}
}
return m_activeFileName ;
}
TQString CppSupportPart : : sourceOrHeaderCandidate ( const KURL & url )
{
TQString urlPath ;
if ( url . isEmpty ( ) )
{
KTextEditor : : Document * doc =
dynamic_cast < KTextEditor : : Document * > ( partController ( ) - > activePart ( ) ) ;
if ( ! doc )
return TQString ( ) ;
urlPath = doc - > url ( ) . path ( ) ;
}
else
{
urlPath = url . path ( ) ;
}
// get the path of the currently active document
TQFileInfo fi ( urlPath ) ;
TQString path = fi . filePath ( ) ;
// extract the exension
TQString ext = fi . extension ( ) ;
if ( ext . isEmpty ( ) )
return TQString ( ) ;
// extract the base path (full path without '.' and extension)
TQString base = path . left ( path . length ( ) - ext . length ( ) - 1 ) ;
//kdDebug( 9007 ) << "base: " << base << ", ext: " << ext << endl;
// just the filename without the extension
TQString fileNameWoExt = fi . fileName ( ) ;
if ( ! ext . isEmpty ( ) )
fileNameWoExt . replace ( " . " + ext , " " ) ;
TQString possibleExts ;
// depending on the current extension assemble a list of
// candidate files to look for
TQStringList candidates ;
// special case for template classes created by the new class dialog
if ( path . endsWith ( " _impl.h " ) )
{
TQString headerpath = path ;
headerpath . replace ( " _impl.h " , " .h " ) ;
candidates < < headerpath ;
fileNameWoExt . replace ( " _impl " , " " ) ;
possibleExts = " h " ;
}
// if file is a header file search for implementation file
else if ( TQStringList : : split ( ' , ' , " h,H,hh,hxx,hpp,tlh " ) . contains ( ext ) )
{
candidates < < ( base + " .c " ) ;
candidates < < ( base + " .cc " ) ;
candidates < < ( base + " .cpp " ) ;
candidates < < ( base + " .c++ " ) ;
candidates < < ( base + " .cxx " ) ;
candidates < < ( base + " .C " ) ;
candidates < < ( base + " .m " ) ;
candidates < < ( base + " .mm " ) ;
candidates < < ( base + " .M " ) ;
candidates < < ( base + " .inl " ) ;
candidates < < ( base + " _impl.h " ) ;
possibleExts = " c,cc,cpp,c++,cxx,C,m,mm,M,inl,_impl.h " ;
}
// if file is an implementation file, search for header file
else if ( TQStringList : : split ( ' , ' , " c,cc,cpp,c++,cxx,C,m,mm,M,inl " ) . contains ( ext ) )
{
candidates < < ( base + " .h " ) ;
candidates < < ( base + " .H " ) ;
candidates < < ( base + " .hh " ) ;
candidates < < ( base + " .hxx " ) ;
candidates < < ( base + " .hpp " ) ;
candidates < < ( base + " .tlh " ) ;
possibleExts = " h,H,hh,hxx,hpp,tlh " ;
}
// search for files from the assembled candidate lists, return the first
// candidate file that actually exists or TQString() if nothing is found.
TQStringList : : ConstIterator it ;
for ( it = candidates . begin ( ) ; it ! = candidates . end ( ) ; + + it )
{
//kdDebug( 9007 ) << "Trying " << ( *it ) << endl;
if ( TQFileInfo ( * it ) . exists ( ) )
{
kdDebug ( 9007 ) < < " using: " < < * it < < endl ;
return * it ;
}
}
//kdDebug( 9007 ) << "Now searching in project files." << endl;
// Our last resort: search the project file list for matching files
TQStringList : : iterator fileIt ;
TQFileInfo candidateFileWoExt ;
TQString candidateFileWoExtString ;
TQStringList possibleExtsList = TQStringList : : split ( ' , ' , possibleExts ) ;
for ( fileIt = m_projectFileList . begin ( ) ; fileIt ! = m_projectFileList . end ( ) ; + + fileIt )
{
candidateFileWoExt . setFile ( * fileIt ) ;
//kdDebug( 9007 ) << "candidate file: " << *fileIt << endl;
if ( ! candidateFileWoExt . extension ( ) . isEmpty ( ) )
candidateFileWoExtString = candidateFileWoExt . fileName ( ) . replace ( " . " + candidateFileWoExt . extension ( ) , " " ) ;
if ( candidateFileWoExtString = = fileNameWoExt )
{
if ( possibleExtsList . contains ( candidateFileWoExt . extension ( ) ) | | candidateFileWoExt . extension ( ) . isEmpty ( ) )
{
//kdDebug( 9007 ) << "checking if " << *fileIt << " exists" << endl;
if ( TQFileInfo ( * fileIt ) . exists ( ) )
kdDebug ( 9007 ) < < " using: " < < * fileIt < < endl ;
return * fileIt ;
}
}
}
return TQString ( ) ;
}
void CppSupportPart : : slotSaveMemory ( ) {
if ( m_backgroundParser ) {
///This is done so the caches are completely empty after tdevelop was idle for some time(else it would be waste of memory). The background-parsers internal lexer-cache-manager just cares about keeping the count of cached files under a specific count, but doesn't decrease that count when tdevelop is idle.
m_backgroundParser - > lock ( ) ;
m_backgroundParser - > saveMemory ( ) ;
m_backgroundParser - > unlock ( ) ;
}
}
void CppSupportPart : : slotSwitchHeader ( bool scrollOnly )
{
bool attemptMatch = true ;
TDEConfig * config = CppSupportFactory : : instance ( ) - > config ( ) ;
if ( config )
{
config - > setGroup ( " General " ) ;
attemptMatch = config - > readBoolEntry ( " SwitchShouldMatch " , true ) ;
}
// ok, both files exist. Do the codemodel have them?
if ( codeModel ( ) - > hasFile ( m_activeFileName ) & & m_activeViewCursor & & attemptMatch )
{
unsigned int currentline , column ;
m_activeViewCursor - > cursorPositionReal ( & currentline , & column ) ;
if ( switchHeaderImpl ( m_activeFileName , currentline , column , scrollOnly ) )
return ;
}
// last chance
KURL url ;
url . setPath ( sourceOrHeaderCandidate ( ) ) ;
if ( scrollOnly )
return ;
else if ( ! splitHeaderSourceConfig ( ) - > splitEnabled ( ) )
partController ( ) - > editDocument ( url ) ;
else
partController ( ) - > splitCurrentDocument ( url ) ;
}
bool CppSupportPart : : switchHeaderImpl ( const TQString & file , int line , int col , bool scrollOnly )
{
bool handled = false ;
FunctionDom d ;
FileDom fd = codeModel ( ) - > fileByName ( file ) ;
if ( fd ) {
CodeModelUtils : : CodeModelHelper h ( codeModel ( ) , fd ) ;
d = h . functionAt ( line , col ) ;
}
if ( d ) {
if ( d - > isFunctionDefinition ( ) ) {
FunctionDom decl = findFunction ( d ) ;
if ( decl ) {
if ( ( void * ) & decl ! = ( void * ) d . data ( ) & & ( ! scrollOnly | | decl - > fileName ( ) ! = file ) ) {
jumpToCodeModelItem ( model_cast < ItemDom > ( decl ) , scrollOnly ) ;
handled = true ;
}
}
} else {
FunctionDom def = findFunctionDefinition ( d ) ;
if ( def ) {
if ( def ! = d & & ( ! scrollOnly | | def - > fileName ( ) ! = file ) ) {
jumpToCodeModelItem ( model_cast < ItemDom > ( def ) , scrollOnly ) ;
handled = true ;
}
}
}
}
return handled ;
}
FunctionDom CppSupportPart : : findFunction ( const FunctionDom & def )
{
// We have a definition so we're looking for a declaration. The declaration will either be the child of a namespace node (non class members)
// or the child of a class node (class member). Search recursively until we find a declaration that matches.
FunctionDom bestMatch ;
FunctionDom decl = findFunctionInNamespace ( codeModel ( ) - > globalNamespace ( ) , def , codeModel ( ) - > globalNamespace ( ) - > namespaceImports ( ) ,
sourceOrHeaderCandidate ( def - > fileName ( ) ) , 0 , bestMatch ) ;
return decl ? decl : bestMatch ;
}
FunctionDom CppSupportPart : : findFunctionInNamespace ( const NamespaceDom & ns , const FunctionDom & def , const std : : set < NamespaceImportModel > & nsImports ,
const TQString & candidateFile , int scopeIndex , FunctionDom & bestMatch )
{
FunctionDom d ;
TQStringList scope = def - > scope ( ) ;
if ( ! ( scopeIndex > = ( signed ) scope . size ( ) ) ) {
NamespaceDom ns_next = ns - > namespaceByName ( scope [ scopeIndex ] ) ;
if ( ns_next ) {
d = findFunctionInNamespace ( ns_next , def , ns_next - > namespaceImports ( ) , candidateFile , scopeIndex + 1 , bestMatch ) ;
}
if ( ! d ) {
for ( std : : set < NamespaceImportModel > : : const_iterator it_ns = nsImports . begin ( ) ; it_ns ! = nsImports . end ( ) ; + + it_ns ) {
if ( ( * it_ns ) . fileName ( ) . str ( ) = = def - > fileName ( ) ) {
ns_next = ns - > namespaceByName ( ( * it_ns ) . name ( ) ) ;
if ( ns_next ) {
if ( d = findFunctionInNamespace ( ns_next , def , nsImports , candidateFile , scopeIndex , bestMatch ) ) break ;
}
}
}
}
if ( ! d ) {
ClassList classList = ns - > classByName ( scope [ scopeIndex ] ) ;
for ( ClassList : : ConstIterator it_cs = classList . begin ( ) ; it_cs ! = classList . end ( ) ; ) {
if ( d = findFunctionInClass ( * ( it_cs + + ) , def , nsImports , candidateFile , scopeIndex + 1 , bestMatch ) ) break ;
}
}
}
if ( ! d ) {
FunctionList functionList = ns - > functionByName ( def - > name ( ) ) ;
for ( FunctionList : : ConstIterator it_decl = functionList . begin ( ) ; it_decl ! = functionList . end ( ) ; + + it_decl ) {
if ( CodeModelUtils : : compareDeclarationToDefinition ( * it_decl , ( FunctionDefinitionModel * ) def . data ( ) , nsImports ) ) {
ParsedFile * p = dynamic_cast < ParsedFile * > ( def - > file ( ) - > parseResult ( ) . data ( ) ) ;
if ( p ) {
if ( p - > includeFiles ( ) [ ( * it_decl ) - > fileName ( ) ] ) {
d = * it_decl ;
break ;
} else if ( ( * it_decl ) - > fileName ( ) = = candidateFile ) {
d = * it_decl ;
break ;
}
}
if ( ! bestMatch ) {
bestMatch = * it_decl ;
}
}
}
}
return d ;
}
FunctionDom CppSupportPart : : findFunctionInClass ( const ClassDom & cs , const FunctionDom & def , const std : : set < NamespaceImportModel > & nsImports ,
const TQString & candidateFile , int scopeIndex , FunctionDom & bestMatch )
{
FunctionDom d ;
TQStringList scope = def - > scope ( ) ;
if ( ! ( scopeIndex > = ( signed ) scope . size ( ) ) ) {
ClassList classList = cs - > classByName ( scope [ scopeIndex ] ) ;
for ( ClassList : : ConstIterator it_cs = classList . begin ( ) ; it_cs ! = classList . end ( ) ; ) {
if ( d = findFunctionInClass ( * ( it_cs + + ) , def , nsImports , candidateFile , scopeIndex + 1 , bestMatch ) ) break ;
}
}
if ( ! d ) {
FunctionList functionList = cs - > functionByName ( def - > name ( ) ) ;
for ( FunctionList : : ConstIterator it_decl = functionList . begin ( ) ; it_decl ! = functionList . end ( ) ; + + it_decl ) {
if ( CodeModelUtils : : compareDeclarationToDefinition ( * it_decl , ( FunctionDefinitionModel * ) def . data ( ) , nsImports ) ) {
ParsedFile * p = dynamic_cast < ParsedFile * > ( def - > file ( ) - > parseResult ( ) . data ( ) ) ;
if ( p ) {
if ( p - > includeFiles ( ) [ ( * it_decl ) - > fileName ( ) ] ) {
d = * it_decl ;
break ;
} else if ( ( * it_decl ) - > fileName ( ) = = candidateFile ) {
d = * it_decl ;
break ;
}
}
if ( ! bestMatch ) {
bestMatch = * it_decl ;
}
}
}
}
return d ;
}
FunctionDom CppSupportPart : : findFunctionDefinition ( const FunctionDom & decl )
{
// We have a declaration so we're looking for a definition. The definition will be the child of some namespace node (never a class node).
// Since the definition can be the child of any namespace in its scope depending on syntax, we have to check every one.
FunctionDom def , bestMatch ;
NamespaceDom ns = codeModel ( ) - > globalNamespace ( ) ;
TQString candidateFile = sourceOrHeaderCandidate ( decl - > fileName ( ) ) ;
FunctionDefinitionList functionList = ns - > functionDefinitionByName ( decl - > name ( ) ) ;
for ( FunctionDefinitionList : : ConstIterator it_def = functionList . begin ( ) ; it_def ! = functionList . end ( ) & & ! def ; + + it_def ) {
if ( CodeModelUtils : : compareDeclarationToDefinition ( decl , * it_def , ns - > namespaceImports ( ) ) ) {
ParsedFile * p = dynamic_cast < ParsedFile * > ( ( * it_def ) - > file ( ) - > parseResult ( ) . data ( ) ) ;
if ( p ) {
if ( p - > includeFiles ( ) [ decl - > fileName ( ) ] ) {
def = * it_def ;
} else if ( ( * it_def ) - > fileName ( ) = = candidateFile ) {
def = * it_def ;
break ;
}
}
if ( ! bestMatch ) {
bestMatch = * it_def ;
}
}
}
TQStringList scope = decl - > scope ( ) ;
for ( TQStringList : : ConstIterator it_scope = scope . begin ( ) ; it_scope ! = scope . end ( ) & & ! def ; + + it_scope ) {
NamespaceDom ns_next = ns - > namespaceByName ( * it_scope ) ;
if ( ns_next ) {
ns = ns_next ;
FunctionDefinitionList functionList = ns - > functionDefinitionByName ( decl - > name ( ) ) ;
for ( FunctionDefinitionList : : ConstIterator it_def = functionList . begin ( ) ; it_def ! = functionList . end ( ) & & ! def ; + + it_def ) {
if ( CodeModelUtils : : compareDeclarationToDefinition ( decl , * it_def , ns - > namespaceImports ( ) ) ) {
ParsedFile * p = dynamic_cast < ParsedFile * > ( ( * it_def ) - > file ( ) - > parseResult ( ) . data ( ) ) ;
if ( p ) {
if ( p - > includeFiles ( ) [ decl - > fileName ( ) ] ) {
def = * it_def ;
} else if ( ( * it_def ) - > fileName ( ) = = candidateFile ) {
def = * it_def ;
break ;
}
}
if ( ! bestMatch ) {
bestMatch = * it_def ;
}
}
}
}
}
return def ? def : bestMatch ;
}
void CppSupportPart : : jumpToCodeModelItem ( const ItemDom & item , bool scrollOnly )
{
static KURL lastSyncedUrl ;
static int lastSyncedLine = - 1 ;
int line , col ;
item - > getStartPosition ( & line , & col ) ;
KURL url ( item - > fileName ( ) ) ;
if ( scrollOnly ) {
KParts : : ReadOnlyPart * part = partController ( ) - > partForURL ( url ) ;
int currentLine = lastSyncedLine ;
if ( part ) {
KTextEditor : : ViewCursorInterface * iface = dynamic_cast < KTextEditor : : ViewCursorInterface * > ( part - > widget ( ) ) ;
if ( iface )
iface - > cursorPosition ( ( uint * ) & currentLine , ( uint * ) & col ) ;
}
partController ( ) - > scrollToLineColumn ( url , line , - 1 , lastSyncedLine ! = currentLine | | lastSyncedUrl ! = url ) ;
} else if ( ! splitHeaderSourceConfig ( ) - > splitEnabled ( ) )
partController ( ) - > editDocument ( url , line ) ;
else
partController ( ) - > splitCurrentDocument ( url , line ) ;
lastSyncedLine = line ;
lastSyncedUrl = url ;
}
KDevLanguageSupport : : Features CppSupportPart : : features ( )
{
if ( withcpp )
return Features ( Classes | Structs | Functions | Variables | Namespaces | Declarations
| Signals | Slots | AddMethod | AddAttribute | NewClass | CreateAccessMethods ) ;
else
return Features ( Structs | Functions | Variables | Declarations ) ;
}
TQString CppSupportPart : : formatClassName ( const TQString & name )
{
TQString n = name ;
return n . replace ( " . " , " :: " ) ;
}
TQString CppSupportPart : : unformatClassName ( const TQString & name )
{
TQString n = name ;
return n . replace ( " :: " , " . " ) ;
}
bool CppSupportPart : : shouldSplitDocument ( const KURL & url )
{
if ( ! splitHeaderSourceConfig ( ) - > splitEnabled ( ) )
return false ;
KURL : : List list = partController ( ) - > openURLs ( ) ;
KURL : : List : : ConstIterator it = list . begin ( ) ;
while ( it ! = list . end ( ) )
{
TQString candidate = sourceOrHeaderCandidate ( ( * it ) ) ;
if ( candidate . isEmpty ( ) )
{
+ + it ;
continue ;
}
KURL urlCandidate ;
urlCandidate . setPath ( candidate ) ;
if ( url = = urlCandidate )
{
// It is already open, so switch to it so
// our split view will open with it
partController ( ) - > editDocument ( ( * it ) ) ;
return true ;
}
+ + it ;
}
return false ;
}
Qt : : Orientation CppSupportPart : : splitOrientation ( ) const
{
TQString o = splitHeaderSourceConfig ( ) - > orientation ( ) ;
if ( o = = " Vertical " )
return Qt : : Vertical ;
else
return Qt : : Horizontal ;
}
void CppSupportPart : : slotNewClass ( )
{
CppNewClassDialog dlg ( this ) ;
dlg . exec ( ) ;
}
void CppSupportPart : : addMethod ( ClassDom klass )
{
if ( ! klass )
{
KMessageBox : : error ( 0 , i18n ( " Please select a class. " ) , i18n ( " Error " ) ) ;
return ;
}
AddMethodDialog dlg ( this , klass , mainWindow ( ) - > main ( ) ) ;
dlg . exec ( ) ;
}
void CppSupportPart : : addAttribute ( ClassDom klass )
{
if ( ! klass )
{
KMessageBox : : error ( 0 , i18n ( " Please select a class. " ) , i18n ( " Error " ) ) ;
return ;
}
AddAttributeDialog dlg ( this , klass , mainWindow ( ) - > main ( ) ) ;
dlg . exec ( ) ;
}
void CppSupportPart : : slotCompleteText ( )
{
if ( ! m_pCompletion )
return ;
m_pCompletion - > completeText ( true ) ;
}
/**
* parsing stuff for project persistent classstore and code completion
*/
void CppSupportPart : : initialParse ( )
{
// For debugging
if ( ! project ( ) )
{
// messagebox ?
kdDebug ( 9007 ) < < " No project " < < endl ;
return ;
}
parseProject ( ) ;
m_valid = true ;
return ;
}
bool CppSupportPart : : parseProject ( bool force )
{
if ( _jd )
delete _jd - > progressBar ; ///Make sure the progress-bar is open
mainWindow ( ) - > statusBar ( ) - > message ( i18n ( " Updating... " ) ) ;
kapp - > setOverrideCursor ( waitCursor ) ;
_jd = new JobData ;
if ( TQFileInfo ( project ( ) - > projectDirectory ( ) + " / " + project ( ) - > projectName ( ) . lower ( )
+ " .kdevelop.pcs " ) . exists ( ) )
{
TQDir d ( project ( ) - > projectDirectory ( ) ) ;
d . rename ( project ( ) - > projectName ( ) . lower ( ) + " .kdevelop.pcs " ,
project ( ) - > projectName ( ) + " .kdevelop.pcs " ) ;
}
_jd - > file . setName ( project ( ) - > projectDirectory ( ) + " / " + project ( ) - > projectName ( )
+ " .kdevelop.pcs " ) ;
TQString skip_file_name = project ( ) - > projectDirectory ( ) + " / " +
project ( ) - > projectName ( ) + " .kdevelop.ignore_pcs " ;
TQString skip_lower_file_name = project ( ) - > projectDirectory ( ) + " / " +
project ( ) - > projectName ( ) . lower ( ) + " .kdevelop.ignore_pcs " ;
if ( ! force & & ! TQFile : : exists ( skip_file_name ) & &
! TQFile : : exists ( skip_lower_file_name ) & & _jd - > file . open ( IO_ReadOnly ) )
{
_jd - > stream . setDevice ( & ( _jd - > file ) ) ;
createIgnorePCSFile ( ) ;
TQString sig ;
int pcs_version = 0 ;
_jd - > stream > > sig > > pcs_version ;
if ( sig = = " PCS " & & pcs_version = = KDEV_PCS_VERSION )
{
int numFiles = 0 ;
_jd - > stream > > numFiles ;
kdDebug ( 9007 ) < < " Read " < < numFiles < < " files from pcs " < < endl ;
for ( int i = 0 ; i < numFiles ; + + i )
{
TQString fn ;
uint ts ;
uint offset ;
_jd - > stream > > fn > > ts > > offset ;
_jd - > pcs [ fn ] = tqMakePair ( ts , offset ) ;
}
}
}
_jd - > files = reorder ( modifiedFileList ( ) ) ;
TQProgressBar * bar = new TQProgressBar ( _jd - > files . count ( ) , mainWindow ( ) - > statusBar ( ) ) ;
bar - > setMinimumWidth ( 120 ) ;
bar - > setCenterIndicator ( true ) ;
mainWindow ( ) - > statusBar ( ) - > addWidget ( bar ) ;
bar - > show ( ) ;
_jd - > progressBar = bar ;
_jd - > dir . setPath ( m_projectDirectory ) ;
_jd - > it = _jd - > files . begin ( ) ;
_jd - > reparseList = TQStringList ( ) ;
_jd - > backgroundCount = 0 ;
_jd - > cycle = 0 ;
TQTimer : : singleShot ( 0 , this , TQT_SLOT ( slotParseFiles ( ) ) ) ;
m_saveMemoryTimer - > stop ( ) ; //Do not regularly remove cached files that may still be needed while parsing(the cache anyway be full for the whole parsing-process)
return true ;
}
void CppSupportPart : : slotParseFiles ( )
{
// NOTE: The checking for m_projectClosed is actually (currently) not needed.
// When the project is closed, the language support plugin is destroyed
// and as a consequence, the timer job signal never arrives at this method
if ( ! _jd ) return ; // how can this possibly happen?!
if ( _jd - > cycle = = 0 & & ! m_projectClosed & & _jd - > it ! = _jd - > files . end ( ) )
{
_jd - > progressBar - > setProgress ( _jd - > progressBar - > progress ( ) + 1 ) ;
TQFileInfo fileInfo ( _jd - > dir , * ( _jd - > it ) ) ;
if ( fileInfo . exists ( ) & & fileInfo . isFile ( ) & & fileInfo . isReadable ( ) )
{
TQString absFilePath = URLUtil : : canonicalPath ( fileInfo . absFilePath ( ) ) ;
if ( isValidSource ( absFilePath ) )
{
TQDateTime t = fileInfo . lastModified ( ) ;
if ( ! ( m_timestamp . contains ( absFilePath ) & & m_timestamp [ absFilePath ] = = t ) )
{
if ( _jd - > pcs . contains ( absFilePath ) )
{
_jd - > stream . device ( ) - > at ( _jd - > pcs [ absFilePath ] . second ) ;
FileDom file = codeModel ( ) - > create < FileModel > ( ) ;
file - > read ( _jd - > stream ) ;
codeModel ( ) - > addFile ( file ) ;
if ( t . toTime_t ( ) ! = _jd - > pcs [ absFilePath ] . first ) {
///The FileDom had to be created first, so the dependencies are known
_jd - > reparseList < < file - > name ( ) ;
/* kdDebug( 9007 ) << "File timestamp: " << ": " << t.toTime_t() << endl;
kdDebug ( 9007 ) < < " Stored timestamp: " < < " : " < < _jd - > pcs [ absFilePath ] . first < < endl ; */
} else {
m_timestamp [ absFilePath ] = t ;
/* kdDebug( 9007 ) << "timestamp ok" << endl;*/
}
} else {
_jd - > reparseList < < absFilePath ;
/* kdDebug( 9007 ) << absFilePath << " put into reparse-list" << endl;
*/ }
} else {
/* kdDebug( 9007 ) << absFilePath << " is already in code-model" << endl;*/
}
}
}
+ + ( _jd - > it ) ;
TQTimer : : singleShot ( 0 , this , TQT_SLOT ( slotParseFiles ( ) ) ) ;
if ( _jd - > it = = _jd - > files . end ( ) ) {
if ( _jd - > reparseList . isEmpty ( ) ) {
_jd - > backgroundCount = 0 ;
} else {
if ( alwaysParseInBackground ) {
_jd - > backgroundCount = parseFilesAndDependencies ( _jd - > reparseList , true , false , true ) ;
} else {
_jd - > reparseList = reorder ( _jd - > reparseList ) ;
_jd - > it = _jd - > reparseList . begin ( ) ;
_jd - > backgroundCount = _jd - > reparseList . count ( ) ;
}
_jd - > progressBar - > setProgress ( 0 ) ; ///restart progress-bar for reparsing
_jd - > progressBar - > setTotalSteps ( _jd - > backgroundCount ) ;
}
_jd - > lastBackgroundState = - 1 ;
_jd - > backgroundState = 0 ;
_jd - > cycle = 1 ;
_jd - > lastParse = TQTime : : currentTime ( ) ;
kapp - > restoreOverrideCursor ( ) ;
}
}
else // finished or interrupted
{
if ( _jd - > backgroundCount < = _jd - > backgroundState | | m_projectClosed ) {
mainWindow ( ) - > statusBar ( ) - > removeWidget ( _jd - > progressBar ) ;
if ( ! m_projectClosed )
{
kdDebug ( 9007 ) < < " updating sourceinfo " < < endl ;
kapp - > restoreOverrideCursor ( ) ;
emit updatedSourceInfo ( ) ;
mainWindow ( ) - > statusBar ( ) - > message ( i18n ( " Done " ) , 2000 ) ;
TQFile : : remove ( project ( ) - > projectDirectory ( )
+ " / " + project ( ) - > projectName ( )
+ " .kdevelop.ignore_pcs " ) ;
TQFile : : remove ( project ( ) - > projectDirectory ( )
+ " / " + project ( ) - > projectName ( ) . lower ( )
+ " .kdevelop.ignore_pcs " ) ;
}
else
{
kdDebug ( 9007 ) < < " ABORT " < < endl ;
}
delete _jd ;
_jd = 0 ;
m_saveMemoryTimer - > start ( 240000 , false ) ;
} else {
_jd - > progressBar - > setProgress ( _jd - > backgroundState ) ; ///restart
_jd - > progressBar - > setTotalSteps ( _jd - > backgroundCount ) ;
if ( _jd - > lastParse . msecsTo ( TQTime : : currentTime ( ) ) > 60000 & & ! m_backgroundParser - > filesInQueue ( ) ) {
_jd - > backgroundCount = _jd - > backgroundState ; ///Stop waiting if there is no progress and no file in the background-parser
TQTimer : : singleShot ( 0 , this , TQT_SLOT ( slotParseFiles ( ) ) ) ;
} else {
int timeStep = 0 ;
if ( alwaysParseInBackground ) {
TQTimer : : singleShot ( 10 , this , TQT_SLOT ( slotParseFiles ( ) ) ) ;
} else {
if ( _jd - > it = = _jd - > reparseList . end ( ) ) {
/*_jd->it = _jd->files.end();
_jd - > backgroundCount = _jd - > backgroundState ; ///finish processing*/
timeStep = 1 ;
} else {
/*///Parse the files one by one
if ( _jd - > lastParse . msecsTo ( TQTime : : currentTime ( ) ) > 100 | | _jd - > backgroundState ! = _jd - > lastBackgroundState ) { */
maybeParse ( * _jd - > it , false ) ;
+ + ( _jd - > it ) ;
_jd - > lastBackgroundState = _jd - > backgroundState ;
/*}else{
timeStep = 1 ;
} */
}
TQTimer : : singleShot ( timeStep , this , TQT_SLOT ( slotParseFiles ( ) ) ) ;
}
}
}
}
}
void CppSupportPart : : maybeParse ( const TQString & fn , bool background )
{
if ( ! isValidSource ( fn ) )
return ;
TQFileInfo fileInfo ( fn ) ;
TQString path = URLUtil : : canonicalPath ( fn ) ;
TQDateTime t = fileInfo . lastModified ( ) ;
if ( ! fileInfo . exists ( ) )
return ;
TQMap < TQString , TQDateTime > : : Iterator it = m_timestamp . find ( path ) ;
if ( codeModel ( ) - > hasFile ( fn ) & & it ! = m_timestamp . end ( ) & & * it = = t )
return ;
TQStringList l ;
l < < fn ;
parseFilesAndDependencies ( l , background ) ;
}
bool CppSupportPart : : isQueued ( const TQString & file ) const {
//int c = m_backgroundParser->countInQueue( file );
//if( c == 0 ) return false;
return m_parseEmitWaiting . waiting ( file , ParseEmitWaiting : : Silent , 2 ) ; //Since it may be possible that the background-parser is currently parsing the file(in an obselete state), it is allowed to have the file in the queue twice.
}
void CppSupportPart : : slotNeedTextHint ( int line , int column , TQString & textHint )
{
if ( 1 | | ! m_activeEditor )
return ;
m_backgroundParser - > lock ( ) ;
TranslationUnitAST * ast = * m_backgroundParser - > translationUnit ( m_activeFileName ) ;
AST * node = 0 ;
if ( ast & & ( node = findNodeAt ( ast , line , column ) ) )
{
while ( node & & node - > nodeType ( ) ! = NodeType_FunctionDefinition )
node = node - > parent ( ) ;
if ( node )
{
int startLine , startColumn ;
int endLine , endColumn ;
node - > getStartPosition ( & startLine , & startColumn ) ;
node - > getEndPosition ( & endLine , & endColumn ) ;
if ( ! node - > text ( ) . isNull ( ) )
textHint = node - > text ( ) ;
else
textHint = m_activeEditor - > textLine ( startLine ) . simplifyWhiteSpace ( ) ;
}
}
m_backgroundParser - > unlock ( ) ;
}
void CppSupportPart : : MakeMemberHelper ( TQString & text , int & atLine , int & atColumn )
{
if ( ! m_activeViewCursor | | ! m_valid )
return ;
atLine = - 2 ;
atColumn = 0 ;
TQString implFile = findSourceFile ( ) ;
m_backgroundParser - > lock ( ) ;
TranslationUnitAST * translationUnit = * m_backgroundParser - > translationUnit ( m_activeFileName ) ;
if ( translationUnit )
{
bool fail = false ;
unsigned int line , column ;
m_activeViewCursor - > cursorPositionReal ( & line , & column ) ;
AST * currentNode = findNodeAt ( translationUnit , line , column ) ;
DeclaratorAST * declarator = 0 ;
while ( currentNode & & currentNode - > nodeType ( ) ! = NodeType_SimpleDeclaration )
{
if ( currentNode - > nodeType ( ) = = NodeType_Declarator )
declarator = ( DeclaratorAST * ) currentNode ;
currentNode = currentNode - > parent ( ) ;
}
SimpleDeclarationAST * decl = currentNode ? ( SimpleDeclarationAST * ) currentNode : 0 ;
if ( decl & & decl - > storageSpecifier ( ) & & decl - > storageSpecifier ( ) - > text ( ) . contains ( " friend " ) )
{
kdDebug ( 9007 ) < < " this is a friend declaration, don't create any definition " < < endl ;
fail = true ;
}
if ( ! fail & & decl & & decl - > initDeclaratorList ( ) & & ! declarator )
{
InitDeclaratorAST * i = decl - > initDeclaratorList ( ) - > initDeclaratorList ( ) . at ( 0 ) ;
if ( i )
declarator = i - > declarator ( ) ;
}
if ( ! fail & & decl & & declarator & & declarator - > parameterDeclarationClause ( ) )
{
TQStringList scope ;
scopeOfNode ( decl , scope ) ;
TQString scopeStr = scope . join ( " :: " ) ;
if ( ! scopeStr . isEmpty ( ) )
scopeStr + = " :: " ;
TQString declStr = declaratorToString ( declarator , scopeStr ) . simplifyWhiteSpace ( ) ;
if ( declarator - > exceptionSpecification ( ) )
{
declStr + = TQString : : fromLatin1 ( " throw( " ) ;
TQPtrList < AST > l = declarator - > exceptionSpecification ( ) - > nodeList ( ) ;
TQPtrListIterator < AST > type_it ( l ) ;
while ( type_it . current ( ) )
{
declStr + = type_it . current ( ) - > text ( ) ;
+ + type_it ;
if ( type_it . current ( ) )
declStr + = TQString : : fromLatin1 ( " , " ) ;
}
declStr + = TQString : : fromLatin1 ( " ) " ) ;
}
text + = " \n \n " ;
TQString type = typeSpecToString ( decl - > typeSpec ( ) ) ;
text + = type ;
if ( ! type . isNull ( ) )
text + = + " " ;
text + = declStr + " \n { \n } " ;
}
if ( ! fail )
{
translationUnit = * m_backgroundParser - > translationUnit ( implFile ) ;
if ( translationUnit )
translationUnit - > getEndPosition ( & atLine , & atColumn ) ;
}
kdDebug ( 9007 ) < < " at line in mm: " < < atLine < < endl ;
}
m_backgroundParser - > unlock ( ) ;
}
void CppSupportPart : : slotMakeMember ( )
{
TQString text ;
int atColumn , atLine ;
MakeMemberHelper ( text , atLine , atColumn ) ;
if ( ! text . isEmpty ( ) )
{
TQString implFile = findSourceFile ( ) ;
if ( ! implFile . isEmpty ( ) )
{
partController ( ) - > editDocument ( KURL ( implFile ) ) ;
kapp - > eventLoop ( ) - > processEvents ( TQEventLoop : : ExcludeUserInput | TQEventLoop : : ExcludeSocketNotifiers , 500 ) ;
}
if ( atLine = = - 2 )
atLine = m_activeEditor - > numLines ( ) - 1 ;
m_backgroundParser - > lock ( )
;
kdDebug ( 9007 ) < < " at line in mm: " < < atLine < < " atCol: " < < atColumn < < endl ;
kdDebug ( 9007 ) < < " text: " < < text < < endl ;
if ( m_activeEditor )
m_activeEditor - > insertText ( atLine , atColumn , text ) ;
if ( m_activeViewCursor )
m_activeViewCursor - > setCursorPositionReal ( atLine + 3 , 1 ) ;
m_backgroundParser - > unlock ( ) ;
}
}
TQStringList CppSupportPart : : subclassWidget ( const TQString & formName )
{
TQStringList newFileNames ;
SubclassingDlg * dlg = new SubclassingDlg ( this , formName , newFileNames ) ;
dlg - > exec ( ) ;
return newFileNames ;
}
TQStringList CppSupportPart : : updateWidget ( const TQString & formName , const TQString & fileName )
{
TQStringList dummy ;
SubclassingDlg * dlg = new SubclassingDlg ( this , formName , fileName , dummy ) ;
dlg - > exec ( ) ;
return dummy ;
}
void CppSupportPart : : partRemoved ( KParts : : Part * part )
{
kdDebug ( 9032 ) < < " CppSupportPart::partRemoved() " < < endl ;
if ( KTextEditor : : Document * doc = dynamic_cast < KTextEditor : : Document * > ( part ) )
{
TQString fileName = doc - > url ( ) . path ( ) ;
if ( ! isValidSource ( fileName ) )
return ;
TQString canonicalFileName = URLUtil : : canonicalPath ( fileName ) ;
m_backgroundParser - > removeFile ( canonicalFileName ) ;
m_backgroundParser - > addFile ( canonicalFileName , true ) ;
}
}
void CppSupportPart : : slotProjectCompiled ( )
{
kdDebug ( 9007 ) < < " CppSupportPart::slotProjectCompiled() " < < endl ;
parseProject ( ) ;
}
TQStringList CppSupportPart : : modifiedFileList ( )
{
TQStringList lst ;
TQStringList fileList = m_projectFileList ;
TQStringList : : Iterator it = fileList . begin ( ) ;
while ( it ! = fileList . end ( ) )
{
TQString fileName = * it ;
+ + it ;
TQFileInfo fileInfo ( m_projectDirectory , fileName ) ;
TQString path = URLUtil : : canonicalPath ( fileInfo . absFilePath ( ) ) ;
if ( ! ( isSource ( path ) | | isHeader ( path ) ) )
continue ;
TQDateTime t = fileInfo . lastModified ( ) ;
TQMap < TQString , TQDateTime > : : Iterator dictIt = m_timestamp . find ( path ) ;
if ( fileInfo . exists ( ) & & dictIt ! = m_timestamp . end ( ) & & * dictIt = = t )
continue ;
lst < < fileName ;
}
return lst ;
}
KTextEditor : : Document * CppSupportPart : : findDocument ( const KURL & url )
{
if ( ! partController ( ) - > parts ( ) )
return 0 ;
TQPtrList < KParts : : Part > parts ( * partController ( ) - > parts ( ) ) ;
TQPtrListIterator < KParts : : Part > it ( parts ) ;
while ( KParts : : Part * part = it . current ( ) )
{
KTextEditor : : Document * doc = dynamic_cast < KTextEditor : : Document * > ( part ) ;
if ( doc & & doc - > url ( ) = = url )
return doc ;
+ + it ;
}
return 0 ;
}
void CppSupportPart : : setupCatalog ( )
{
kdDebug ( 9007 ) < < " CppSupportPart::setupCatalog() " < < endl ;
TDEStandardDirs * dirs = CppSupportFactory : : instance ( ) - > dirs ( ) ;
TQStringList pcsList = dirs - > findAllResources ( " pcs " , " *.db " , false , true ) ;
TQStringList pcsIdxList = dirs - > findAllResources ( " pcs " , " *.idx " , false , true ) ;
TQStringList enabledPCSs ;
if ( DomUtil : : elementByPath ( * project ( ) - > projectDom ( ) , " kdevcppsupport/references " ) . isNull ( ) )
{
for ( TQStringList : : Iterator it = pcsList . begin ( ) ; it ! = pcsList . end ( ) ; + + it )
{
kdDebug ( 9007 ) < < " CppSupportPart::setupCatalog()1 " < < * it < < endl ;
enabledPCSs . push_back ( TQFileInfo ( * it ) . baseName ( true ) ) ;
}
}
else
{
enabledPCSs = DomUtil : : readListEntry ( * project ( ) - > projectDom ( ) , " kdevcppsupport/references " , " pcs " ) ;
}
TQStringList indexList = TQStringList ( ) < < " kind " < < " name " < < " scope " < < " fileName " < < " prefix " ;
if ( pcsList . size ( ) & & pcsVersion ( ) < KDEV_DB_VERSION )
{
TQStringList l = pcsList + pcsIdxList ;
int rtn = KMessageBox : : questionYesNoList ( 0 , i18n ( " Persistent class store will be disabled: you have a wrong version of pcs installed. \n Remove old pcs files? " ) , l , i18n ( " C++ Support " ) , KStdGuiItem : : del ( ) , KStdGuiItem : : cancel ( ) ) ;
if ( rtn = = KMessageBox : : Yes )
{
TQStringList : : Iterator it = l . begin ( ) ;
while ( it ! = l . end ( ) )
{
TQFile : : remove
( * it ) ;
+ + it ;
}
// @todo regenerate the pcs list
pcsList . clear ( ) ;
}
else
{
return ;
}
}
TQStringList : : Iterator it = pcsList . begin ( ) ;
while ( it ! = pcsList . end ( ) )
{
kdDebug ( 9007 ) < < " CppSupportPart::setupCatalog()2 " < < * it < < endl ;
Catalog * catalog = new Catalog ( ) ;
catalog - > open ( * it ) ;
catalog - > setEnabled ( enabledPCSs . contains ( TQFileInfo ( * it ) . baseName ( true ) ) ) ;
+ + it ;
for ( TQStringList : : Iterator idxIt = indexList . begin ( ) ; idxIt ! = indexList . end ( ) ; + + idxIt )
catalog - > addIndex ( ( * idxIt ) . utf8 ( ) ) ;
m_catalogList . append ( catalog ) ;
codeRepository ( ) - > registerCatalog ( catalog ) ;
}
setPcsVersion ( KDEV_DB_VERSION ) ;
}
KMimeType : : List CppSupportPart : : mimeTypes ( )
{
TQStringList mimeList ;
mimeList + = m_headerMimeTypes ;
mimeList + = m_sourceMimeTypes ;
KMimeType : : List list ;
for ( TQStringList : : Iterator it = mimeList . begin ( ) ; it ! = mimeList . end ( ) ; + + it )
{
if ( KMimeType : : Ptr mime = KMimeType : : mimeType ( * it ) )
list < < mime ;
}
return list ;
}
int CppSupportPart : : pcsVersion ( )
{
TDEConfig * config = CppSupportFactory : : instance ( ) - > config ( ) ;
TDEConfigGroupSaver cgs ( config , " PCS " ) ;
return config - > readNumEntry ( " Version " , 0 ) ;
}
void CppSupportPart : : setPcsVersion ( int version )
{
TDEConfig * config = CppSupportFactory : : instance ( ) - > config ( ) ;
TDEConfigGroupSaver cgs ( config , " PCS " ) ;
config - > writeEntry ( " Version " , version ) ;
config - > sync ( ) ;
}
TQString CppSupportPart : : formatTag ( const Tag & inputTag )
{
Tag tag = inputTag ;
switch ( tag . kind ( ) )
{
case Tag : : Kind_Namespace :
return TQString : : fromLatin1 ( " namespace " ) + tag . name ( ) ;
case Tag : : Kind_Class :
return TQString : : fromLatin1 ( " class " ) + tag . name ( ) ;
case Tag : : Kind_Function :
case Tag : : Kind_FunctionDeclaration :
{
CppFunction < Tag > tagInfo ( tag ) ;
return tagInfo . name ( ) + " ( " + tagInfo . arguments ( ) . join ( " , " ) + " ) : " + tagInfo . type ( ) ;
}
break ;
case Tag : : Kind_Variable :
case Tag : : Kind_VariableDeclaration :
{
CppVariable < Tag > tagInfo ( tag ) ;
return tagInfo . name ( ) + " : " + tagInfo . type ( ) ;
}
break ;
}
return tag . name ( ) ;
}
void CppSupportPart : : codeCompletionConfigStored ( )
{
if ( m_projectClosing ) return ;
updateParserConfiguration ( ) ;
/*
m_backgroundParser - > updateParserConfiguration ( ) ;
KDevDriver * d = dynamic_cast < KDevDriver * > ( m_driver ) ; //The foreground-parse isn't used anymore, and could be removed
if ( d ) {
d - > setup ( ) ;
d - > makeMacrosPersistent ( ) ;
} */
partController ( ) - > setActivePart ( partController ( ) - > activePart ( ) ) ;
}
void CppSupportPart : : splitHeaderSourceConfigStored ( )
{
TQString o = splitHeaderSourceConfig ( ) - > orientation ( ) ;
if ( o = = " Vertical " )
emit splitOrientationChanged ( Qt : : Vertical ) ;
else if ( o = = " Horizontal " )
emit splitOrientationChanged ( Qt : : Horizontal ) ;
}
void CppSupportPart : : removeWithReferences ( const TQString & fileName )
{
kdDebug ( 9007 ) < < " remove with references: " < < fileName < < endl ;
m_timestamp . remove ( fileName ) ;
if ( ! codeModel ( ) - > hasFile ( fileName ) )
return ;
emit aboutToRemoveSourceInfo ( fileName ) ;
codeModel ( ) - > removeFile ( codeModel ( ) - > fileByName ( fileName ) ) ;
}
bool CppSupportPart : : isValidSource ( const TQString & fileName ) const
{
TQFileInfo fileInfo ( fileName ) ;
TQString path = URLUtil : : canonicalPath ( fileInfo . absFilePath ( ) ) ;
return /*project() && project() ->isProjectFile( path )
& & */ ( isSource ( path ) | | isHeader ( path ) )
& & ! TQFile : : exists ( fileInfo . dirPath ( true ) + " /.tdev_ignore " ) ;
}
TQString CppSupportPart : : formatModelItem ( const CodeModelItem * item , bool shortDescription )
{
if ( item - > isFunction ( ) | | item - > isFunctionDefinition ( ) )
{
const FunctionModel * model = static_cast < const FunctionModel * > ( item ) ;
TQString function ;
TQString args ;
ArgumentList argumentList = model - > argumentList ( ) ;
for ( ArgumentList : : const_iterator it = argumentList . begin ( ) ; it ! = argumentList . end ( ) ; + + it )
{
args . isEmpty ( ) ? args + = " " : args + = " , " ;
args + = formatModelItem ( ( * it ) . data ( ) ) ;
}
if ( ! shortDescription )
function + = ( model - > isVirtual ( ) ? TQString ( " virtual " ) : TQString ( " " ) ) + model - > resultType ( ) + " " ;
function + = model - > name ( ) + " ( " + args + " ) " + ( model - > isConstant ( ) ? TQString ( " const " ) : TQString ( " " ) ) +
( model - > isAbstract ( ) ? TQString ( " = 0 " ) : TQString ( " " ) ) ;
return function ;
}
else if ( item - > isVariable ( ) )
{
const VariableModel * model = static_cast < const VariableModel * > ( item ) ;
if ( shortDescription )
return model - > name ( ) ;
return model - > type ( ) + " " + model - > name ( ) ;
}
else if ( item - > isArgument ( ) )
{
const ArgumentModel * model = static_cast < const ArgumentModel * > ( item ) ;
TQString arg ;
if ( ! shortDescription )
arg + = model - > type ( ) + " " ;
arg + = model - > name ( ) ;
if ( ! shortDescription )
arg + = model - > defaultValue ( ) . isEmpty ( ) ? TQString ( " " ) : TQString ( " = " ) + model - > defaultValue ( ) ;
return arg . stripWhiteSpace ( ) ;
}
else
return KDevLanguageSupport : : formatModelItem ( item , shortDescription ) ;
}
void CppSupportPart : : addClass ( )
{
slotNewClass ( ) ;
}
void CppSupportPart : : saveProjectSourceInfo ( )
{
const FileList fileList = codeModel ( ) - > fileList ( ) ;
if ( ! project ( ) | | fileList . isEmpty ( ) )
return ;
TQFile f ( project ( ) - > projectDirectory ( ) + " / "
+ project ( ) - > projectName ( ) + " .kdevelop.pcs " ) ;
if ( ! f . open ( IO_WriteOnly ) )
return ;
m_backgroundParser - > lock ( ) ;
createIgnorePCSFile ( ) ;
TQDataStream stream ( & f ) ;
TQMap < TQString , uint > offsets ;
TQString pcs ( " PCS " ) ;
stream < < pcs < < KDEV_PCS_VERSION ;
stream < < int ( fileList . size ( ) ) ;
for ( FileList : : ConstIterator it = fileList . begin ( ) ; it ! = fileList . end ( ) ; + + it )
{
const FileDom dom = ( * it ) ;
stream < < dom - > name ( ) < < m_timestamp [ dom - > name ( ) ] . toTime_t ( ) ;
if ( m_timestamp . find ( dom - > name ( ) ) = = m_timestamp . end ( ) ) {
kdDebug ( 9007 ) < < dom - > name ( ) < < " : timestamp is missing " < < endl ;
}
offsets . insert ( dom - > name ( ) , stream . device ( ) - > at ( ) ) ;
stream < < ( uint ) 0 ; // dummy offset
}
for ( FileList : : ConstIterator it = fileList . begin ( ) ; it ! = fileList . end ( ) ; + + it )
{
const FileDom dom = ( * it ) ;
int offset = stream . device ( ) - > at ( ) ;
dom - > write ( stream ) ;
int end = stream . device ( ) - > at ( ) ;
stream . device ( ) - > at ( offsets [ dom - > name ( ) ] ) ;
stream < < offset ;
stream . device ( ) - > at ( end ) ;
}
TQFile : : remove ( project ( ) - > projectDirectory ( ) + " / "
+ project ( ) - > projectName ( ) + " .kdevelop.ignore_pcs " ) ;
TQFile : : remove ( project ( ) - > projectDirectory ( ) + " / "
+ project ( ) - > projectName ( ) . lower ( ) + " .kdevelop.ignore_pcs " ) ;
m_backgroundParser - > unlock ( ) ;
}
TQString CppSupportPart : : extractInterface ( const ClassDom & klass )
{
TQString txt ;
TQTextStream stream ( & txt , IO_WriteOnly ) ;
TQString name = klass - > name ( ) + " Interface " ;
TQString ind ;
ind . fill ( TQChar ( ' ' ) , 4 ) ;
stream
< < " class " < < name < < " \n "
< < " { " < < " \n "
< < " public: " < < " \n "
< < ind < < name < < " () {} " < < " \n "
< < ind < < " virtual ~ " < < name < < " () {} " < < " \n "
< < " \n " ;
const FunctionList functionList = klass - > functionList ( ) ;
for ( FunctionList : : ConstIterator it = functionList . begin ( ) ; it ! = functionList . end ( ) ; + + it )
{
const FunctionDom & fun = * it ;
if ( ! fun - > isVirtual ( ) | | fun - > name ( ) . startsWith ( " ~ " ) )
continue ;
stream < < ind < < formatModelItem ( fun ) ;
if ( ! fun - > isAbstract ( ) )
stream < < " = 0 " ;
stream < < " ; \n " ;
}
stream
< < " \n "
< < " private: " < < " \n "
< < ind < < name < < " ( const " < < name < < " & source ); " < < " \n "
< < ind < < " void operator = ( const " < < name < < " & source ); " < < " \n "
< < " }; " < < " \n \n " ;
return txt ;
}
void CppSupportPart : : slotExtractInterface ( )
{
if ( ! m_activeClass )
return ;
TQFileInfo fileInfo ( m_activeClass - > fileName ( ) ) ;
TQString ifaceFileName = fileInfo . dirPath ( true ) + " / " + m_activeClass - > name ( ) . lower ( ) + " _interface.h " ;
if ( TQFile : : exists ( ifaceFileName ) )
{
KMessageBox : : error ( mainWindow ( ) - > main ( ) , i18n ( " File %1 already exists " ) . arg ( ifaceFileName ) ,
i18n ( " C++ Support " ) ) ;
}
else
{
TQString text = extractInterface ( m_activeClass ) ;
TQFile f ( ifaceFileName ) ;
if ( f . open ( IO_WriteOnly ) )
{
TQTextStream stream ( & f ) ;
stream
< < " #ifndef __ " < < m_activeClass - > name ( ) . upper ( ) < < " _INTERFACE_H " < < " \n "
< < " #define __ " < < m_activeClass - > name ( ) . upper ( ) < < " _INTERFACE_H " < < " \n "
< < " \n "
< < extractInterface ( m_activeClass )
< < " \n "
< < " #endif // __ " < < m_activeClass - > name ( ) . upper ( ) < < " _INTERFACE_H " < < " \n " ;
f . close ( ) ;
project ( ) - > addFile ( ifaceFileName ) ;
}
}
m_activeClass = 0 ;
}
void CppSupportPart : : gotoLine ( int line )
{
if ( isHeader ( m_activeFileName ) )
{
KURL url ;
url . setPath ( sourceOrHeaderCandidate ( ) ) ;
partController ( ) - > editDocument ( url , line ) ;
}
else
m_activeViewCursor - > setCursorPositionReal ( line , 0 ) ;
}
FileDom CppSupportPart : : fileByName ( const TQString & name ) {
return codeModel ( ) - > fileByName ( name ) ;
}
int CppSupportPart : : parseFilesAndDependencies ( TQStringList files , bool background , bool parseFirst , bool silent ) {
TQMap < TQString , int > fileGroups ;
int nextGroup = 0 ;
for ( TQStringList : : iterator it = files . begin ( ) ; it ! = files . end ( ) ; + + it ) {
FileDom d = fileByName ( * it ) ;
TQStringList lst ;
if ( ! d ) {
lst < < * it ;
} else {
lst = codeModel ( ) - > getGroupStrings ( d - > groupId ( ) ) ;
/* kdDebug( 9007 ) << "adding group of: " << *it << ":\n" << " which is " << lst.join("\n") << "\n\n";*/
if ( lst . count ( ) > 10 ) {
lst = codeModel ( ) - > getGroupStrings ( d - > groupId ( ) ) ;
}
}
int cgroup = nextGroup ;
nextGroup + + ;
if ( fileGroups . find ( * it ) ! = fileGroups . end ( ) )
cgroup = fileGroups [ * it ] ;
for ( TQStringList : : iterator lit = lst . begin ( ) ; lit ! = lst . end ( ) ; + + lit )
fileGroups [ * lit ] = cgroup ;
}
TQValueVector < TQStringList > groups ;
groups . resize ( nextGroup ) ;
///put the groups together
for ( TQMap < TQString , int > : : iterator it = fileGroups . begin ( ) ; it ! = fileGroups . end ( ) ; + + it ) {
groups [ * it ] < < it . key ( ) ;
}
for ( int a = 0 ; a < nextGroup ; a + + ) {
TQStringList group = reorder ( groups [ a ] ) ;
/* kdDebug( 9007 ) << "reparsing the following group: " << ":\n" << group.join("\n") << "\n\n";*/
if ( background ) {
m_backgroundParser - > lock ( ) ;
if ( ! group . isEmpty ( ) ) {
if ( ! parseFirst )
m_parseEmitWaiting . addGroup ( group , silent ? ParseEmitWaiting : : Silent : ParseEmitWaiting : : None ) ;
else
m_parseEmitWaiting . addGroupFront ( group , silent ? ParseEmitWaiting : : Silent : ParseEmitWaiting : : None ) ;
if ( ! silent ) {
if ( ! parseFirst )
m_fileParsedEmitWaiting . addGroup ( group , silent ? ParseEmitWaiting : : Silent : ParseEmitWaiting : : None ) ;
else
m_fileParsedEmitWaiting . addGroupFront ( group , silent ? ParseEmitWaiting : : Silent : ParseEmitWaiting : : None ) ;
}
}
if ( parseFirst & & ! group . empty ( ) ) {
for ( TQStringList : : iterator it = - - group . end ( ) ; it ! = group . end ( ) ; ) {
backgroundParser ( ) - > addFileFront ( * it ) ;
if ( it = = group . begin ( ) ) {
it = group . end ( ) ;
} else {
- - it ;
}
}
} else {
for ( TQStringList : : iterator it = group . begin ( ) ; it ! = group . end ( ) ; + + it ) {
backgroundParser ( ) - > addFile ( * it ) ;
}
}
m_backgroundParser - > unlock ( ) ;
} else {
for ( TQStringList : : iterator it = group . begin ( ) ; it ! = group . end ( ) ; + + it ) {
m_driver - > parseFile ( * it ) ;
}
}
}
return fileGroups . count ( ) ;
}
int CppSupportPart : : parseFileAndDependencies ( const TQString & fileName , bool background , bool parseFirst , bool silent ) {
if ( ! isValidSource ( fileName ) ) return 0 ;
// kdDebug( 9007 ) << "reparsing dependencies of " << fileName << "\n";
return parseFilesAndDependencies ( fileName , background , parseFirst , silent ) ;
}
void CppSupportPart : : parseEmit ( ParseEmitWaiting : : Processed files ) {
if ( files . res . isEmpty ( ) ) return ;
bool modelHasFiles = true ;
for ( TQStringList : : iterator it = files . res . begin ( ) ; it ! = files . res . end ( ) ; + + it ) {
if ( ! codeModel ( ) - > hasFile ( * it ) ) modelHasFiles = false ;
}
int oldFileCount = codeModel ( ) - > fileList ( ) . count ( ) ;
if ( ( files . flag & ParseEmitWaiting : : HadErrors ) & & modelHasFiles & & ! files . hasFlag ( ParseEmitWaiting : : Silent ) ) {
mainWindow ( ) - > statusBar ( ) - > message ( " File parsed, but not updating code-model because of errors " , 2000 ) ;
kdDebug ( 9007 ) < < " not updating code-model because at least one file has errors " < < endl ;
// for( TQStringList::iterator it = files.res.begin(); it != files.res.end(); ++it )
// m_backgroundParser->removeFile( *it );
} else {
///update timestamps
for ( TQStringList : : iterator it = files . res . begin ( ) ; it ! = files . res . end ( ) ; + + it ) {
if ( ! codeModel ( ) - > hasFile ( * it ) ) modelHasFiles = false ;
TQString & fileName = * it ;
TQFileInfo fileInfo ( fileName ) ;
TQString path = URLUtil : : canonicalPath ( fileName ) ;
if ( ! fileInfo . exists ( ) ) {
removeWithReferences ( path ) ;
continue ;
}
m_timestamp [ path ] = fileInfo . lastModified ( ) ;
}
if ( files . hasFlag ( ParseEmitWaiting : : Silent ) & & ! alwaysParseInBackground )
return ;
m_backgroundParser - > lock ( ) ;
TQStringList l = files . res ;
TQMap < TQString , bool > wholeResult ;
TQStringList missing ;
TQMap < TQString , FileDom > newFiles ;
while ( ! l . isEmpty ( ) ) {
TQString fileName = l . front ( ) ;
if ( ! m_backgroundParser - > hasTranslationUnit ( fileName ) ) {
kdDebug ( 9007 ) < < " error: translation-unit is missing: " < < fileName < < endl ;
missing < < fileName ;
} else {
if ( ParsedFilePointer ast = m_backgroundParser - > translationUnit ( fileName ) )
{
if ( true /*!hasErrors*/ )
{
FileDom oldFile = codeModel ( ) - > fileByName ( fileName ) ;
StoreWalker walker ( fileName , codeModel ( ) ) ;
walker . setOverrides ( newFiles ) ;
walker . parseTranslationUnit ( * ast ) ;
if ( oldFile ) {
newFiles [ fileName ] = walker . file ( ) ;
///update timestamps
TQFileInfo fileInfo ( fileName ) ;
TQString path = URLUtil : : canonicalPath ( fileName ) ;
m_timestamp [ path ] = fileInfo . lastModified ( ) ;
} else {
codeModel ( ) - > addFile ( walker . file ( ) ) ;
}
if ( walker . file ( ) ) {
TQStringList grp = walker . file ( ) - > wholeGroupStrings ( ) ;
for ( TQStringList : : const_iterator it = grp . begin ( ) ; it ! = grp . end ( ) ; + + it )
wholeResult [ * it ] = true ;
}
}
} else {
kdDebug ( 9007 ) < < " failed to parse " < < fileName < < endl ;
}
}
l . pop_front ( ) ;
}
bool canUpdate = true ;
for ( TQMap < TQString , FileDom > : : const_iterator it = newFiles . begin ( ) ; it ! = newFiles . end ( ) ; + + it ) {
FileDom oldFile = codeModel ( ) - > fileByName ( it . key ( ) ) ;
if ( ! oldFile | | ! oldFile - > canUpdate ( * it ) ) {
canUpdate = false ;
break ;
}
}
if ( canUpdate ) {
///Update the code-model
for ( TQMap < TQString , FileDom > : : const_iterator it = newFiles . begin ( ) ; it ! = newFiles . end ( ) ; + + it ) {
FileDom oldFile = codeModel ( ) - > fileByName ( it . key ( ) ) ;
oldFile - > update ( * it ) ;
codeModel ( ) - > mergeGroups ( oldFile - > groupId ( ) , ( * it ) - > groupId ( ) ) ; ///Merge parsing-groups together
}
} else {
///Remove the current files and replace them with the new ones
for ( TQMap < TQString , FileDom > : : const_iterator it = newFiles . begin ( ) ; it ! = newFiles . end ( ) ; + + it ) {
removeWithReferences ( it . key ( ) ) ;
codeModel ( ) - > addFile ( * it ) ;
}
}
/*
///make the list unique
l . clear ( ) ;
for ( TQMap < TQString , bool > : : const_iterator it = wholeResult . begin ( ) ; it ! = wholeResult . end ( ) ; + + it )
l < < it . key ( ) ; */
m_backgroundParser - > unlock ( ) ;
if ( ! missing . isEmpty ( ) ) {
kdDebug ( 9007 ) < < " error: translation-units were missing: " < < missing < < endl ;
//don't reparse missing units, because it may cause the whole project to be reparsed
// parseFilesAndDependencies( missing, true, false, files.hasFlag( ParseEmitWaiting::Silent ) );
}
if ( files . hasFlag ( ParseEmitWaiting : : Silent ) ) {
if ( alwaysParseInBackground )
for ( TQStringList : : iterator it = files . res . begin ( ) ; it ! = files . res . end ( ) ; + + it )
m_backgroundParser - > removeFile ( * it ) ;
} else {
if ( ! canUpdate ) { ///If the current model could be updated, do not emit addedSourceInfo(..) and remove the units from the parser, because nobody will be using them
TQStringList l = files . res ;
while ( ! l . isEmpty ( ) ) {
emit aboutToRemoveSourceInfo ( l . front ( ) ) ;
emit removedSourceInfo ( l . front ( ) ) ;
emit addedSourceInfo ( l . front ( ) ) ;
l . pop_front ( ) ;
}
if ( ! files . hasFlag ( ParseEmitWaiting : : Silent ) )
emitFileParsed ( files ) ;
} else {
TQStringList l = files . res ;
while ( ! l . isEmpty ( ) ) {
emit codeModelUpdated ( l . front ( ) ) ;
emit aboutToRemoveSourceInfo ( l . front ( ) ) ;
emit removedSourceInfo ( l . front ( ) ) ;
emit addedSourceInfo ( l . front ( ) ) ;
l . pop_front ( ) ;
}
}
}
kdDebug ( 9007 ) < < " files in code-model after parseEmit: " < < codeModel ( ) - > fileList ( ) . count ( ) < < " before: " < < oldFileCount < < endl ;
}
}
/*void CppSupportPart::recomputeCodeModel( const TQString& fileName )
{ */
//}
void CppSupportPart : : emitSynchronousParseReady ( const TQString & file , ParsedFilePointer unit ) {
emit synchronousParseReady ( file , unit ) ;
}
void CppSupportPart : : emitFileParsed ( TQStringList l )
{
while ( ! l . isEmpty ( ) ) {
emit fileParsed ( l . front ( ) ) ;
l . pop_front ( ) ;
}
}
bool CppSupportPart : : isHeader ( const TQString & fileName ) const
{
/*KMimeType::Ptr ptr = KMimeType::findByPath( fileName );
if ( ptr & & m_headerMimeTypes . contains ( ptr - > name ( ) ) )
return true ; */
return ( m_headerExtensions . findIndex ( TQFileInfo ( fileName ) . extension ( ) ) ! = - 1 ) ;
}
bool CppSupportPart : : isSource ( const TQString & fileName ) const
{
/*KMimeType::Ptr ptr = KMimeType::findByPath( fileName );
if ( ptr & & m_sourceMimeTypes . contains ( ptr - > name ( ) ) )
return true ; */
return ( m_sourceExtensions . findIndex ( TQFileInfo ( fileName ) . extension ( ) ) ! = - 1 ) ;
}
void CppSupportPart : : gotoDeclarationLine ( int line )
{
if ( isHeader ( m_activeFileName ) )
m_activeViewCursor - > setCursorPositionReal ( line , 0 ) ;
else
{
KURL url ;
url . setPath ( sourceOrHeaderCandidate ( ) ) ;
partController ( ) - > editDocument ( url , line ) ;
}
}
void CppSupportPart : : removeCatalog ( const TQString & dbName )
{
if ( ! TQFile : : exists ( dbName ) )
return ;
TQValueList < Catalog * > catalogs = codeRepository ( ) - > registeredCatalogs ( ) ;
Catalog * c = 0 ;
for ( TQValueList < Catalog * > : : Iterator it = catalogs . begin ( ) ; it ! = catalogs . end ( ) ; + + it )
{
if ( ( * it ) - > dbName ( ) = = dbName )
{
c = * it ;
break ;
}
}
if ( c )
{
codeRepository ( ) - > unregisterCatalog ( c ) ;
m_catalogList . remove ( c ) ;
}
TQFileInfo fileInfo ( dbName ) ;
TQDir dir ( fileInfo . dir ( true ) ) ;
TQStringList indexList = TQStringList ( ) < < " kind " < < " name " < < " scope " < < " fileName " < < " prefix " ;
for ( TQStringList : : Iterator iter = indexList . begin ( ) ; iter ! = indexList . end ( ) ; iter + + )
{
TQStringList fileList = dir . entryList ( fileInfo . baseName ( true ) + " . " + ( * iter ) + " .idx " ) ;
for ( TQStringList : : Iterator it = fileList . begin ( ) ; it ! = fileList . end ( ) ; + + it )
{
TQString idxName = fileInfo . dirPath ( true ) + " / " + * it ;
kdDebug ( 9007 ) < < " =========> remove db index: " < < idxName < < endl ;
dir . remove ( * it ) ;
}
}
dir . remove ( fileInfo . fileName ( ) ) ;
}
void CppSupportPart : : addCatalog ( Catalog * catalog )
{
m_catalogList . append ( catalog ) ;
codeRepository ( ) - > registerCatalog ( catalog ) ;
}
FunctionDefinitionDom CppSupportPart : : functionDefinitionAt ( int line , int column )
{
if ( ! codeModel ( ) - > hasFile ( m_activeFileName ) )
return FunctionDefinitionDom ( ) ;
CodeModelUtils : : CodeModelHelper h ( codeModel ( ) , codeModel ( ) - > fileByName ( m_activeFileName ) ) ;
FunctionDom d = h . functionAt ( line , column , CodeModelUtils : : CodeModelHelper : : Definition ) ;
if ( d ) {
FunctionDefinitionModel * m = dynamic_cast < FunctionDefinitionModel * > ( d . data ( ) ) ;
if ( m ) return FunctionDefinitionDom ( m ) ;
}
return FunctionDefinitionDom ( ) ;
}
FunctionDefinitionDom CppSupportPart : : currentFunctionDefinition ( )
{
if ( ! this - > m_activeViewCursor )
return FunctionDefinitionDom ( ) ;
unsigned int line , column ;
this - > m_activeViewCursor - > cursorPositionReal ( & line , & column ) ;
return functionDefinitionAt ( line , column ) ;
}
void CppSupportPart : : slotCursorPositionChanged ( )
{
if ( codeCompletion ( ) )
{
unsigned int line = 0 ;
unsigned int column = 0 ;
if ( KDevEditorUtil : : currentPositionReal ( & line , & column , dynamic_cast < KTextEditor : : Document * > ( partController ( ) - > activePart ( ) ) ) )
{
TQString typeInfoString = codeCompletion ( ) - > createTypeInfoString ( line , column ) ;
mainWindow ( ) - > statusBar ( ) - > message ( typeInfoString ) ;
}
}
// m_functionHintTimer->changeInterval( 1000 );
if ( splitHeaderSourceConfig ( ) - > splitEnabled ( )
& & splitHeaderSourceConfig ( ) - > autoSync ( ) )
slotSwitchHeader ( true ) ;
}
/*
void CppSupportPart : : slotFunctionHint ( )
{
kdDebug ( 9007 ) < < " =======> compute current function definition " < < endl ;
// m_functionHintTimer->stop();
if ( FunctionDefinitionDom fun = currentFunctionDefinition ( ) )
{
TQStringList scope = fun - > scope ( ) ;
TQString funName = scope . join ( " :: " ) ;
if ( ! funName . isEmpty ( ) )
funName + = " :: " ;
funName + = formatModelItem ( fun , true ) ;
mainWindow ( ) - > statusBar ( ) - > message ( funName , 2000 ) ;
}
}
*/
void CppSupportPart : : createIgnorePCSFile ( )
{
static TQCString skip_me ( " ignore me \n " ) ;
TQString skip_file_name = project ( ) - > projectDirectory ( ) + " / "
+ project ( ) - > projectName ( ) + " .kdevelop.ignore_pcs " ;
TQFile skip_pcs_file ( skip_file_name ) ;
if ( skip_pcs_file . open ( IO_WriteOnly ) )
{
skip_pcs_file . writeBlock ( skip_me ) ;
skip_pcs_file . close ( ) ;
}
}
TQString CppSupportPart : : specialHeaderName ( bool local ) const
{
if ( local )
return : : locateLocal ( " data " , " kdevcppsupport/configuration " , CppSupportFactory : : instance ( ) ) ;
return : : locate ( " data " , " kdevcppsupport/configuration " , CppSupportFactory : : instance ( ) ) ;
}
void CppSupportPart : : updateParserConfiguration ( )
{
m_backgroundParser - > updateParserConfiguration ( ) ;
TQString conf_file_name = specialHeaderName ( ) ;
m_driver - > removeAllMacrosInFile ( conf_file_name ) ;
dynamic_cast < KDevDriver * > ( m_driver ) - > setup ( ) ;
m_driver - > parseFile ( conf_file_name , true , true , true ) ;
m_buildSafeFileSetTimer - > start ( 500 , true ) ;
parseProject ( true ) ;
}
const Driver * CppSupportPart : : driver ( ) const {
return m_driver ;
}
Driver * CppSupportPart : : driver ( ) {
return m_driver ;
}
KDevDesignerIntegration * CppSupportPart : : designer ( KInterfaceDesigner : : DesignerType type )
{
KDevDesignerIntegration * des = 0 ;
switch ( type )
{
case KInterfaceDesigner : : Glade :
case KInterfaceDesigner : : TQtDesigner :
des = m_designers [ type ] ;
if ( des = = 0 )
{
CppImplementationWidget * impl = new CppImplementationWidget ( this ) ;
des = new QtDesignerCppIntegration ( this , impl ) ;
des - > loadSettings ( * project ( ) - > projectDom ( ) , " kdevcppsupport/designerintegration " ) ;
m_designers [ type ] = des ;
}
break ;
}
return des ;
}
void CppSupportPart : : resetParserStoreTimer ( ) {
// m_deleteParserStoreTimer->start(10000); ///try to empty the store regularly
}
void CppSupportPart : : slotDeleteParserStore ( ) {
/* if( !m_backgroundParser->filesInQueue() )
m_backgroundParser - > removeAllFiles ( ) ;
else
resetParserStoreTimer ( ) ; */
}
void CppSupportPart : : slotCreateSubclass ( )
{
TQFileInfo fi ( m_contextFileName ) ;
if ( fi . extension ( false ) ! = " ui " )
return ;
QtDesignerCppIntegration * des = dynamic_cast < QtDesignerCppIntegration * > ( designer ( KInterfaceDesigner : : TQtDesigner ) ) ;
if ( des )
des - > selectImplementation ( m_contextFileName ) ;
}
void CppSupportPart : : addMethod ( ClassDom aClass , const TQString & name , const TQString type ,
const TQString & parameters , CodeModelItem : : Access accessType ,
bool isConst , bool isInline , bool isVirtual , bool isPureVirtual ,
const TQString & implementation )
{
partController ( ) - > editDocument ( KURL ( aClass - > fileName ( ) ) ) ;
KTextEditor : : EditInterface * editIface = dynamic_cast < KTextEditor : : EditInterface * > ( partController ( ) - > activePart ( ) ) ;
if ( ! editIface )
{
/// @fixme show messagebox
return ;
}
TQString declarationString = type + " " + name + " ( " + parameters + " ) " + ( isConst ? " const " : " " ) ;
KDevSourceFormatter * sourceFormatter = extension < KDevSourceFormatter > ( " TDevelop/SourceFormatter " ) ;
TQString finalDeclaration = ( ( isVirtual | | isPureVirtual ) ? " \n virtual " : " \n " + declarationString +
( isPureVirtual ? " = 0 " : " " ) +
( isInline ? " \n { \n " + implementation + " \n } \n " : " ; " ) ) ;
if ( sourceFormatter ! = 0 )
finalDeclaration = sourceFormatter - > formatSource ( finalDeclaration ) ;
TQString indentString = " \t " ;
if ( sourceFormatter ! = 0 )
indentString = sourceFormatter - > indentString ( ) ;
editIface - > insertText ( findInsertionLineMethod ( aClass , accessType ) , 0 ,
finalDeclaration . replace ( " \n " , " \n \t " ) + " \n " ) ;
backgroundParser ( ) - > addFile ( aClass - > fileName ( ) ) ;
if ( isInline | | isPureVirtual )
return ;
// construct fully qualified name for method definition
TQString fullyQualifiedName = aClass - > scope ( ) . join ( " :: " ) ;
if ( ! fullyQualifiedName . isEmpty ( ) )
{
fullyQualifiedName + = " :: " ;
}
fullyQualifiedName + = aClass - > name ( ) + " :: " + name ;
TQString definitionString = " \n " + type + " " + fullyQualifiedName + " ( " + parameters + " ) " + ( isConst ? " const " : " " ) + " \n { \n " + implementation + " \n } \n " ;
if ( sourceFormatter ! = 0 )
definitionString = sourceFormatter - > formatSource ( definitionString ) ;
TQFileInfo info ( aClass - > fileName ( ) ) ;
TQString implementationFile = info . dirPath ( true ) + " / " + info . baseName ( ) + " .cpp " ;
TQFileInfo fileInfo ( implementationFile ) ;
KDevCreateFile * createFileSupport = extension < KDevCreateFile > ( " TDevelop/CreateFile " ) ;
if ( ! TQFile : : exists ( fileInfo . absFilePath ( ) ) & & createFileSupport ! = 0 )
createFileSupport - > createNewFile ( fileInfo . extension ( ) , fileInfo . dirPath ( true ) , fileInfo . baseName ( ) ) ;
partController ( ) - > editDocument ( KURL ( implementationFile ) ) ;
editIface = dynamic_cast < KTextEditor : : EditInterface * > ( partController ( ) - > activePart ( ) ) ;
if ( ! editIface )
return ; //@fixme errorverdoedelung
editIface - > insertLine ( editIface - > numLines ( ) , TQString : : fromLatin1 ( " " ) ) ;
editIface - > insertText ( editIface - > numLines ( ) - 1 , 0 , definitionString ) ;
backgroundParser ( ) - > addFile ( implementationFile ) ;
}
ClassDom CppSupportPart : : currentClass ( ) const
{
FileDom file = codeModel ( ) - > fileByName ( m_activeFileName ) ;
if ( file = = 0 | | m_activeViewCursor = = 0 )
return 0 ;
unsigned int curLine , curCol ;
m_activeViewCursor - > cursorPositionReal ( & curLine , & curCol ) ;
CodeModelUtils : : CodeModelHelper h ( codeModel ( ) , file ) ;
return h . classAt ( curLine , curCol ) ;
}
VariableDom CppSupportPart : : currentAttribute ( ClassDom curClass ) const
{
if ( m_activeViewCursor = = 0 | | curClass = = 0 )
return 0 ;
unsigned int line , col ;
m_activeViewCursor - > cursorPositionReal ( & line , & col ) ;
VariableList vars = curClass - > variableList ( ) ;
for ( VariableList : : iterator i = vars . begin ( ) ; i ! = vars . end ( ) ; + + i )
{
int startLine , startCol ;
( * i ) - > getStartPosition ( & startLine , & startCol ) ;
if ( startLine < ( int ) line | | ( startLine = = ( int ) line & & startCol < = ( int ) col ) )
{
int endLine , endCol ;
( * i ) - > getEndPosition ( & endLine , & endCol ) ;
if ( endLine > ( int ) line | | ( endLine = = ( int ) line & & endCol > = ( int ) col ) )
return * i ;
}
}
return 0 ;
}
void CppSupportPart : : slotCreateAccessMethods ( )
{
if ( m_curAttribute = = 0 | | m_curClass = = 0 )
return ;
CreateGetterSetterDialog dlg ( this , m_curClass , m_curAttribute ) ;
dlg . exec ( ) ;
}
int CppSupportPart : : findInsertionLineMethod ( ClassDom aClass , CodeModelItem : : Access access )
{
int line , column ;
aClass - > getEndPosition ( & line , & column ) ;
int point = CodeModelUtils : : findLastMethodLine ( aClass , access ) ;
if ( point = = - 1 )
{
KTextEditor : : EditInterface * editIface = dynamic_cast < KTextEditor : : EditInterface * > ( partController ( ) - > activePart ( ) ) ;
if ( ! editIface )
return - 1 ;
editIface - > insertLine ( line - 1 , CodeModelUtils : : accessSpecifierToString ( access ) + " : \n " ) ;
return line ;
}
return point + 1 ;
}
int CppSupportPart : : findInsertionLineVariable ( ClassDom aClass , CodeModelItem : : Access access )
{
int line , column ;
aClass - > getEndPosition ( & line , & column ) ;
int point = CodeModelUtils : : findLastVariableLine ( aClass , access ) ;
if ( point = = - 1 )
{
KTextEditor : : EditInterface * editIface = dynamic_cast < KTextEditor : : EditInterface * > ( partController ( ) - > activePart ( ) ) ;
if ( ! editIface )
return - 1 ;
editIface - > insertLine ( line - 1 , CodeModelUtils : : accessSpecifierToString ( access ) + " : \n " ) ;
return line ;
}
return point ;
}
void CppSupportPart : : createAccessMethods ( ClassDom theClass , VariableDom theVariable )
{
m_curClass = theClass ;
m_curAttribute = theVariable ;
slotCreateAccessMethods ( ) ;
}
void CppSupportPart : : slotCursorMoved ( )
{
m_cursorMovedTimer - > start ( 250 , true ) ;
}
void CppSupportPart : : slotTextChanged ( )
{
setTyping ( true ) ; ///@todo check if this is really needed
if ( m_backgroundParserConfig - > useBackgroundParser ( ) )
{
m_textChangedTimer - > start ( m_backgroundParserConfig - > backgroudParseDelay ( ) , true ) ;
}
}
void CppSupportPart : : slotParseCurrentFile ( )
{
if ( isValid ( ) & & ! isQueued ( m_activeFileName ) )
{
parseFileAndDependencies ( m_activeFileName , true , true ) ;
}
}
void CppSupportPart : : updateBackgroundParserConfig ( )
{
BackgroundParserConfig config ;
config . readConfig ( ) ;
if ( m_backgroundParserConfig - > useProblemReporter ( ) & & ! config . useProblemReporter ( ) )
{
removeProblemReporter ( ) ;
}
else if ( ! m_backgroundParserConfig - > useProblemReporter ( ) & & config . useProblemReporter ( ) )
{
embedProblemReporter ( true ) ;
}
* m_backgroundParserConfig = config ;
}
const SynchronizedFileSet & CppSupportPart : : safeFileSet ( ) const {
return m_safeProjectFiles ;
}
SynchronizedFileSet & CppSupportPart : : safeFileSet ( ) {
return m_safeProjectFiles ;
}
void CppSupportPart : : buildSafeFileSet ( ) {
if ( codeCompletion ( ) = = 0 ) //probably the project has already been closed
return ;
SynchronizedFileSet : : SetType files ; //everything that goes into this set must be deep-copied
kdDebug ( 9007 ) < < " CppSupportPart:: rebuilding safe-file-set " < < endl ;
for ( TQStringList : : const_iterator it = m_projectFileList . begin ( ) ; it ! = m_projectFileList . end ( ) ; + + it ) {
TQFileInfo fi ( * it ) ;
TQString file = * it ;
if ( fi . isRelative ( ) ) {
fi . setFile ( TQDir ( m_projectDirectory ) , * it ) ;
file = fi . absFilePath ( ) ;
}
//deep-copy
files . insert ( TQString : : fromUtf8 ( file . utf8 ( ) ) ) ;
}
///Now get all translation-units from the code-repository
TQValueList < Catalog : : QueryArgument > args ;
args < < Catalog : : QueryArgument ( " kind " , Tag : : Kind_TranslationUnit ) ;
TQValueList < Tag > tags ( codeCompletion ( ) - > repository ( ) - > query ( args ) ) ;
for ( TQValueList < Tag > : : const_iterator it = tags . begin ( ) ; it ! = tags . end ( ) ; + + it ) {
files . insert ( ( * it ) . fileName ( ) + " || " + ( * it ) . attribute ( " macroValueHash " ) . toString ( ) + " || " + ( * it ) . attribute ( " macroIdHash " ) . toString ( ) ) ;
}
m_safeProjectFiles . setFiles ( files ) ;
}
void CppSupportPart : : addToRepository ( ParsedFilePointer file ) {
TQString catalogString ( " automatic_ " + KURL : : encode_string_no_slash ( m_projectDirectory ) ) ;
TDEStandardDirs * dirs = CppSupportFactory : : instance ( ) - > dirs ( ) ;
TQString dbName = dirs - > saveLocation ( " data " , " kdevcppsupport/pcs " ) + catalogString + " .db " ;
Catalog * catalog = 0 ;
///First check if the catalog is already there
TQValueList < Catalog * > catalogs = codeRepository ( ) - > registeredCatalogs ( ) ;
for ( TQValueList < Catalog * > : : const_iterator it = catalogs . begin ( ) ; it ! = catalogs . end ( ) ; + + it ) {
if ( ( * it ) - > dbName ( ) = = dbName ) {
catalog = * it ;
break ;
}
}
if ( ! catalog ) {
kdDebug ( 9007 ) < < " creating new catalog named " < < catalogString < < " for automatic filling " < < endl ;
//TQStringList indexList = TQStringList() << "kind" << "name" << "scope" << "fileName" << "prefix";
catalog = new Catalog ;
catalog - > open ( dbName ) ;
catalog - > addIndex ( " kind " ) ;
catalog - > addIndex ( " name " ) ;
catalog - > addIndex ( " scope " ) ;
catalog - > addIndex ( " prefix " ) ;
catalog - > addIndex ( " fileName " ) ;
/*
for ( TQStringList : : Iterator idxIt = indexList . begin ( ) ; idxIt ! = indexList . end ( ) ; + + idxIt )
catalog - > addIndex ( ( * idxIt ) . utf8 ( ) ) ; */
addCatalog ( catalog ) ;
}
catalog - > setEnabled ( true ) ;
///Now check if the file was already parsed with the same parameters, if yes don't parse again(auto-update is currently not supported, when major changes have been done in the libraries, the repository should be deleted)
TQValueList < Catalog : : QueryArgument > args ;
bool compatibleParsed = false ;
Tag compatibleParsedTag ;
args < < Catalog : : QueryArgument ( " kind " , Tag : : Kind_TranslationUnit ) ;
args < < Catalog : : QueryArgument ( " fileName " , file - > fileName ( ) ) ;
TQValueList < Tag > tags ( catalog - > query ( args ) ) ;
if ( ! tags . isEmpty ( ) ) {
for ( TQValueList < Tag > : : const_iterator it = tags . begin ( ) ; it ! = tags . end ( ) ; + + it ) {
if ( ( * it ) . hasAttribute ( " cppparsedfile " ) ) {
TQVariant v = ( * it ) . attribute ( " cppparsedfile " ) ;
///@todo reenable this
/*TQByteArray b = v.toByteArray();
if ( ! b . isEmpty ( ) ) {
//Would be much more efficient not to do this deserialization
ParsedFile f ( b ) ;
if ( f . usedMacros ( ) . valueHash ( ) = = file - > usedMacros ( ) . valueHash ( ) & & f . usedMacros ( ) . idHash ( ) = = file - > usedMacros ( ) . idHash ( ) & & f . includeFiles ( ) . hash ( ) = = file - > includeFiles ( ) . hash ( ) ) {
///Do not reparse the file, it seems to already be in the repository in a similar state
if ( ( * it ) . attribute ( " includedFrom " ) . toString ( ) = = file - > includedFrom ( ) ) return ;
///It is probable that the same state has already been parsed, but there seems to be no such tag yet(the tag will be added)
compatibleParsed = true ;
compatibleParsedTag = * it ;
break ;
}
} */
}
}
}
if ( compatibleParsed ) {
///Add a Tag that makes sure that the file will not be parsed again
compatibleParsedTag . setAttribute ( " includedFrom " , file - > includedFrom ( ) ) ;
TQByteArray data ;
TQDataStream s ( data , IO_WriteOnly ) ;
file - > write ( s ) ;
compatibleParsedTag . setAttribute ( " cppparsedfile " , data ) ;
catalog - > addItem ( compatibleParsedTag ) ;
return ;
}
kdDebug ( 9007 ) < < " parsing translation-unit " < < file - > fileName ( ) < < " into catalog " < < catalogString < < endl ;
TagCreator w ( file - > fileName ( ) , catalog ) ;
w . parseTranslationUnit ( * file ) ;
codeRepository ( ) - > touchCatalog ( catalog ) ;
m_safeProjectFiles . insert ( file - > fileName ( ) + " || " + TQString ( " %1 " ) . arg ( file - > usedMacros ( ) . valueHash ( ) ) + " || " + TQString ( " %1 " ) . arg ( file - > usedMacros ( ) . idHash ( ) ) ) ;
}
TQString CppSupportPart : : findHeaderSimple ( const TQString & header )
{
TQStringList : : ConstIterator it ;
for ( it = m_projectFileList . begin ( ) ; it ! = m_projectFileList . end ( ) ; + + it )
{
TQString s = * it ;
if ( s = = header )
return s ;
if ( ( s . right ( header . length ( ) ) = = header ) & & ( s [ s . length ( ) - header . length ( ) - 1 ] = = ' / ' ) )
return s ;
}
return TQString ( ) ;
}
UIBlockTester : : UIBlockTesterThread : : UIBlockTesterThread ( UIBlockTester & parent ) : TQThread ( ) , m_parent ( parent ) , m_stop ( false ) {
}
void UIBlockTester : : UIBlockTesterThread : : run ( ) {
while ( ! m_stop ) {
msleep ( m_parent . m_msecs / 10 ) ;
m_parent . m_timeMutex . lock ( ) ;
TQDateTime t = TQDateTime : : currentDateTime ( ) ;
uint msecs = m_parent . m_lastTime . time ( ) . msecsTo ( t . time ( ) ) ;
if ( msecs > m_parent . m_msecs ) {
m_parent . lockup ( ) ;
m_parent . m_lastTime = t ;
}
m_parent . m_timeMutex . unlock ( ) ;
}
}
void UIBlockTester : : UIBlockTesterThread : : stop ( ) {
m_stop = true ;
}
UIBlockTester : : UIBlockTester ( uint milliseconds ) : m_thread ( * this ) , m_msecs ( milliseconds ) {
m_timer = new TQTimer ( this ) ;
m_timer - > start ( milliseconds / 10 ) ;
connect ( m_timer , TQT_SIGNAL ( timeout ( ) ) , this , TQT_SLOT ( timer ( ) ) ) ;
timer ( ) ;
m_thread . start ( ) ;
}
UIBlockTester : : ~ UIBlockTester ( ) {
m_thread . stop ( ) ;
m_thread . wait ( ) ;
}
void UIBlockTester : : timer ( ) {
m_timeMutex . lock ( ) ;
m_lastTime = TQDateTime : : currentDateTime ( ) ;
m_timeMutex . unlock ( ) ;
}
void UIBlockTester : : lockup ( ) {
//std::cout << "UIBlockTester: lockup of the UI for " << m_msecs << endl; ///kdDebug(..) is not thread-safe..
int a = 1 ; ///Place breakpoint here
}
# include "cppsupportpart.moc"
//kate: indent-mode csands; tab-width 4; space-indent off;