/*************************************************************************** * Copyright (C) 2002 by Roberto Raggi * * roberto@kdevelop.org * * * * 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 "backgroundparser.h" #include "javasupportpart.h" #include "javasupport_events.h" #include "driver.h" #include "kdevdeepcopy.h" #include "kdevdriver.h" #include #include #include #include #include #include #include #include #include #include #include #include #include class KDevSourceProvider: public SourceProvider { public: KDevSourceProvider( JavaSupportPart* javaSupport ) : m_javaSupport( javaSupport ), m_readFromDisk( false ) {} void setReadFromDisk( bool b ) { m_readFromDisk = b; } bool readFromDisk() const { return m_readFromDisk; } virtual TQString contents( const TQString& fileName ) { if( !m_readFromDisk ){ //kdDebug(9013) << "-------> kapp is locked = " << kapp->locked() << endl; bool needToLock = kapp->locked() == false; if( needToLock ) kapp->lock(); //kdDebug(9013) << "-------> kapp locked" << endl; TQPtrList parts( *m_javaSupport->partController()->parts() ); TQPtrListIterator it( parts ); while( it.current() ){ KTextEditor::Document* doc = dynamic_cast( it.current() ); ++it; KTextEditor::EditInterface* editIface = dynamic_cast( doc ); if( !doc || !editIface || doc->url().path() != fileName ) continue; TQString contents = TQString( editIface->text().ascii() ); // deep copy if( needToLock ) kapp->unlock(); //kdDebug(9013) << "-------> kapp unlocked" << endl; return contents; } if( needToLock ) kapp->unlock(); //kdDebug(9013) << "-------> kapp unlocked" << endl; } TQFile f( fileName ); TQTextStream stream( &f ); if( f.open(IO_ReadOnly) ){ TQString contents = stream.read(); f.close(); return contents; } return TQString(); } virtual bool isModified( const TQString& fileName ) { Q_UNUSED( fileName ); return true; } private: JavaSupportPart* m_javaSupport; bool m_readFromDisk; private: KDevSourceProvider( const KDevSourceProvider& source ); void operator = ( const KDevSourceProvider& source ); }; class SynchronizedFileList { public: SynchronizedFileList() {} bool isEmpty() const { TQMutexLocker locker( &m_mutex ); return m_fileList.isEmpty(); } uint count() const { TQMutexLocker locker( &m_mutex ); return m_fileList.count(); } TQPair front() const { TQMutexLocker locker( &m_mutex ); return m_fileList.front(); } void clear() { TQMutexLocker locker( &m_mutex ); m_fileList.clear(); } void push_back( const TQString& fileName, bool readFromDisk=false ) { TQMutexLocker locker( &m_mutex ); m_fileList.append( tqMakePair(fileName, readFromDisk) ); /// \FIXME ROBE deepcopy?! } void pop_front() { TQMutexLocker locker( &m_mutex ); m_fileList.pop_front(); } bool tqcontains( const TQString& fileName ) const { TQMutexLocker locker( &m_mutex ); TQValueList< TQPair >::ConstIterator it = m_fileList.begin(); while( it != m_fileList.end() ){ if( (*it).first == fileName ) return true; ++it; } return false; } void remove( const TQString& fileName ) { TQMutexLocker locker( &m_mutex ); TQValueList< TQPair >::Iterator it = m_fileList.begin(); while( it != m_fileList.end() ){ if( (*it).first == fileName ) m_fileList.remove( it ); ++it; } } private: mutable TQMutex m_mutex; TQValueList< TQPair > m_fileList; }; BackgroundParser::BackgroundParser( JavaSupportPart* part, TQWaitCondition* consumed ) : m_consumed( consumed ), m_javaSupport( part ), m_close( false ) { m_fileList = new SynchronizedFileList(); m_driver = new KDevDriver( m_javaSupport ); m_driver->setSourceProvider( new KDevSourceProvider(m_javaSupport) ); //disabled for now m_driver->setResolveDependencesEnabled( true ); } BackgroundParser::~BackgroundParser() { removeAllFiles(); delete( m_driver ); m_driver = 0; delete m_fileList; m_fileList = 0; } void BackgroundParser::addFile( const TQString& fileName, bool readFromDisk ) { TQString fn = deepCopy( fileName ); bool added = false; if( !m_fileList->tqcontains(fn) ){ m_fileList->push_back( fn, readFromDisk ); added = true; } if( added ) m_canParse.wakeAll(); } void BackgroundParser::removeAllFiles() { kdDebug(9013) << "BackgroundParser::removeAllFiles()" << endl; TQMutexLocker locker( &m_mutex ); TQMap::Iterator it = m_unitDict.begin(); while( it != m_unitDict.end() ){ Unit* unit = it.data(); ++it; delete( unit ); unit = 0; } m_unitDict.clear(); m_driver->reset(); m_fileList->clear(); m_isEmpty.wakeAll(); } void BackgroundParser::removeFile( const TQString& fileName ) { TQMutexLocker locker( &m_mutex ); if( Unit* unit = findUnit(fileName) ){ m_driver->remove( fileName ); m_unitDict.remove( fileName ); delete( unit ); unit = 0; } if( m_fileList->isEmpty() ) m_isEmpty.wakeAll(); } Unit* BackgroundParser::parseFile( const TQString& fileName, bool readFromDisk ) { static_cast( m_driver->sourceProvider() )->setReadFromDisk( readFromDisk ); m_driver->remove( fileName ); m_driver->parseFile( fileName ); RefJavaAST translationUnit = m_driver->takeTranslationUnit( fileName ); Unit* unit = new Unit; unit->fileName = fileName; unit->translationUnit = translationUnit; unit->problems = m_driver->problems( fileName ); static_cast( m_driver->sourceProvider() )->setReadFromDisk( false ); if( m_unitDict.tqfind(fileName) != m_unitDict.end() ){ Unit* u = m_unitDict[ fileName ]; m_unitDict.remove( fileName ); delete( u ); u = 0; } m_unitDict.insert( fileName, unit ); if( m_fileList->tqcontains(fileName) ){ kdDebug(9013) << "========================> FILE: " << fileName << " IN TQUEUE <=============" << endl; } else { KApplication::postEvent( m_javaSupport, new FileParsedEvent(fileName, unit->problems) ); } m_currentFile = TQString(); if( m_fileList->isEmpty() ) m_isEmpty.wakeAll(); return unit; } Unit* BackgroundParser::findUnit( const TQString& fileName ) { TQMap::Iterator it = m_unitDict.tqfind( fileName ); return it != m_unitDict.end() ? *it : 0; } RefJavaAST BackgroundParser::translationUnit( const TQString& fileName ) { Unit* u = 0; if( (u = findUnit(fileName)) == 0 ){ m_fileList->remove( fileName ); u = parseFile( fileName, false ); } return u->translationUnit; } TQValueList BackgroundParser::problems( const TQString& fileName ) { Unit* u = 0; if( (u = findUnit(fileName)) == 0 ){ m_fileList->remove( fileName ); u = parseFile( fileName, false ); } return u ? u->problems : TQValueList(); } void BackgroundParser::close() { TQMutexLocker locker( &m_mutex ); m_close = true; m_canParse.wakeAll(); } bool BackgroundParser::filesInQueue() { TQMutexLocker locker( &m_mutex ); return m_fileList->count() || !m_currentFile.isEmpty(); } void BackgroundParser::run() { // (void) m_javaSupport->codeCompletion()->repository()->getEntriesInScope( TQStringList(), false ); while( !m_close ){ m_mutex.lock(); while( m_fileList->isEmpty() ){ m_canParse.wait( &m_mutex ); if( m_close ){ break; } } if( m_close ){ m_mutex.unlock(); break; } TQPair entry = m_fileList->front(); TQString fileName = entry.first; bool readFromDisk = entry.second; m_currentFile = fileName; m_fileList->pop_front(); (void) parseFile( fileName, readFromDisk ); m_mutex.unlock(); } kdDebug(9013) << "!!!!!!!!!!!!!!!!!! BG PARSER DESTROYED !!!!!!!!!!!!" << endl; //commented to fix #83352 //TQThread::exit(); }