You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdevelop/lib/cppparser/driver.h

461 lines
14 KiB

/* This file is part of KDevelop
Copyright (C) 2002,2003 Roberto Raggi <roberto@kdevelop.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef DRIVER_H
#define DRIVER_H
#include "ast.h"
#include "macro.h"
#include <qpair.h>
#include <qvaluestack.h>
#include <qstringlist.h>
#include <qcstring.h>
#include <qdatastream.h>
#include <qmap.h>
#include <qdatetime.h>
#include <qvaluelist.h>
#include <map>
#include <set>
#include <hashedstring.h>
#include <ksharedptr.h>
#include <codemodel.h>
#include <ext/hash_map>
#include "lexercache.h"
class Lexer;
class Parser;
enum
{
Dep_Global,
Dep_Local
};
typedef QPair<QString, int> Dependence;
class ParsedFile;
typedef KSharedPtr< ParsedFile > ParsedFilePointer;
class ParsedFile : public AbstractParseResult {
public:
struct IncludeDesc {
bool local; //Whether it is a local include(#include "local.h", not #include <global.h>)
QString includePath;
ParsedFilePointer parsed; //May be zero!
};
// ParsedFile() {
// }
ParsedFile( QDataStream& s ) {
read( s );
}
ParsedFile( const QString& fileName, const QDateTime& timeStamp );
///Deserializes the ParsedFile from a previous call to serialize(). AST will always be zero after a call to this.
ParsedFile( const QByteArray& array );
/**
* @return All Macros that were used while processing this translation-unit. May be modified.
*/
MacroSet& usedMacros();
const MacroSet& usedMacros() const;
/**
* @return the count of lines that were skipped while preprocessing the file
* */
int skippedLines() const;
void setSkippedLines( int lines );
/**
* @return Absolutely all files included by this one(no matter through how many other files they were included)
*/
// HashedStringSet& includeFiles();
const HashedStringSet& includeFiles() const;
void addIncludeFiles( const HashedStringSet& includeFiles );
void addIncludeFile( const QString& includePath, const ParsedFilePointer& parsed, bool localInclude );
///If this file was parsed while resolving the dependencies of another file, this returns the file this one was included from. Else returns an empty string.
QString includedFrom() const;
void setIncludedFrom( const QString& str );
/**
* @return Reference to the internal list of all directly included files(without those included indirectly)
*/
const QValueList<IncludeDesc>& directIncludeFiles() const;
operator TranslationUnitAST* () const; //May be zero!
TranslationUnitAST* operator -> () const {
if( !this ) return 0;
return m_translationUnit;
}
void setTranslationUnit( const TranslationUnitAST::Node& trans );
QString fileName() const;
QDateTime timeStamp() const;
///Serializes the content of this class into a byte-array. Note that this does not serialize the AST.
QByteArray serialize() const;
/*void read( QDataStream& stream );
void write( QDataStream& stream ) const;*/
virtual void read( QDataStream& stream ) {
int directIncludeFilesCount;
stream >> directIncludeFilesCount;
m_directIncludeFiles.clear();
for( int a = 0; a < directIncludeFilesCount; a++ ) {
IncludeDesc i;
Q_INT8 in;
stream >> in;
i.local = in;
stream >> i.includePath;
//"parsed" will not be reconstructed
m_directIncludeFiles.push_back( i );
}
stream >> m_skippedLines;
stream >> m_fileName;
stream >> m_timeStamp;
stream >> m_includedFrom;
m_usedMacros.read( stream );
m_translationUnit = 0;
m_includeFiles.read( stream );
}
virtual void write( QDataStream& stream ) const {
int i = m_directIncludeFiles.size();
stream << i;
for( QValueList<IncludeDesc>::const_iterator it = m_directIncludeFiles.begin(); it != m_directIncludeFiles.end(); ++it ) {
Q_INT8 i = (*it).local;
stream << i;
stream << (*it).includePath;
}
stream << m_skippedLines;
stream << m_fileName;
stream << m_timeStamp;
stream << m_includedFrom;
m_usedMacros.write( stream );
m_includeFiles.write( stream );
}
virtual ParsedFileType type() const {
return CppParsedFile;
}
private:
QValueList<IncludeDesc> m_directIncludeFiles;
MacroSet m_usedMacros;
TranslationUnitAST::Node m_translationUnit;
HashedStringSet m_includeFiles;
int m_skippedLines;
QString m_fileName;
QDateTime m_timeStamp;
QString m_includedFrom;
};
/**
* An interface that provides source code to the Driver
*/
class SourceProvider {
public:
SourceProvider() {}
virtual ~SourceProvider() {}
/**
* Get the contents of a file
* \param fileName The name of the file to get the contents for. An absolute
* path should be used.
* \return A QString that contains the contents of the file
*/
virtual QString contents( const QString& fileName ) = 0;
/**
* Check to see if a file has been modified
* \param fileName The name of hte file to get the modification state of. An
* absolute path should be used.
* \return true if the file has been modified
* \return false if the file has not been modified
*/
virtual bool isModified( const QString& fileName ) = 0;
private:
SourceProvider( const SourceProvider& source );
void operator = ( const SourceProvider& source );
};
class Driver {
public:
Driver();
virtual ~Driver();
typedef std::multimap< HashedString, Macro > MacroMap;
/**
* Get the source provider for this driver. This would be useful for
* getting the text the driver is working with.
*/
SourceProvider* sourceProvider();
/**
* Sets the source provider the driver will use
* @param sourceProvider the SourceProvider the driver will use
*/
void setSourceProvider( SourceProvider* sourceProvider );
/**
* @brief Resets the driver
*
* Clears the driver of all problems, dependencies, macros, and include paths and
* removes any translation units that have been parsed
*/
virtual void reset();
/**
* Tells the driver to start parsing a file
* @param fileName The name of the file to parse
* @param onlyPreProcesss Tells the driver to only run the file through the preprocessor. Defaults to false
* @param force Force the parsing of the file. Defaults to false
* @param macrosGlobal Should the macros be global? (Global macros are not deleted once a new translation-unit is parsed)
*/
virtual void parseFile( const QString& fileName, bool onlyPreProcesss = false, bool force = false, bool macrosGlobal = false );
/**
* Indicates that the file has been parsed
* @param fileName The name of the file parsed. It is legal to create a ParsedFilePointer on the given item.
*/
virtual void fileParsed( ParsedFile& fileName );
/**
* Removes the file specified by @p fileName from the driver
* @param fileName The name of the file to remove
*/
virtual void remove
( const QString& fileName );
/**
* Add a dependency on another header file for @p fileName
* @param fileName The file name to add the dependency for
* @param dep The dependency to add
*/
virtual void addDependence( const QString& fileName, const Dependence& dep );
/**
* Add a macro to the driver
* @param macro The macro to add to the driver
*/
virtual void addMacro( const Macro& macro );
/**
* Add a problem to the driver
* @param fileName The file name to add the problem for
* @param problem The problem to add
*/
virtual void addProblem( const QString& fileName, const Problem& problem );
/**
* The current file name the driver is working with
*/
QString currentFileName() const {
return m_currentFileName;
}
ParsedFilePointer takeTranslationUnit( const QString& fileName );
void takeTranslationUnit( const ParsedFile& file );
/**
* Get the translation unit contained in the driver for @p fileName.
* @param fileName The name of the file to get the translation unit for
* @return The TranslationUnitAST pointer that represents the translation unit
* @return 0 if no translation unit exists for the file
*/
ParsedFilePointer translationUnit( const QString& fileName ) const;
/**
* Get the dependencies for a file
* @param fileName The file name to get dependencies for
* @return The dependencies for the file
*/
QMap<QString, Dependence> dependences( const QString& fileName ) const;
/**
* Get all the macros the driver contains
* @return The macros
*/
const MacroMap& macros() const;
/**
* Take all macros from the given map(forgetting own macros) */
void insertMacros( const MacroSet& macros );
/**
* Get the list of problem areas the driver contains
* @param fileName The filename to get problems for
* @return The list of problems for @p fileName
*/
QValueList<Problem> problems( const QString& fileName ) const;
void usingString( const HashedString& str );
/**
* Check if we have a macro in the driver
* If the last stacked macro of that name is an undef-macro, false is returned.
* @param name The name of the macro to check for
* @return true if we have the macro in the driver
* @return false if we don't have the macro in the driver
*/
bool hasMacro( const HashedString& name ) ;
/**
* Get the macro identified by @p name
* @param name The name of the macro to get
* @return A const reference of the macro object represented by @p name
*/
const Macro& macro( const HashedString& name ) const;
/**
* Get the last inserted macro identified by @p name
* @override
* @param name The name of the macro to get
* @return A non-const reference of the macro object represented by @p name
*
*/
Macro& macro( const HashedString& name );
/**
* Remove the last inserted Macro of that name
* @param macroName The name of the macro to remove
*/
virtual void removeMacro( const HashedString& macroName );
/**
* Remove all macros from the driver for a certain file
* @param fileName The file name
*/
virtual void removeAllMacrosInFile( const QString& fileName ); ///Check when this is called. It may be wrong.
QStringList includePaths() const {
return m_includePaths;
}
virtual QStringList getCustomIncludePath( const QString& );
virtual void addIncludePath( const QString &path );
virtual void clearIncludePaths();
/// @todo remove
const QMap<QString, ParsedFilePointer> &parsedUnits() const {
return m_parsedUnits;
}
/**
* Set whether or not to enable dependency resolving for files added to the driver
*/
virtual void setResolveDependencesEnabled( bool enabled );
/**
* Check if dependency resolving is enabled
* \return true if dependency resolving is enabled
* \return false if dependency resolving is disabled
*/
bool isResolveDependencesEnabled() const {
return depresolv;
}
void setMaxDependenceDepth( int depth );
/**
* Used by the Lexer to indicate that a Macro was used
* @param macro The used macro
* */
void usingMacro( const Macro& macro );
/**
* Returns the local instance of the lexer-cache, can be used from outside to control the cache-behavior.
* */
LexerCache* lexerCache();
///This uses getCustomIncludePath(..) to resolve the include-path internally
QString findIncludeFile( const Dependence& dep, const QString& fromFile );
protected:
///This uses the state of the parser to find the include-file
QString findIncludeFile( const Dependence& dep ) const;
/**
* Set up the lexer.
*/
virtual void setupLexer( Lexer* lexer );
/**
* Setup the parser
*/
virtual void setupParser( Parser* parser );
/**
* Set up the preprocessor
*/
virtual void setupPreProcessor();
/**
* Is code-information for this file already available? If false is returned, the file will be parsed.
* Code-model and static repository should be checked to find out whether the file is already available.
* This function is only used when dependency-resolving is activated.
* @arg file absolute path to the file
*/
virtual bool shouldParseIncludedFile( const ParsedFilePointer& /*file*/ );
void clearMacros();
void clearParsedMacros();
private:
QMap<QString, Dependence>& findOrInsertDependenceList( const QString& fileName );
QValueList<Problem>& findOrInsertProblemList( const QString& fileName );
private:
QString m_currentFileName;
QString m_currentMasterFileName;
typedef QMap<QString, Dependence> DependenceMap;
typedef QMap< QString, DependenceMap> DependencesMap;
DependencesMap m_dependences;
MacroMap m_macros;
QMap< QString, QValueList<Problem> > m_problems;
QMap<QString, ParsedFilePointer> m_parsedUnits;
QStringList m_includePaths;
uint depresolv :
1;
Lexer *lexer;
SourceProvider* m_sourceProvider;
ParsedFilePointer m_currentParsedFile;
CachedLexedFilePointer m_currentLexerCache;
LexerCache m_lexerCache;
int m_dependenceDepth;
int m_maxDependenceDepth;
class ParseHelper;
friend class ParseHelper;
private:
Driver( const Driver& source );
void operator = ( const Driver& source );
};
#endif