#include "tdelocale.h" /* defines [function] i18n */ #include #include "kdevdriver.h" #include "cppcodecompletionconfig.h" #include "setuphelper.h" #include #include "includepathresolver.h" KDevDriver::KDevDriver( CppSupportPart* cppSupport, bool foreground ) : m_cppSupport( cppSupport ), m_includePathResolver(0), m_foreground(foreground), m_shouldParseIncludedFiles(true) { //setupProject(); setup(); } KDevDriver::~KDevDriver() { delete m_includePathResolver; } CppSupportPart* KDevDriver::cppSupport() { return m_cppSupport; } void KDevDriver::setupProject() { TQMap map; TQStringList fileList = m_cppSupport->project() ->allFiles(); TQStringList::ConstIterator it = fileList.begin(); while ( it != fileList.end() ) { TQFileInfo info( *it ); ++it; map.insert( info.dirPath( true ), true ); } TQMap::Iterator mapit = map.begin(); while ( mapit != map.end() ) { addIncludePath( mapit.key() ); ++mapit; } } void KDevDriver::setupLexer( Lexer* lexer ) { Driver::setupLexer( lexer ); lexer->setReportMessages( true ); lexer->setReportWarnings( true ); } //! setup the preprocessor //! code provided by Reginald Stadlbauer void KDevDriver::setup() { if( lexerCache() ) lexerCache()->clear(); ///Clear the lexer-cache so missing headers get a chance to be parsed clearMacros(); clearIncludePaths(); addMacro( Macro("KDEVELOP_PARSER", "3.4") ); bool ok; TQString verboseGccOutput = SetupHelper::getVerboseGccIncludePath( &ok ); TQStringList verboseGccLines = TQStringList::split( '\n', verboseGccOutput ); if( verboseGccLines.count() > 3 ) { ///Parse the output of gcc. It includes gcc's final include-path when parsing an empty c++-file(including dirs like /usr/include/c++/4.xx/...) //what about order? for( TQStringList::iterator it = verboseGccLines.begin(); it != verboseGccLines.end(); ++it ) { if( (*it).startsWith(" ") && (*it).length() > 2 && (*it)[1] != ' ' ) { //it is a potential include-file TQString path = (*it).stripWhiteSpace(); TQFileInfo info( path ); if( info.exists() ) { kdDebug( 9007 ) << "Adding include-path from gcc-output: \"" << path << "\" absolute: \"" << info.absFilePath() << "\"" << endl; addIncludePath(info.absFilePath()); } } } } else { ///Do some of the old stuff addIncludePath( "/include" ); addIncludePath( "/usr/include" ); addIncludePath( "/usr/local/include" ); bool ok; TQString includePath = SetupHelper::getGccIncludePath(&ok); if (ok) { TQStringList ls = TQStringList::split( "\n", includePath ); for( TQStringList::const_iterator it = ls.begin(); it != ls.end(); ++it ) { if( !(*it).isEmpty() ) addIncludePath( *it ); } } addIncludePath( includePath ); addIncludePath( "/usr/include/g++-3" ); addIncludePath( "/usr/include/g++" ); } addMacro( Macro( "__cplusplus", "1" ) ); ///@todo maybe remove the following? Is there any normal user who has his environment set up correctly so this is of any use? TQString tdedir = getenv( "TDEDIR" ); if( !tdedir.isNull() ) addIncludePath( tdedir + "/include" ); TQString qmakespec = getenv( "QMAKESPEC" ); if ( qmakespec.isNull() ) qmakespec = "linux-g++"; TQString qtdir = getenv( "QTDIR" ); if( !qtdir.isNull() ) { addIncludePath( qtdir + "/include" ); // #### implement other mkspecs and find a better way to find the // #### proper mkspec (althoigh this will be no fun :-) addIncludePath( qtdir + "/mkspecs/" + qmakespec ); } TQStringList lines = SetupHelper::getGccMacros(&ok); if (!ok) { for (TQStringList::ConstIterator it = lines.constBegin(); it != lines.constEnd(); ++it) { TQStringList lst = TQStringList::split( ' ', *it ); if ( lst.count() != 3 ) continue; addMacro( Macro( lst[1], lst[2] ) ); } } addMacro( Macro( "__cplusplus", "1" ) ); addMacro( Macro( "signals", "signals" ) ); addMacro( Macro( "slots", "slots" ) ); addMacro( Macro( "TQ_SCRIPTABLE", "" ) ); CppCodeCompletionConfig* cfg = m_cppSupport->codeCompletionConfig(); TQString str = cfg->customIncludePaths(); int pos = 0; while( pos < str.length() ) { int end = str.find( ';', pos ); if( end == -1 ) { end = str.length(); } TQString s = str.mid( pos, end-pos ).stripWhiteSpace(); if( !s.isEmpty() ) { if( !s.startsWith( "/" ) && m_cppSupport->project() ) { s = m_cppSupport->project()->projectDirectory() + "/" + s; } addIncludePath( s ); } pos = end+1; } setResolveDependencesEnabled( cfg->preProcessAllHeaders() | cfg->parseMissingHeaders() ); delete m_includePathResolver; if( cfg->resolveIncludePaths() ) { m_includePathResolver = new CppTools::IncludePathResolver( m_foreground ); if( m_cppSupport && m_cppSupport->project() ) m_includePathResolver->setOutOfSourceBuildSystem( m_cppSupport->project()->projectDirectory(), m_cppSupport->project()->buildDirectory() ); } else m_includePathResolver = 0; m_shouldParseIncludedFiles = cfg->parseMissingHeaders(); } TQStringList KDevDriver::getCustomIncludePath( const TQString& file ) { if( !file.startsWith("/") ) kdDebug( 9007 ) << "KDevDriver::getCustomIncludePath(..): given file \"" << file << "\" is not absolute" << endl; if( !m_includePathResolver ) return includePaths(); CppTools::PathResolutionResult res = m_includePathResolver->resolveIncludePath( file ); if( !res.success ) { Problem p( i18n( "%1. Message: %2" ).arg( res.errorMessage ).arg( res.longErrorMessage ), 0, 0, Problem::Level_Warning ); p.setFileName( file ); addProblem( file, p ); } return res.path + includePaths(); } bool KDevDriver::shouldParseIncludedFile( const ParsedFilePointer& file ) { TQString compoundString = file->fileName() + "||" + TQString("%1").arg(file->usedMacros().valueHash()) + "||" + TQString("%1").arg(file->usedMacros().idHash()); if( !m_shouldParseIncludedFiles ) return false; m_cppSupport->safeFileSet().contains( compoundString ); if( m_cppSupport->safeFileSet().contains( file->fileName()) ){ return false; } else if( m_cppSupport->safeFileSet().contains( compoundString ) ) { //kdDebug( 9007 ) << "ALREADY IN FILE-SET: " << compoundString << endl; return false; } else { m_cppSupport->safeFileSet().insert( compoundString ); //This is needed so the same instance of a file is not queued many times //kdDebug( 9007 ) << "NOT IN FILE-SET, PARSING: " << compoundString << endl; return true; } } //kate: indent-mode csands; tab-width 4; space-indent off;