diff --git a/src/libs/cplusplus/pp-engine.cpp b/src/libs/cplusplus/pp-engine.cpp index 4ad7854d773944074c9c3ceecd89a74d39fc3982..7b9ad5ec41aa1b7389ce3ddf7da6d6509f59c244 100644 --- a/src/libs/cplusplus/pp-engine.cpp +++ b/src/libs/cplusplus/pp-engine.cpp @@ -871,27 +871,33 @@ void Preprocessor::preprocess(const QString &fileName, const QByteArray &source, expandBuiltinMacro(identifierToken, spell); else { - if (Macro *m = env->resolve(spell)) { - if (! m->isFunctionLike()) { - if (0 == (m = processObjectLikeMacro(identifierToken, spell, m))) - continue; +#ifdef ICHECK_BUILD + if(spell != "Q_PROPERTY" && spell != "Q_INVOKABLE" && spell != "Q_ENUMS" + && spell != "Q_FLAGS" && spell != "Q_DECLARE_FLAGS"){ +#endif + if (Macro *m = env->resolve(spell)) { + if (! m->isFunctionLike()) { + if (0 == (m = processObjectLikeMacro(identifierToken, spell, m))) + continue; - // the macro expansion generated something that looks like - // a function-like macro. - } + // the macro expansion generated something that looks like + // a function-like macro. + } - // `m' is function-like macro. - if (_dot->is(T_LPAREN)) { - QVector<MacroArgumentReference> actuals; - collectActualArguments(&actuals); + // `m' is function-like macro. + if (_dot->is(T_LPAREN)) { + QVector<MacroArgumentReference> actuals; + collectActualArguments(&actuals); - if (_dot->is(T_RPAREN)) { - expandFunctionLikeMacro(identifierToken, m, actuals); - continue; + if (_dot->is(T_RPAREN)) { + expandFunctionLikeMacro(identifierToken, m, actuals); + continue; + } } } +#ifdef ICHECK_BUILD } - +#endif // it's not a function or object-like macro. out(spell); } diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp index 6f7245072f21ee02772f7ef58f67ef6399d6b53a..dd346e9cb79b84f8808546990de072cba5156f41 100644 --- a/src/plugins/cpptools/cppmodelmanager.cpp +++ b/src/plugins/cpptools/cppmodelmanager.cpp @@ -161,73 +161,7 @@ static const char pp_configuration[] = "#define __declspec(a)\n" "#define STDMETHOD(method) virtual HRESULT STDMETHODCALLTYPE method\n"; -namespace CppTools { -namespace Internal { - -class CppPreprocessor: public CPlusPlus::Client -{ -public: - CppPreprocessor(QPointer<CppModelManager> modelManager); - virtual ~CppPreprocessor(); - - void setRevision(unsigned revision); - void setWorkingCopy(const CppModelManagerInterface::WorkingCopy &workingCopy); - void setIncludePaths(const QStringList &includePaths); - void setFrameworkPaths(const QStringList &frameworkPaths); - void setProjectFiles(const QStringList &files); - void setTodo(const QStringList &files); - - void run(const QString &fileName); - - void resetEnvironment(); - - const QSet<QString> &todo() const - { return m_todo; } - -public: // attributes - Snapshot snapshot; - -protected: - CPlusPlus::Document::Ptr switchDocument(CPlusPlus::Document::Ptr doc); - - bool includeFile(const QString &absoluteFilePath, QString *result, unsigned *revision); - QString tryIncludeFile(QString &fileName, IncludeType type, unsigned *revision); - - void mergeEnvironment(CPlusPlus::Document::Ptr doc); - - virtual void macroAdded(const Macro ¯o); - virtual void passedMacroDefinitionCheck(unsigned offset, const Macro ¯o); - virtual void failedMacroDefinitionCheck(unsigned offset, const QByteArray &name); - virtual void startExpandingMacro(unsigned offset, - const Macro ¯o, - const QByteArray &originalText, - bool inCondition, - const QVector<MacroArgumentReference> &actuals); - virtual void stopExpandingMacro(unsigned offset, const Macro ¯o); - virtual void startSkippingBlocks(unsigned offset); - virtual void stopSkippingBlocks(unsigned offset); - virtual void sourceNeeded(QString &fileName, IncludeType type, - unsigned line); - -private: - QPointer<CppModelManager> m_modelManager; - Environment env; - Preprocessor preprocess; - QStringList m_includePaths; - QStringList m_systemIncludePaths; - CppModelManagerInterface::WorkingCopy m_workingCopy; - QStringList m_projectFiles; - QStringList m_frameworkPaths; - QSet<QString> m_included; - Document::Ptr m_currentDoc; - QSet<QString> m_todo; - QSet<QString> m_processed; - unsigned m_revision; -}; - -} // namespace Internal -} // namespace CppTools - +#ifndef ICHECK_BUILD CppPreprocessor::CppPreprocessor(QPointer<CppModelManager> modelManager) : snapshot(modelManager->snapshot()), m_modelManager(modelManager), @@ -235,6 +169,15 @@ CppPreprocessor::CppPreprocessor(QPointer<CppModelManager> modelManager) m_revision(0) { } +#else + +CppPreprocessor::CppPreprocessor(QPointer<CPlusPlus::ParseManager> modelManager) + : preprocess(this, &env), + m_revision(0) +{ +} +#endif + CppPreprocessor::~CppPreprocessor() { } @@ -258,7 +201,7 @@ void CppPreprocessor::setTodo(const QStringList &files) namespace { - +#ifndef ICHECK_BUILD class Process: public std::unary_function<Document::Ptr, void> { QPointer<CppModelManager> _modelManager; @@ -313,7 +256,7 @@ public: _modelManager->emitDocumentUpdated(doc); // ### TODO: compress } }; - +#endif } // end of anonymous namespace void CppPreprocessor::run(const QString &fileName) @@ -580,11 +523,19 @@ void CppPreprocessor::sourceNeeded(QString &fileName, IncludeType type, unsigned snapshot.insert(doc); m_todo.remove(fileName); +#ifndef ICHECK_BUILD Process process(m_modelManager, snapshot, m_workingCopy); process(doc); (void) switchDocument(previousDoc); +#else + (void) switchDocument(previousDoc); + Document::CheckMode mode = Document::FastCheck; + mode = Document::FullCheck; + doc->parse(); + doc->check(mode); +#endif } Document::Ptr CppPreprocessor::switchDocument(Document::Ptr doc) @@ -594,6 +545,7 @@ Document::Ptr CppPreprocessor::switchDocument(Document::Ptr doc) return previousDoc; } +#ifndef ICHECK_BUILD void CppTools::CppModelManagerInterface::updateModifiedSourceFiles() { const Snapshot snapshot = this->snapshot(); @@ -1397,5 +1349,5 @@ void CppModelManager::GC() m_snapshot = newSnapshot; protectSnapshot.unlock(); } - +#endif diff --git a/src/plugins/cpptools/cppmodelmanager.h b/src/plugins/cpptools/cppmodelmanager.h index bd5b7c0768f240b3aa82e651aa1abecd3633adeb..1ebac420beb231e308755679bc91b3304f651e13 100644 --- a/src/plugins/cpptools/cppmodelmanager.h +++ b/src/plugins/cpptools/cppmodelmanager.h @@ -33,9 +33,13 @@ #include <cpptools/cppmodelmanagerinterface.h> #include <projectexplorer/project.h> #include <cplusplus/CppDocument.h> - +#include <cplusplus/PreprocessorClient.h> #include <texteditor/basetexteditor.h> - +#include <cplusplus/PreprocessorEnvironment.h> +#include <cplusplus/pp-engine.h> +#ifdef ICHECK_BUILD +# include "ParseManager.h" +#endif #include <QtCore/QHash> #include <QtCore/QFutureInterface> #include <QtCore/QFutureSynchronizer> @@ -57,13 +61,19 @@ namespace ProjectExplorer { class ProjectExplorerPlugin; } +namespace CPlusPlus { + class ParseManager; +} + namespace CppTools { + namespace Internal { class CppEditorSupport; class CppPreprocessor; class CppFindReferences; +#ifndef ICHECK_BUILD class CppModelManager : public CppModelManagerInterface { Q_OBJECT @@ -221,6 +231,75 @@ private: CppFindReferences *m_findReferences; bool m_indexerEnabled; }; +#endif + +using namespace CPlusPlus; +class CppPreprocessor: public CPlusPlus::Client +{ +public: +#ifndef ICHECK_BUILD + CppPreprocessor(QPointer<CppModelManager> modelManager); +#else + CppPreprocessor(QPointer<CPlusPlus::ParseManager> modelManager); +#endif + virtual ~CppPreprocessor(); + + void setRevision(unsigned revision); + void setWorkingCopy(const CppModelManagerInterface::WorkingCopy &workingCopy); + void setIncludePaths(const QStringList &includePaths); + void setFrameworkPaths(const QStringList &frameworkPaths); + void setProjectFiles(const QStringList &files); + void setTodo(const QStringList &files); + + void run(const QString &fileName); + + void resetEnvironment(); + + const QSet<QString> &todo() const + { return m_todo; } + +public: // attributes + Snapshot snapshot; + +protected: + CPlusPlus::Document::Ptr switchDocument(CPlusPlus::Document::Ptr doc); + + bool includeFile(const QString &absoluteFilePath, QString *result, unsigned *revision); + QString tryIncludeFile(QString &fileName, IncludeType type, unsigned *revision); + + void mergeEnvironment(CPlusPlus::Document::Ptr doc); + + virtual void macroAdded(const Macro ¯o); + virtual void passedMacroDefinitionCheck(unsigned offset, const Macro ¯o); + virtual void failedMacroDefinitionCheck(unsigned offset, const QByteArray &name); + virtual void startExpandingMacro(unsigned offset, + const Macro ¯o, + const QByteArray &originalText, + bool inCondition, + const QVector<MacroArgumentReference> &actuals); + virtual void stopExpandingMacro(unsigned offset, const Macro ¯o); + virtual void startSkippingBlocks(unsigned offset); + virtual void stopSkippingBlocks(unsigned offset); + virtual void sourceNeeded(QString &fileName, IncludeType type, + unsigned line); + +private: +#ifndef ICHECK_BUILD + QPointer<CppModelManager> m_modelManager; +#endif + Environment env; + Preprocessor preprocess; + QStringList m_includePaths; + QStringList m_systemIncludePaths; + CppModelManagerInterface::WorkingCopy m_workingCopy; + QStringList m_projectFiles; + QStringList m_frameworkPaths; + QSet<QString> m_included; + Document::Ptr m_currentDoc; + QSet<QString> m_todo; + QSet<QString> m_processed; + unsigned m_revision; +}; } // namespace Internal } // namespace CppTools diff --git a/src/shared/cplusplus/AST.cpp b/src/shared/cplusplus/AST.cpp index 084334a9ab4ca396cb3fd1b07daf67d8e8b4f7bc..d394fa369410efd52373224a25cb38708f917c1d 100644 --- a/src/shared/cplusplus/AST.cpp +++ b/src/shared/cplusplus/AST.cpp @@ -144,6 +144,47 @@ unsigned AccessDeclarationAST::lastToken() const return access_specifier_token + 1; } +#ifdef ICHECK_BUILD +unsigned QPropertyDeclarationAST::firstToken() const +{ + return property_specifier_token; +} + +unsigned QPropertyDeclarationAST::lastToken() const +{ + return rparen_token; +} + +unsigned QEnumDeclarationAST::firstToken() const +{ + return enum_specifier_token; +} + +unsigned QEnumDeclarationAST::lastToken() const +{ + return rparen_token; +} + +unsigned QFlagsDeclarationAST::firstToken() const +{ + return this->flags_specifier_token; +} + +unsigned QFlagsDeclarationAST::lastToken() const +{ + return rparen_token; +} + +unsigned QDeclareFlagsDeclarationAST::firstToken() const +{ + return declareflags_specifier_token; +} + +unsigned QDeclareFlagsDeclarationAST::lastToken() const +{ + return rparen_token; +} +#endif unsigned ArrayAccessAST::firstToken() const { @@ -1600,7 +1641,9 @@ unsigned ThrowExpressionAST::lastToken() const unsigned TranslationUnitAST::firstToken() const { - return declaration_list->firstToken(); + if(declaration_list) + return declaration_list->firstToken(); + return 0; } unsigned TranslationUnitAST::lastToken() const diff --git a/src/shared/cplusplus/AST.h b/src/shared/cplusplus/AST.h index a26384b74fd8074aa66416944e511ad3a1745ddc..8bbd9fe9891a5b5195775b28cea18ff4c16b5170 100644 --- a/src/shared/cplusplus/AST.h +++ b/src/shared/cplusplus/AST.h @@ -146,6 +146,12 @@ public: virtual AccessDeclarationAST *asAccessDeclaration() { return 0; } virtual ArrayAccessAST *asArrayAccess() { return 0; } virtual ArrayDeclaratorAST *asArrayDeclarator() { return 0; } +#ifdef ICHECK_BUILD + virtual QPropertyDeclarationAST *asQPropertyDeclarationAST() { return 0; } + virtual QEnumDeclarationAST *asQEnumDeclarationAST() { return 0; } + virtual QFlagsDeclarationAST *asQFlagsDeclarationAST() { return 0; } + virtual QDeclareFlagsDeclarationAST *asQDeclareFlagsDeclarationAST() { return 0; } +#endif virtual ArrayInitializerAST *asArrayInitializer() { return 0; } virtual AsmDefinitionAST *asAsmDefinition() { return 0; } virtual AttributeAST *asAttribute() { return 0; } @@ -298,6 +304,9 @@ class CPLUSPLUS_EXPORT DeclarationAST: public AST { public: virtual DeclarationAST *asDeclaration() { return this; } +#ifdef ICHECK_BUILD + unsigned invoke_token; +#endif }; class CPLUSPLUS_EXPORT NameAST: public ExpressionAST @@ -502,6 +511,109 @@ protected: virtual bool match0(AST *, ASTMatcher *); }; +#ifdef ICHECK_BUILD +class CPLUSPLUS_EXPORT QPropertyDeclarationAST: public DeclarationAST +{ + /* + Q_PROPERTY(type name + READ getFunction + [WRITE setFunction] + [RESET resetFunction] + [NOTIFY notifySignal] + [DESIGNABLE bool] + [SCRIPTABLE bool] + [STORED bool] + [USER bool] + [CONSTANT] + [FINAL])*/ +public: + unsigned property_specifier_token; + unsigned lparen_token; + unsigned type_token; + unsigned type_name_token; + unsigned read_token; + unsigned read_function_token; + unsigned write_token; + unsigned write_function_token; + unsigned reset_token; + unsigned reset_function_token; + unsigned notify_token; + unsigned notify_function_token; + unsigned rparen_token; + +public: + virtual QPropertyDeclarationAST *asQPropertyDeclarationAST() { return this; } + + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + +protected: + virtual void accept0(ASTVisitor *visitor); + virtual bool match0(AST *, ASTMatcher *); +}; + +class CPLUSPLUS_EXPORT QEnumDeclarationAST: public DeclarationAST +{ + /*Q_ENUMS(enum1, enum2)*/ +public: + unsigned enum_specifier_token; + unsigned lparen_token; + unsigned rparen_token; + EnumeratorListAST *enumerator_list; + +public: + virtual QEnumDeclarationAST *asQEnumDeclarationAST() { return this; } + + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + +protected: + virtual void accept0(ASTVisitor *visitor); + virtual bool match0(AST *, ASTMatcher *); +}; + +class CPLUSPLUS_EXPORT QFlagsDeclarationAST: public DeclarationAST +{ + /*Q_FLAGS(enum1 enum2 flags1 ...)*/ +public: + unsigned flags_specifier_token; + unsigned lparen_token; + unsigned rparen_token; + EnumeratorListAST *enumerator_list; + +public: + virtual QFlagsDeclarationAST *asQFlagsDeclarationAST() { return this; } + + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + +protected: + virtual void accept0(ASTVisitor *visitor); + virtual bool match0(AST *, ASTMatcher *); +}; + +class CPLUSPLUS_EXPORT QDeclareFlagsDeclarationAST: public DeclarationAST +{ + /*Q_DECLARE_FLAGS(flag enum)*/ +public: + unsigned declareflags_specifier_token; + unsigned lparen_token; + unsigned flag_token; + unsigned enum_token; + unsigned rparen_token; + +public: + virtual QDeclareFlagsDeclarationAST *asQDeclareFlagsDeclarationAST() { return this; } + + virtual unsigned firstToken() const; + virtual unsigned lastToken() const; + +protected: + virtual void accept0(ASTVisitor *visitor); + virtual bool match0(AST *, ASTMatcher *); +}; +#endif + class CPLUSPLUS_EXPORT AsmDefinitionAST: public DeclarationAST { public: diff --git a/src/shared/cplusplus/ASTMatch0.cpp b/src/shared/cplusplus/ASTMatch0.cpp index e16c0788080f0b8e08d6b74d580365545358fb7b..1d329a856afc33691098d8613ea7779f68293ed4 100644 --- a/src/shared/cplusplus/ASTMatch0.cpp +++ b/src/shared/cplusplus/ASTMatch0.cpp @@ -96,6 +96,40 @@ bool AccessDeclarationAST::match0(AST *pattern, ASTMatcher *matcher) return false; } +#ifdef ICHECK_BUILD +bool QPropertyDeclarationAST::match0(AST *pattern, ASTMatcher *matcher) +{ + if (QPropertyDeclarationAST *_other = pattern->asQPropertyDeclarationAST()) + return matcher->match(this, _other); + + return false; +} + +bool QEnumDeclarationAST::match0(AST *pattern, ASTMatcher *matcher) +{ + if (QEnumDeclarationAST *_other = pattern->asQEnumDeclarationAST()) + return matcher->match(this, _other); + + return false; +} + +bool QFlagsDeclarationAST::match0(AST *pattern, ASTMatcher *matcher) +{ + if (QFlagsDeclarationAST *_other = pattern->asQFlagsDeclarationAST()) + return matcher->match(this, _other); + + return false; +} + +bool QDeclareFlagsDeclarationAST::match0(AST *pattern, ASTMatcher *matcher) +{ + if (QDeclareFlagsDeclarationAST *_other = pattern->asQDeclareFlagsDeclarationAST()) + return matcher->match(this, _other); + + return false; +} +#endif + bool AsmDefinitionAST::match0(AST *pattern, ASTMatcher *matcher) { if (AsmDefinitionAST *_other = pattern->asAsmDefinition()) diff --git a/src/shared/cplusplus/ASTMatcher.cpp b/src/shared/cplusplus/ASTMatcher.cpp index 138950c2309307b761cf1c61ddd794db4e678f63..73decce35076d8b76367149b08d94a77e2763a25 100644 --- a/src/shared/cplusplus/ASTMatcher.cpp +++ b/src/shared/cplusplus/ASTMatcher.cpp @@ -195,8 +195,74 @@ bool ASTMatcher::match(AccessDeclarationAST *node, AccessDeclarationAST *pattern pattern->colon_token = node->colon_token; +#ifdef ICHECK_BUILD + pattern->invoke_token = node->invoke_token; +#endif + + return true; +} + +#ifdef ICHECK_BUILD +bool ASTMatcher::match(QPropertyDeclarationAST *node, QPropertyDeclarationAST *pattern) +{ + (void) node; + (void) pattern; + + pattern->property_specifier_token = node->property_specifier_token; + + pattern->type_name_token = node->type_name_token; + + pattern->read_function_token = node->read_function_token; + + pattern->write_function_token = node->write_function_token; + + pattern->notify_function_token = node->notify_function_token; + + return true; +} + +bool ASTMatcher::match(QEnumDeclarationAST *node, QEnumDeclarationAST *pattern) +{ + (void) node; + (void) pattern; + + pattern->enum_specifier_token = node->enum_specifier_token; + + if (! pattern->enumerator_list) + pattern->enumerator_list = node->enumerator_list; + else if (! AST::match(node->enumerator_list, pattern->enumerator_list, this)) + return false; + + return true; +} + +bool ASTMatcher::match(QFlagsDeclarationAST *node, QFlagsDeclarationAST *pattern) +{ + (void) node; + (void) pattern; + + pattern->flags_specifier_token = node->flags_specifier_token; + + if (! pattern->enumerator_list) + pattern->enumerator_list = node->enumerator_list; + else if (! AST::match(node->enumerator_list, pattern->enumerator_list, this)) + return false; + + return true; +} + +bool ASTMatcher::match(QDeclareFlagsDeclarationAST *node, QDeclareFlagsDeclarationAST *pattern) +{ + (void) node; + (void) pattern; + + pattern->declareflags_specifier_token = node->declareflags_specifier_token; + pattern->flag_token = node->flag_token; + pattern->enum_token = node->enum_token; + return true; } +#endif bool ASTMatcher::match(AsmDefinitionAST *node, AsmDefinitionAST *pattern) { diff --git a/src/shared/cplusplus/ASTMatcher.h b/src/shared/cplusplus/ASTMatcher.h index c3490ac69be4f60ff8f1aa1dd102d76991ada103..065ee663599fc9492a80768850ed7dc3b7ac161b 100644 --- a/src/shared/cplusplus/ASTMatcher.h +++ b/src/shared/cplusplus/ASTMatcher.h @@ -40,6 +40,12 @@ public: virtual ~ASTMatcher(); virtual bool match(AccessDeclarationAST *node, AccessDeclarationAST *pattern); +#ifdef ICHECK_BUILD + virtual bool match(QPropertyDeclarationAST *node, QPropertyDeclarationAST *pattern); + virtual bool match(QEnumDeclarationAST *node, QEnumDeclarationAST *pattern); + virtual bool match(QFlagsDeclarationAST *node, QFlagsDeclarationAST *pattern); + virtual bool match(QDeclareFlagsDeclarationAST *node, QDeclareFlagsDeclarationAST *pattern); +#endif virtual bool match(ArrayAccessAST *node, ArrayAccessAST *pattern); virtual bool match(ArrayDeclaratorAST *node, ArrayDeclaratorAST *pattern); virtual bool match(ArrayInitializerAST *node, ArrayInitializerAST *pattern); diff --git a/src/shared/cplusplus/ASTVisit.cpp b/src/shared/cplusplus/ASTVisit.cpp index 070cf7fd8569854c44067d89d3dd71b970a76002..4b08ea6375d2c2195edff530f752c6a5622fd5fe 100644 --- a/src/shared/cplusplus/ASTVisit.cpp +++ b/src/shared/cplusplus/ASTVisit.cpp @@ -99,6 +99,36 @@ void AccessDeclarationAST::accept0(ASTVisitor *visitor) visitor->endVisit(this); } +#ifdef ICHECK_BUILD +void QPropertyDeclarationAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + } + visitor->endVisit(this); +} + +void QEnumDeclarationAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + } + visitor->endVisit(this); +} + +void QFlagsDeclarationAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + } + visitor->endVisit(this); +} + +void QDeclareFlagsDeclarationAST::accept0(ASTVisitor *visitor) +{ + if (visitor->visit(this)) { + } + visitor->endVisit(this); +} +#endif + void AsmDefinitionAST::accept0(ASTVisitor *visitor) { if (visitor->visit(this)) { diff --git a/src/shared/cplusplus/ASTVisitor.h b/src/shared/cplusplus/ASTVisitor.h index d4ebdcc81abfaedae65c15b45b39e9dc3cc71021..701abd80c8fff6c5dcff102804e77e73ecbafe8a 100644 --- a/src/shared/cplusplus/ASTVisitor.h +++ b/src/shared/cplusplus/ASTVisitor.h @@ -103,6 +103,12 @@ public: virtual void postVisit(AST *) {} virtual bool visit(AccessDeclarationAST *) { return true; } +#ifdef ICHECK_BUILD + virtual bool visit(QPropertyDeclarationAST *) { return true; } + virtual bool visit(QEnumDeclarationAST *) { return true; } + virtual bool visit(QFlagsDeclarationAST *) { return true; } + virtual bool visit(QDeclareFlagsDeclarationAST *) { return true; } +#endif virtual bool visit(ArrayAccessAST *) { return true; } virtual bool visit(ArrayDeclaratorAST *) { return true; } virtual bool visit(ArrayInitializerAST *) { return true; } @@ -229,6 +235,12 @@ public: virtual bool visit(ObjCSynchronizedStatementAST *) { return true; } virtual void endVisit(AccessDeclarationAST *) { } +#ifdef ICHECK_BUILD + virtual void endVisit(QPropertyDeclarationAST *) { } + virtual void endVisit(QEnumDeclarationAST *) { } + virtual void endVisit(QFlagsDeclarationAST *) { } + virtual void endVisit(QDeclareFlagsDeclarationAST *) { } +#endif virtual void endVisit(ArrayAccessAST *) { } virtual void endVisit(ArrayDeclaratorAST *) { } virtual void endVisit(ArrayInitializerAST *) { } diff --git a/src/shared/cplusplus/ASTfwd.h b/src/shared/cplusplus/ASTfwd.h index cefdfdc3815c9e719c2f3920c6059a42a54f28d9..e38739c01edd2368482a8340a6cdbdbee81b4051 100644 --- a/src/shared/cplusplus/ASTfwd.h +++ b/src/shared/cplusplus/ASTfwd.h @@ -60,6 +60,12 @@ class ASTVisitor; class ASTMatcher; class AccessDeclarationAST; +#ifdef ICHECK_BUILD + class QPropertyDeclarationAST; + class QEnumDeclarationAST; + class QFlagsDeclarationAST; + class QDeclareFlagsDeclarationAST; +#endif class ArrayAccessAST; class ArrayDeclaratorAST; class ArrayInitializerAST; diff --git a/src/shared/cplusplus/CPlusPlusForwardDeclarations.h b/src/shared/cplusplus/CPlusPlusForwardDeclarations.h index 836257e04f00f46a068f7032b2c0112c7eca5c38..caa90a552349a0e81e48910a30fdc70791dace5b 100644 --- a/src/shared/cplusplus/CPlusPlusForwardDeclarations.h +++ b/src/shared/cplusplus/CPlusPlusForwardDeclarations.h @@ -60,7 +60,11 @@ # elif defined(CPLUSPLUS_BUILD_STATIC_LIB) # define CPLUSPLUS_EXPORT # else -# define CPLUSPLUS_EXPORT Q_DECL_IMPORT +# ifdef ICHECK_BUILD +# define CPLUSPLUS_EXPORT +# else +# define CPLUSPLUS_EXPORT Q_DECL_IMPORT +# endif # endif #else # define CPLUSPLUS_EXPORT diff --git a/src/shared/cplusplus/CheckDeclaration.cpp b/src/shared/cplusplus/CheckDeclaration.cpp index 9758f306a2214dd80ccc135dfd7d7d7589e28ac1..c6f747d3ddb8a2298efaa7f83e6bcc053fe80ce0 100644 --- a/src/shared/cplusplus/CheckDeclaration.cpp +++ b/src/shared/cplusplus/CheckDeclaration.cpp @@ -170,6 +170,9 @@ bool CheckDeclaration::visit(SimpleDeclarationAST *ast) const bool isQ_SLOT = ast->qt_invokable_token && tokenKind(ast->qt_invokable_token) == T_Q_SLOT; const bool isQ_SIGNAL = ast->qt_invokable_token && tokenKind(ast->qt_invokable_token) == T_Q_SIGNAL; +#ifdef ICHECK_BUILD + const bool isQ_INVOKABLE = (ast->invoke_token > 0); +#endif List<Declaration *> **decl_it = &ast->symbols; for (DeclaratorListAST *it = ast->declarator_list; it; it = it->next) { @@ -196,6 +199,10 @@ bool CheckDeclaration::visit(SimpleDeclarationAST *ast) fun->setMethodKey(Function::SignalMethod); else if (isQ_SLOT) fun->setMethodKey(Function::SlotMethod); +#ifdef ICHECK_BUILD + else if (isQ_INVOKABLE) + fun->setInvokable(true); +#endif fun->setVisibility(semantic()->currentVisibility()); } else if (semantic()->currentMethodKey() != Function::NormalMethod) { translationUnit()->warning(ast->firstToken(), @@ -259,6 +266,28 @@ bool CheckDeclaration::visit(AccessDeclarationAST *ast) return false; } +#ifdef ICHECK_BUILD +bool CheckDeclaration::visit(QPropertyDeclarationAST *) +{ + return false; +} + +bool CheckDeclaration::visit(QEnumDeclarationAST *) +{ + return false; +} + +bool CheckDeclaration::visit(QFlagsDeclarationAST *) +{ + return false; +} + +bool CheckDeclaration::visit(QDeclareFlagsDeclarationAST *) +{ + return false; +} +#endif + bool CheckDeclaration::visit(AsmDefinitionAST *) { return false; @@ -316,11 +345,18 @@ bool CheckDeclaration::visit(FunctionDefinitionAST *ast) const bool isQ_SLOT = ast->qt_invokable_token && tokenKind(ast->qt_invokable_token) == T_Q_SLOT; const bool isQ_SIGNAL = ast->qt_invokable_token && tokenKind(ast->qt_invokable_token) == T_Q_SIGNAL; +#ifdef ICHECK_BUILD + const bool isQ_INVOKABLE = (ast->invoke_token > 0); +#endif if (isQ_SIGNAL) fun->setMethodKey(Function::SignalMethod); else if (isQ_SLOT) fun->setMethodKey(Function::SlotMethod); +#ifdef ICHECK_BUILD + else if (isQ_INVOKABLE) + fun->setInvokable(true); +#endif checkFunctionArguments(fun); diff --git a/src/shared/cplusplus/CheckDeclaration.h b/src/shared/cplusplus/CheckDeclaration.h index 0e11a5398b44cb8d1cc519f92134306b0a246aae..0090a1d6708f608fd25b432a9af09e59d307995f 100644 --- a/src/shared/cplusplus/CheckDeclaration.h +++ b/src/shared/cplusplus/CheckDeclaration.h @@ -77,6 +77,12 @@ protected: virtual bool visit(SimpleDeclarationAST *ast); virtual bool visit(EmptyDeclarationAST *ast); virtual bool visit(AccessDeclarationAST *ast); +#ifdef ICHECK_BUILD + virtual bool visit(QPropertyDeclarationAST *ast); + virtual bool visit(QEnumDeclarationAST *ast); + virtual bool visit(QFlagsDeclarationAST *ast); + virtual bool visit(QDeclareFlagsDeclarationAST *ast); +#endif virtual bool visit(AsmDefinitionAST *ast); virtual bool visit(ExceptionDeclarationAST *ast); virtual bool visit(FunctionDefinitionAST *ast); diff --git a/src/shared/cplusplus/Keywords.cpp b/src/shared/cplusplus/Keywords.cpp index 6da25125f7b6e0c8657fc8b0b55518c3077fc4b4..51757eb8c86dcecba0cd7db2fce0e64e89f8cdf9 100644 --- a/src/shared/cplusplus/Keywords.cpp +++ b/src/shared/cplusplus/Keywords.cpp @@ -718,6 +718,30 @@ static inline int classify7(const char *s, bool q) { } } } +#ifdef ICHECK_BUILD + else if (s[2] == 'E') { + if (s[3] == 'N') { + if (s[4] == 'U') { + if (s[5] == 'M') { + if (s[6] == 'S') { + return T_Q_ENUMS; + } + } + } + } + } + else if (s[2] == 'F') { + if (s[3] == 'L') { + if (s[4] == 'A') { + if (s[5] == 'G') { + if (s[6] == 'S') { + return T_Q_FLAGS; + } + } + } + } + } +#endif } } return T_IDENTIFIER; @@ -1079,6 +1103,29 @@ static inline int classify10(const char *s, bool) { } } } +#ifdef ICHECK_BUILD + else if (s[0] == 'Q') { + if (s[1] == '_') { + if (s[2] == 'P') { + if (s[3] == 'R') { + if (s[4] == 'O') { + if (s[5] == 'P') { + if (s[6] == 'E') { + if (s[7] == 'R') { + if (s[8] == 'T') { + if (s[9] == 'Y') { + return T_Q_PROPERTY; + } + } + } + } + } + } + } + } + } + } +#endif return T_IDENTIFIER; } @@ -1129,6 +1176,31 @@ static inline int classify11(const char *s, bool) { } } } +#ifdef ICHECK_BUILD + else if (s[0] == 'Q') { + if (s[1] == '_') { + if (s[2] == 'I') { + if (s[3] == 'N') { + if (s[4] == 'V') { + if (s[5] == 'O') { + if (s[6] == 'K') { + if (s[7] == 'A') { + if (s[8] == 'B') { + if (s[9] == 'L') { + if (s[10] == 'E') { + return T_Q_INVOKABLE; + } + } + } + } + } + } + } + } + } + } + } +#endif return T_IDENTIFIER; } @@ -1217,6 +1289,43 @@ static inline int classify13(const char *s, bool) { return T_IDENTIFIER; } +#ifdef ICHECK_BUILD +static inline int classify15(const char *s, bool) { + if (s[0] == 'Q') { + if (s[1] == '_') { + if (s[2] == 'D') { + if (s[3] == 'E') { + if (s[4] == 'C') { + if (s[5] == 'L') { + if (s[6] == 'A') { + if (s[7] == 'R') { + if (s[8] == 'E') { + if (s[9] == '_') { + if (s[10] == 'F') { + if (s[11] == 'L') { + if (s[12] == 'A') { + if (s[13] == 'G') { + if (s[14] == 'S') { + return T_Q_DECLARE_FLAGS; + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + return T_IDENTIFIER; +} +#endif + static inline int classify16(const char *s, bool) { if (s[0] == 'r') { if (s[1] == 'e') { @@ -1268,6 +1377,9 @@ int Lexer::classify(const char *s, int n, bool q) { case 11: return classify11(s, q); case 12: return classify12(s, q); case 13: return classify13(s, q); +#ifdef ICHECK_BUILD + case 15: return classify15(s, q); +#endif case 16: return classify16(s, q); default: return T_IDENTIFIER; } // switch diff --git a/src/shared/cplusplus/Parser.cpp b/src/shared/cplusplus/Parser.cpp index b40c59c4b7db8ed9bff472669b4bccce986a80d2..ae22e72745eaff895eb66fbc51b5e108764f2019 100644 --- a/src/shared/cplusplus/Parser.cpp +++ b/src/shared/cplusplus/Parser.cpp @@ -54,6 +54,9 @@ #include "Literals.h" #include "ObjectiveCTypeQualifiers.h" #include <cstdio> // for putchar +#ifdef ICHECK_BUILD +# include <QString> +#endif #define CPLUSPLUS_NO_DEBUG_RULE @@ -1651,6 +1654,158 @@ bool Parser::parseAccessDeclaration(DeclarationAST *&node) return false; } +#ifdef ICHECK_BUILD +bool Parser::parseQPropertyDeclaration(DeclarationAST *&node) +{ + /* + Q_PROPERTY(type name + READ getFunction + [WRITE setFunction] + [RESET resetFunction] + [NOTIFY notifySignal] + [DESIGNABLE bool] + [SCRIPTABLE bool] + [STORED bool] + [USER bool] + [CONSTANT] + [FINAL])*/ + DEBUG_THIS_RULE(); + if (LA() == T_Q_PROPERTY) { + QPropertyDeclarationAST *ast = new (_pool)QPropertyDeclarationAST; + ast->property_specifier_token = consumeToken(); + if(LA() == T_LPAREN){ + ast->lparen_token = consumeToken(); + QString tokenstr; + tokenstr = tok().spell(); + //read the type and the name of the type + if(tokenstr != "READ" ){ + ast->type_token = consumeToken(); + tokenstr = tok().spell(); + } + if(tokenstr != "READ" ){ + ast->type_name_token = consumeToken(); + tokenstr = tok().spell(); + } + unsigned fctdefinition = 0; + unsigned fctname = 0; + for(int i = 0; i < 18; i++){ + if(cursor() < _translationUnit->tokenCount() - 1){ + if(LA() == T_RPAREN){ + ast->rparen_token = consumeToken(); + break; + } + tokenstr = tok().spell(); + fctdefinition = consumeToken(); + fctname = consumeToken(); + if(tokenstr == "READ"){ + ast->read_token = fctdefinition; + ast->read_function_token = fctname; + } + else if(tokenstr == "WRITE"){ + ast->write_token = fctdefinition; + ast->write_function_token = fctname; + } + else if(tokenstr == "RESET"){ + ast->reset_token = fctdefinition; + ast->reset_function_token = fctname; + } + else if(tokenstr == "NOTIFY"){ + ast->notify_token = fctdefinition; + ast->notify_function_token = fctname; + } + } + } + } + node = ast; + return true; + } + return false; +} + +bool Parser::parseQEnumDeclaration(DeclarationAST *&node) +{ + /*Q_ENUMS(ConnectionState)*/ + DEBUG_THIS_RULE(); + if (LA() == T_Q_ENUMS) { + QEnumDeclarationAST *ast = new (_pool)QEnumDeclarationAST; + ast->enum_specifier_token = consumeToken(); + EnumeratorListAST** enumerator_list_ptr; + enumerator_list_ptr = &ast->enumerator_list; + + if(LA() == T_LPAREN){ + ast->lparen_token = consumeToken(); + while(LA() != T_EOF_SYMBOL && LA() != T_RPAREN){ + *enumerator_list_ptr = new (_pool) EnumeratorListAST; + EnumeratorAST *pdecl = new (_pool) EnumeratorAST; + pdecl->identifier_token = consumeToken(); + (*enumerator_list_ptr)->value = pdecl; + enumerator_list_ptr = &(*enumerator_list_ptr)->next; + if (LA() == T_COMMA) + consumeToken(); + } + if(LA() == T_RPAREN) + ast->rparen_token = consumeToken(); + } + node = ast; + return true; + } + return false; +} + +bool Parser::parseQFlags(DeclarationAST *&node) +{ + /*Q_FLAGS(enum1 enum2 flags1)*/ + DEBUG_THIS_RULE(); + if (LA() == T_Q_FLAGS) { + QFlagsDeclarationAST *ast = new (_pool)QFlagsDeclarationAST; + ast->flags_specifier_token = consumeToken(); + EnumeratorListAST** enumerator_list_ptr; + enumerator_list_ptr = &ast->enumerator_list; + if(LA() == T_LPAREN){ + ast->lparen_token = consumeToken(); + while(LA() != T_EOF_SYMBOL && LA() != T_RPAREN){ + *enumerator_list_ptr = new (_pool) EnumeratorListAST; + EnumeratorAST *pdecl = new (_pool) EnumeratorAST; + pdecl->identifier_token = consumeToken(); + (*enumerator_list_ptr)->value = pdecl; + enumerator_list_ptr = &(*enumerator_list_ptr)->next; + if (LA() == T_COMMA) + consumeToken(); + } + if(LA() == T_RPAREN) + ast->rparen_token = consumeToken(); + } + node = ast; + return true; + } + return false; +} + +bool Parser::parseQDeclareFlags(DeclarationAST *&node) +{ + /*Q_DECLARE_FLAGS(flag enum)*/ + DEBUG_THIS_RULE(); + if (LA() == T_Q_DECLARE_FLAGS) { + QDeclareFlagsDeclarationAST *ast = new (_pool)QDeclareFlagsDeclarationAST; + ast->declareflags_specifier_token = consumeToken(); + if(LA() == T_LPAREN){ + ast->lparen_token = consumeToken(); + if(LA() != T_EOF_SYMBOL) + ast->flag_token = consumeToken(); + if(LA() == T_COMMA && LA() != T_EOF_SYMBOL) + consumeToken(); + if(LA() != T_EOF_SYMBOL) + ast->enum_token = consumeToken(); + if(LA() != T_EOF_SYMBOL && LA() == T_RPAREN) + ast->rparen_token = consumeToken(); + } + node = ast; + return true; + } + return false; +} +#endif + bool Parser::parseMemberSpecification(DeclarationAST *&node) { DEBUG_THIS_RULE(); @@ -1670,6 +1825,20 @@ bool Parser::parseMemberSpecification(DeclarationAST *&node) case T_PRIVATE: return parseAccessDeclaration(node); +#ifdef ICHECK_BUILD + case T_Q_PROPERTY: + return parseQPropertyDeclaration(node); + + case T_Q_ENUMS: + return parseQEnumDeclaration(node); + + case T_Q_FLAGS: + return parseQFlags(node); + + case T_Q_DECLARE_FLAGS: + return parseQDeclareFlags(node); +#endif + default: return parseSimpleDeclaration(node, /*acceptStructDeclarator=*/true); } // switch @@ -2780,6 +2949,11 @@ bool Parser::parseSimpleDeclaration(DeclarationAST *&node, unsigned qt_invokable_token = 0; if (acceptStructDeclarator && (LA() == T_Q_SIGNAL || LA() == T_Q_SLOT)) qt_invokable_token = consumeToken(); +#ifdef ICHECK_BUILD + unsigned invoke_token = 0; + if (LA() == T_Q_INVOKABLE) + invoke_token = consumeToken(); +#endif // parse a simple declaration, a function definition, // or a contructor declaration. @@ -2907,6 +3081,9 @@ bool Parser::parseSimpleDeclaration(DeclarationAST *&node, } SimpleDeclarationAST *ast = new (_pool) SimpleDeclarationAST; ast->qt_invokable_token = qt_invokable_token; +#ifdef ICHECK_BUILD + ast->invoke_token = invoke_token; +#endif ast->decl_specifier_list = decl_specifier_seq; ast->declarator_list = declarator_list; match(T_SEMICOLON, &ast->semicolon_token); @@ -2936,6 +3113,9 @@ bool Parser::parseSimpleDeclaration(DeclarationAST *&node, if (LA() == T_LBRACE || hasCtorInitializer) { FunctionDefinitionAST *ast = new (_pool) FunctionDefinitionAST; ast->qt_invokable_token = qt_invokable_token; +#ifdef ICHECK_BUILD + ast->invoke_token = invoke_token; +#endif ast->decl_specifier_list = decl_specifier_seq; ast->declarator = firstDeclarator; ast->ctor_initializer = ctor_initializer; @@ -2945,6 +3125,9 @@ bool Parser::parseSimpleDeclaration(DeclarationAST *&node, } else if (LA() == T_TRY) { FunctionDefinitionAST *ast = new (_pool) FunctionDefinitionAST; ast->qt_invokable_token = qt_invokable_token; +#ifdef ICHECK_BUILD + ast->invoke_token = invoke_token; +#endif ast->decl_specifier_list = decl_specifier_seq; ast->declarator = firstDeclarator; ast->ctor_initializer = ctor_initializer; diff --git a/src/shared/cplusplus/Parser.h b/src/shared/cplusplus/Parser.h index 9fa6abb166583813881338b7c0a2de7e49e906bc..62e1a6941857ee1d8a45ede8c93faa48e8ad77f3 100644 --- a/src/shared/cplusplus/Parser.h +++ b/src/shared/cplusplus/Parser.h @@ -78,6 +78,12 @@ public: bool parseAbstractDeclarator(DeclaratorAST *&node); bool parseEmptyDeclaration(DeclarationAST *&node); bool parseAccessDeclaration(DeclarationAST *&node); +#ifdef ICHECK_BUILD + bool parseQPropertyDeclaration(DeclarationAST *&node); + bool parseQEnumDeclaration(DeclarationAST *&node); + bool parseQFlags(DeclarationAST *&node); + bool parseQDeclareFlags(DeclarationAST *&node); +#endif bool parseAdditiveExpression(ExpressionAST *&node); bool parseAndExpression(ExpressionAST *&node); bool parseAsmDefinition(DeclarationAST *&node); diff --git a/src/shared/cplusplus/Symbols.cpp b/src/shared/cplusplus/Symbols.cpp index e19e2d123bf9747fd591e908269722288260f29c..8b1a15e79dba43613c6a86ff0b87d0c750d382b8 100644 --- a/src/shared/cplusplus/Symbols.cpp +++ b/src/shared/cplusplus/Symbols.cpp @@ -221,6 +221,10 @@ bool Function::isEqualTo(const Type *other) const return false; else if (isVolatile() != o->isVolatile()) return false; +#ifdef ICHECK_BUILD + else if (isInvokable() != o->isInvokable()) + return false; +#endif const Name *l = identity(); const Name *r = o->identity(); @@ -240,6 +244,35 @@ bool Function::isEqualTo(const Type *other) const return false; } +#ifdef ICHECK_BUILD +bool Function::isEqualTo(const Function* fct, bool ignoreName/* = false*/) const +{ + if(!ignoreName) + return isEqualTo((Type*)fct); + + if (! fct) + return false; + else if (isConst() != fct->isConst()) + return false; + else if (isVolatile() != fct->isVolatile()) + return false; + else if (isInvokable() != fct->isInvokable()) + return false; + + if (_arguments->symbolCount() != fct->_arguments->symbolCount()) + return false; + else if (! _returnType.isEqualTo(fct->_returnType)) + return false; + for (unsigned i = 0; i < _arguments->symbolCount(); ++i) { + Symbol *l = _arguments->symbolAt(i); + Symbol *r = fct->_arguments->symbolAt(i); + if (! l->type().isEqualTo(r->type())) + return false; + } + return true; +} +#endif + void Function::accept0(TypeVisitor *visitor) { visitor->visit(this); } @@ -316,6 +349,16 @@ bool Function::isPureVirtual() const void Function::setPureVirtual(bool isPureVirtual) { f._isPureVirtual = isPureVirtual; } +#ifdef ICHECK_BUILD + +bool Function::isInvokable() const +{ return f._isInvokable == 1; } + +void Function::setInvokable(bool isInvokable) +{ f._isInvokable = isInvokable; } + +#endif + bool Function::isAmbiguous() const { return f._isAmbiguous; } diff --git a/src/shared/cplusplus/Symbols.h b/src/shared/cplusplus/Symbols.h index 4d8d87f360ece192c5cb18cd15430fd128a5c96b..c1a1f37926454c4813481f76b2cf29763b7bea50 100644 --- a/src/shared/cplusplus/Symbols.h +++ b/src/shared/cplusplus/Symbols.h @@ -350,6 +350,14 @@ public: bool isPureVirtual() const; void setPureVirtual(bool isPureVirtual); +#ifdef ICHECK_BUILD + + bool isInvokable() const; + void setInvokable(bool isInvokable); + bool isEqualTo(const Function* fct, bool ignoreName = false) const; + +#endif + // Symbol's interface virtual FullySpecifiedType type() const; @@ -387,6 +395,9 @@ private: unsigned _isVolatile: 1; unsigned _isAmbiguous: 1; unsigned _methodKey: 3; +#ifdef ICHECK_BUILD + unsigned _isInvokable: 1; +#endif }; union { unsigned _flags; diff --git a/src/shared/cplusplus/Token.cpp b/src/shared/cplusplus/Token.cpp index ce661e43b0589acceee16473bba35bd2ad5f4b01..61c22b7cb257499d6ffa3533daa125dfa8189119 100644 --- a/src/shared/cplusplus/Token.cpp +++ b/src/shared/cplusplus/Token.cpp @@ -91,7 +91,11 @@ static const char *token_names[] = { ("@protected"), ("@protocol"), ("@public"), ("@required"), ("@selector"), ("@synchronized"), ("@synthesize"), ("@throw"), ("@try"), - ("SIGNAL"), ("SLOT"), ("Q_SIGNAL"), ("Q_SLOT"), ("signals"), ("slots"), ("Q_FOREACH"), ("Q_D"), ("Q_Q") + ("SIGNAL"), ("SLOT"), ("Q_SIGNAL"), ("Q_SLOT"), ("signals"), ("slots"), + ("Q_FOREACH"), ("Q_D"), ("Q_Q"), +#ifdef ICHECK_BUILD + ("Q_INVOKABLE"), ("Q_PROPERTY"), ("Q_ENUMS"), ("Q_FLAGS"), ("Q_DECLARE_FLAGS") +#endif }; Token::Token() : diff --git a/src/shared/cplusplus/Token.h b/src/shared/cplusplus/Token.h index cd1cf577c6d59bdb92411db93b49464ae0708768..1a24eb52b6c281303aac249c3e10da0b094b678a 100644 --- a/src/shared/cplusplus/Token.h +++ b/src/shared/cplusplus/Token.h @@ -238,9 +238,16 @@ enum Kind { T_Q_FOREACH, T_Q_D, T_Q_Q, - +#ifndef ICHECK_BUILD T_LAST_KEYWORD = T_Q_Q, - +#else + T_Q_INVOKABLE, + T_Q_PROPERTY, + T_Q_ENUMS, + T_Q_FLAGS, + T_Q_DECLARE_FLAGS, + T_LAST_KEYWORD = T_Q_DECLARE_FLAGS, +#endif // aliases T_OR = T_PIPE_PIPE, T_AND = T_AMPER_AMPER, diff --git a/src/tools/ICheck/ICheck.pri b/src/tools/ICheck/ICheck.pri new file mode 100644 index 0000000000000000000000000000000000000000..22772cc4b1c22bf799a519c5ed59399864fe2430 --- /dev/null +++ b/src/tools/ICheck/ICheck.pri @@ -0,0 +1,5 @@ +# ---------------------------------------------------- +# This file is generated by the Qt Visual Studio Add-in. +# ------------------------------------------------------ + +SOURCES += ./main.cpp diff --git a/src/tools/ICheck/ICheck.pro b/src/tools/ICheck/ICheck.pro new file mode 100644 index 0000000000000000000000000000000000000000..75a1f24c02ec342fb5cfd8c726f936f30a30f2cb --- /dev/null +++ b/src/tools/ICheck/ICheck.pro @@ -0,0 +1,6 @@ +TEMPLATE = subdirs +CONFIG += ordered + +SUBDIRS = \ + ICheckLib \ + ICheckApp diff --git a/src/tools/ICheck/ICheckApp/ICheckApp.pro b/src/tools/ICheck/ICheckApp/ICheckApp.pro new file mode 100644 index 0000000000000000000000000000000000000000..c841d43072f399e2013301d3e8665c56191b0742 --- /dev/null +++ b/src/tools/ICheck/ICheckApp/ICheckApp.pro @@ -0,0 +1,23 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2010-01-18T15:27:35 +# +#------------------------------------------------- + +QT -= gui + +TARGET = ICheckApp +CONFIG += console +CONFIG -= app_bundle + +TEMPLATE = app + +INCLUDEPATH += ../ICheckLib +CONFIG(debug, debug|release){ + LIBS += -L../ICheckLib/debug -lICheckLibd +} +else { + LIBS += -L../ICheckLib/release -lICheckLib +} + +SOURCES += main.cpp diff --git a/src/tools/ICheck/ICheckApp/main.cpp b/src/tools/ICheck/ICheckApp/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..94e9a999b5215f8c68678ff064d8422f6696b36e --- /dev/null +++ b/src/tools/ICheck/ICheckApp/main.cpp @@ -0,0 +1,129 @@ +#include "ichecklib.h" +#include <QtCore/QCoreApplication> +#include <QString> +#include <QStringList> +#include <iostream> +#include <QDebug> +#include <QDir> +#include <QFile> +#include <QFileInfo> +#include <QProcess> + +using namespace std; + +QStringList getQTIncludePath() +{ + QStringList ret; + QStringList processevironment = QProcess::systemEnvironment(); + foreach(QString item, processevironment){ + if(item.indexOf("QTDIR=") == 0){ + QString qtpath = item.remove("QTDIR="); + ret << qtpath + "\\include\\QtCore"; + break; + } + } + return ret; +} + +int main(int argc, char *argv[]) +{ + int ret = 0; + if(argc == 3){ + try{ + //Extract the file name and path from the arguments + QString interfaceHeaderFile = argv[1]; + QString checkHeaderFile = argv[2]; + QString curpath = QDir::currentPath(); + //Create FileInfos for the header files + QFile ifile(interfaceHeaderFile); + if (!ifile.exists()){ + QString err = "File does not exist: " + interfaceHeaderFile; + throw err; + } + QFile chfile(checkHeaderFile); + if (!chfile.exists()){ + QString err = "File does not exist: " + checkHeaderFile; + throw err; + } + QFileInfo iFileInfo(ifile); + QFileInfo chFileInfo(chfile); + + //Now create a list of the include path + QString chIncludepath = chFileInfo.absolutePath(); + QStringList chIncludepathlist; + chIncludepathlist << chIncludepath; + chIncludepathlist << getQTIncludePath(); + + QString iIncludepath = iFileInfo.absolutePath(); + QStringList iIncludepathlist; + iIncludepathlist << iIncludepath; + + //Create a list of all the soucre files they need to be parsed. + //In our case it is just the header file + QStringList chFilelist; + chFilelist << chFileInfo.filePath(); + + QStringList iFilelist; + iFilelist << iFileInfo.filePath(); + + ICheckLib i_ichecklib; + i_ichecklib.ParseHeader(iIncludepathlist, iFilelist); + + ICheckLib ichecklib; + ichecklib.ParseHeader(chIncludepathlist, chFilelist); + + if(!ichecklib.check(i_ichecklib)){ + cout << "Folowing interface items are missing:" << endl; + QStringList errorlist = ichecklib.getErrorMsg(); + foreach(QString msg, errorlist){ + cout << (const char *)msg.toLatin1() << endl; + } + ret = -1; + } + else + cout << "Interface is full defined."; + +/* + //Parse the interface header + CPlusPlus::ParseManager* iParseManager = new CPlusPlus::ParseManager(); + iParseManager->setIncludePath(iIncludepathlist); + iParseManager->parse(iFilelist); + + //Parse the header that needs to be compared against the interface header + CPlusPlus::ParseManager* chParseManager = new CPlusPlus::ParseManager(); + chIncludepathlist << getQTIncludePath(); + chParseManager->setIncludePath(chIncludepathlist); + chParseManager->parse(chFilelist); + + if(!chParseManager->checkAllMetadatas(iParseManager)){ + cout << "Folowing interface items are missing:" << endl; + QStringList errorlist = chParseManager->getErrorMsg(); + foreach(QString msg, errorlist){ + cout << (const char *)msg.toLatin1() << endl; + } + ret = -1; + } + else + cout << "Interface is full defined."; + + delete iParseManager; + delete chParseManager; + */ + } + catch (QString msg) + { + cout << endl << "Error:" << endl; + cout << (const char *)msg.toLatin1(); + ret = -2; + } + } + else{ + cout << "CompareHeaderWithHeader.exe"; + cout << " \"Interface header\""; + cout << " \"headerfile to check\""; + } + + qDebug() << endl << endl << "return value: " << ret; + getchar(); + return ret; +} diff --git a/src/tools/ICheck/ICheckLib/ICheckLib.pri b/src/tools/ICheck/ICheckLib/ICheckLib.pri new file mode 100644 index 0000000000000000000000000000000000000000..9eebf58160fb8edc82d03ff7c2777f7727959a1e --- /dev/null +++ b/src/tools/ICheck/ICheckLib/ICheckLib.pri @@ -0,0 +1,110 @@ +# ---------------------------------------------------- +# This file is generated by the Qt Visual Studio Add-in. +# ------------------------------------------------------ +HEADERS += $$REL_PATH_TO_SRC/shared/cplusplus/Array.h \ + $$REL_PATH_TO_SRC/shared/cplusplus/AST.h \ + $$REL_PATH_TO_SRC/shared/cplusplus/ASTMatcher.h \ + $$REL_PATH_TO_SRC/shared/cplusplus/ASTVisitor.h \ + $$REL_PATH_TO_SRC/shared/cplusplus/CheckDeclaration.h \ + $$REL_PATH_TO_SRC/shared/cplusplus/CheckDeclarator.h \ + $$REL_PATH_TO_SRC/shared/cplusplus/CheckExpression.h \ + $$REL_PATH_TO_SRC/shared/cplusplus/CheckName.h \ + $$REL_PATH_TO_SRC/shared/cplusplus/CheckSpecifier.h \ + $$REL_PATH_TO_SRC/shared/cplusplus/CheckStatement.h \ + $$REL_PATH_TO_SRC/shared/cplusplus/Control.h \ + $$REL_PATH_TO_SRC/plugins/coreplugin/core_global.h \ + $$REL_PATH_TO_SRC/shared/cplusplus/CoreTypes.h \ + $$REL_PATH_TO_SRC/shared/cplusplus/CPlusPlusForwardDeclarations.h \ + $$REL_PATH_TO_SRC/libs/cplusplus/CppBindings.h \ + $$REL_PATH_TO_SRC/libs/cplusplus/CppDocument.h \ + $$REL_PATH_TO_SRC/shared/cplusplus/DiagnosticClient.h \ + $$REL_PATH_TO_SRC/libs/cplusplus/FastPreprocessor.h \ + $$REL_PATH_TO_SRC/shared/cplusplus/FullySpecifiedType.h \ + ./ichecklib.h \ + ./ICheckLib_global.h \ + $$REL_PATH_TO_SRC/shared/cplusplus/Lexer.h \ + $$REL_PATH_TO_SRC/shared/cplusplus/Literals.h \ + $$REL_PATH_TO_SRC/shared/cplusplus/LiteralTable.h \ + $$REL_PATH_TO_SRC/libs/cplusplus/Macro.h \ + $$REL_PATH_TO_SRC/shared/cplusplus/MemoryPool.h \ + $$REL_PATH_TO_SRC/shared/cplusplus/Name.h \ + $$REL_PATH_TO_SRC/libs/cplusplus/NamePrettyPrinter.h \ + $$REL_PATH_TO_SRC/shared/cplusplus/Names.h \ + $$REL_PATH_TO_SRC/shared/cplusplus/NameVisitor.h \ + $$REL_PATH_TO_SRC/shared/cplusplus/ObjectiveCTypeQualifiers.h \ + $$REL_PATH_TO_SRC/libs/cplusplus/Overview.h \ + ./ParseManager.h \ + $$REL_PATH_TO_SRC/shared/cplusplus/Parser.h \ + $$REL_PATH_TO_SRC/libs/cplusplus/pp-cctype.h \ + $$REL_PATH_TO_SRC/libs/cplusplus/pp-engine.h \ + $$REL_PATH_TO_SRC/libs/cplusplus/pp-macro-expander.h \ + $$REL_PATH_TO_SRC/libs/cplusplus/pp-scanner.h \ + $$REL_PATH_TO_SRC/libs/cplusplus/pp.h \ + $$REL_PATH_TO_SRC/libs/cplusplus/PreprocessorClient.h \ + $$REL_PATH_TO_SRC/libs/cplusplus/PreprocessorEnvironment.h \ + $$REL_PATH_TO_SRC/libs/utils/qtcassert.h \ + $$REL_PATH_TO_SRC/shared/cplusplus/Scope.h \ + $$REL_PATH_TO_SRC/shared/cplusplus/Semantic.h \ + $$REL_PATH_TO_SRC/shared/cplusplus/SemanticCheck.h \ + $$REL_PATH_TO_SRC/shared/cplusplus/Symbol.h \ + $$REL_PATH_TO_SRC/shared/cplusplus/Symbols.h \ + $$REL_PATH_TO_SRC/shared/cplusplus/SymbolVisitor.h \ + $$REL_PATH_TO_SRC/shared/cplusplus/Token.h \ + $$REL_PATH_TO_SRC/shared/cplusplus/TranslationUnit.h \ + $$REL_PATH_TO_SRC/shared/cplusplus/Type.h \ + $$REL_PATH_TO_SRC/shared/cplusplus/TypeMatcher.h \ + $$REL_PATH_TO_SRC/libs/cplusplus/TypePrettyPrinter.h \ + $$REL_PATH_TO_SRC/shared/cplusplus/TypeVisitor.h +SOURCES += $$REL_PATH_TO_SRC/shared/cplusplus/Array.cpp \ + $$REL_PATH_TO_SRC/shared/cplusplus/AST.cpp \ + $$REL_PATH_TO_SRC/shared/cplusplus/ASTMatch0.cpp \ + $$REL_PATH_TO_SRC/shared/cplusplus/ASTMatcher.cpp \ + $$REL_PATH_TO_SRC/shared/cplusplus/ASTVisit.cpp \ + $$REL_PATH_TO_SRC/shared/cplusplus/ASTVisitor.cpp \ + $$REL_PATH_TO_SRC/shared/cplusplus/CheckDeclaration.cpp \ + $$REL_PATH_TO_SRC/shared/cplusplus/CheckDeclarator.cpp \ + $$REL_PATH_TO_SRC/shared/cplusplus/CheckExpression.cpp \ + $$REL_PATH_TO_SRC/shared/cplusplus/CheckName.cpp \ + $$REL_PATH_TO_SRC/shared/cplusplus/CheckSpecifier.cpp \ + $$REL_PATH_TO_SRC/shared/cplusplus/CheckStatement.cpp \ + $$REL_PATH_TO_SRC/shared/cplusplus/Control.cpp \ + $$REL_PATH_TO_SRC/shared/cplusplus/CoreTypes.cpp \ + $$REL_PATH_TO_SRC/libs/cplusplus/CppBindings.cpp \ + $$REL_PATH_TO_SRC/libs/cplusplus/CppDocument.cpp \ + $$REL_PATH_TO_SRC/plugins/cpptools/cppmodelmanager.cpp \ + $$REL_PATH_TO_SRC/shared/cplusplus/DiagnosticClient.cpp \ + $$REL_PATH_TO_SRC/libs/cplusplus/FastPreprocessor.cpp \ + $$REL_PATH_TO_SRC/shared/cplusplus/FullySpecifiedType.cpp \ + ./ichecklib.cpp \ + $$REL_PATH_TO_SRC/shared/cplusplus/Keywords.cpp \ + $$REL_PATH_TO_SRC/shared/cplusplus/Lexer.cpp \ + $$REL_PATH_TO_SRC/shared/cplusplus/Literals.cpp \ + $$REL_PATH_TO_SRC/shared/cplusplus/LiteralTable.cpp \ + $$REL_PATH_TO_SRC/libs/cplusplus/Macro.cpp \ + $$REL_PATH_TO_SRC/shared/cplusplus/MemoryPool.cpp \ + $$REL_PATH_TO_SRC/shared/cplusplus/Name.cpp \ + $$REL_PATH_TO_SRC/libs/cplusplus/NamePrettyPrinter.cpp \ + $$REL_PATH_TO_SRC/shared/cplusplus/Names.cpp \ + $$REL_PATH_TO_SRC/shared/cplusplus/NameVisitor.cpp \ + $$REL_PATH_TO_SRC/shared/cplusplus/ObjectiveCAtKeywords.cpp \ + $$REL_PATH_TO_SRC/shared/cplusplus/ObjectiveCTypeQualifiers.cpp \ + $$REL_PATH_TO_SRC/libs/cplusplus/Overview.cpp \ + ./ParseManager.cpp \ + $$REL_PATH_TO_SRC/shared/cplusplus/Parser.cpp \ + $$REL_PATH_TO_SRC/libs/cplusplus/pp-engine.cpp \ + $$REL_PATH_TO_SRC/libs/cplusplus/pp-macro-expander.cpp \ + $$REL_PATH_TO_SRC/libs/cplusplus/pp-scanner.cpp \ + $$REL_PATH_TO_SRC/libs/cplusplus/PreprocessorClient.cpp \ + $$REL_PATH_TO_SRC/libs/cplusplus/PreprocessorEnvironment.cpp \ + $$REL_PATH_TO_SRC/shared/cplusplus/Scope.cpp \ + $$REL_PATH_TO_SRC/shared/cplusplus/Semantic.cpp \ + $$REL_PATH_TO_SRC/shared/cplusplus/SemanticCheck.cpp \ + $$REL_PATH_TO_SRC/shared/cplusplus/Symbol.cpp \ + $$REL_PATH_TO_SRC/shared/cplusplus/Symbols.cpp \ + $$REL_PATH_TO_SRC/shared/cplusplus/SymbolVisitor.cpp \ + $$REL_PATH_TO_SRC/shared/cplusplus/Token.cpp \ + $$REL_PATH_TO_SRC/shared/cplusplus/TranslationUnit.cpp \ + $$REL_PATH_TO_SRC/shared/cplusplus/Type.cpp \ + $$REL_PATH_TO_SRC/shared/cplusplus/TypeMatcher.cpp \ + $$REL_PATH_TO_SRC/libs/cplusplus/TypePrettyPrinter.cpp \ + $$REL_PATH_TO_SRC/shared/cplusplus/TypeVisitor.cpp diff --git a/src/tools/ICheck/ICheckLib/ICheckLib.pro b/src/tools/ICheck/ICheckLib/ICheckLib.pro new file mode 100644 index 0000000000000000000000000000000000000000..af8b79ef3aa71c4e5e7182671bee7e9cbe90a28b --- /dev/null +++ b/src/tools/ICheck/ICheckLib/ICheckLib.pro @@ -0,0 +1,36 @@ +REL_PATH_TO_SRC = ../../../ + +TEMPLATE = lib +CONFIG += debug + +CONFIG(debug, debug|release){ + TARGET = ICheckLibd + DESTDIR = ./debug + DLLDESTDIR = ../ICheckApp/debug + MOC_DIR += ./debug/GeneratedFiles + OBJECTS_DIR += ./debug + INCLUDEPATH += ./ \ + ./debug/GeneratedFiles \ + $$REL_PATH_TO_SRC/plugins \ + $$REL_PATH_TO_SRC/libs \ + $$REL_PATH_TO_SRC/shared/cplusplus \ + $$REL_PATH_TO_SRC/libs/cplusplus \ + $(QTDIR) +} +else { + TARGET = ICheckLib + DESTDIR = ./release + DLLDESTDIR = ../ICheckApp/release + MOC_DIR += ./release/GeneratedFiles + OBJECTS_DIR += ./release + INCLUDEPATH += ./ \ + ./release/GeneratedFiles \ + $$REL_PATH_TO_SRC/plugins \ + $$REL_PATH_TO_SRC/libs \ + $$REL_PATH_TO_SRC/shared/cplusplus \ + $$REL_PATH_TO_SRC/libs/cplusplus \ + $(QTDIR) +} + +DEFINES += ICHECKLIB_LIBRARY ICHECK_BUILD +include(ICheckLib.pri) diff --git a/src/tools/ICheck/ICheckLib/ParseManager.cpp b/src/tools/ICheck/ICheckLib/ParseManager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c902eea2b6082feb4fcd951ed63503621d04e2a9 --- /dev/null +++ b/src/tools/ICheck/ICheckLib/ParseManager.cpp @@ -0,0 +1,1362 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "ParseManager.h" +#include "cplusplus\CppDocument.h" +#include "Control.h" +#include "TranslationUnit.h" +#include "AST.h" +#include "Symbols.h" +#include <QDebug> +#include "Name.h" +#include "cpptools\cppmodelmanager.h" + +using namespace CppTools; +using namespace CppTools::Internal; + + +using namespace CPlusPlus; + +//<------------------------------------------------------- Compare function for the internal structures +/********************************** +Compares function with function +with return type, function name +and their arguments and arguments +types. +**********************************/ +bool ParseManager::FUNCTIONITEM::isEqualTo(ParseManager::FUNCTIONITEM *cpfct, bool ignoreName/* = true*/) +{ + if(ignoreName) + return function->isEqualTo(cpfct->function, true); + return function->isEqualTo(cpfct->function); +} + +/***************************************************************** +Compares two property regarding +of their function definition, +type definition, function arguments +and function types. + +Q_PROPERTY( ConnectionState state READ state NOTIFY stateChanged); +******************************************************************/ +bool ParseManager::PROPERTYITEM::isEqualTo(ParseManager::PROPERTYITEM *cpppt) +{ + QString thistype = this->trlUnit->spell(this->ast->type_token); + QString cppttype = cpppt->trlUnit->spell(cpppt->ast->type_token); + + if(thistype != cppttype) + return false; + + QString thistypename = this->trlUnit->spell(this->ast->type_name_token); + QString cppttypename = cpppt->trlUnit->spell(cpppt->ast->type_name_token); + if(thistypename != cppttypename) + return false; + + if(this->readdefined != cpppt->readdefined) + return false; + if(this->writedefined != cpppt->writedefined) + return false; + if(this->resetdefined != cpppt->resetdefined) + return false; + if(this->notifydefined != cpppt->notifydefined) + return false; + //check for read function + if(this->readdefined){ + if(!this->readFct || !cpppt->readFct) + return false; + if(!this->readFct->isEqualTo(cpppt->readFct)) + return false; + } + //check for write function + if(this->writedefined){ + if(!this->writeFct || !cpppt->writeFct) + return false; + if(!this->writeFct->isEqualTo(cpppt->writeFct)) + return false; + } + //check for reset function + if(this->resetdefined){ + if(!this->resetFct || !cpppt->resetFct) + return false; + if(!this->resetFct->isEqualTo(cpppt->resetFct)) + return false; + } + //check for notify function + if(this->notifydefined){ + if(!this->notifyFct || !cpppt->notifyFct) + return false; + if(!this->notifyFct->isEqualTo(cpppt->notifyFct)) + return false; + } + return true; +} + +/***************************************************************** +Compares two enums regarding +of their values created by the getEnumValueStringList function. +*****************************************************************/ +bool ParseManager::QENUMITEM::isEqualTo(QENUMITEM *cpenum) +{ + if(this->values.count() != cpenum->values.count()) + return false; + foreach(QString str, this->values){ + if(!cpenum->values.contains(str)) + return false; + } + return true; +} + +/***************************************************************** +Compares two flags regarding +of their enum definitions and their +values created by the getEnumValueStringList function. +*****************************************************************/ +bool ParseManager::QFLAGITEM::isEqualTo(QFLAGITEM *cpflag) +{ + if(this->enumvalues.count() != cpflag->enumvalues.count()) + return false; + foreach(QString str, this->enumvalues){ + if(!cpflag->enumvalues.contains(str)) + return false; + } + return true; +} + + + +ParseManager::ParseManager() +: pCppPreprocessor(0) +{ + +} + +ParseManager::~ParseManager() +{ + if(pCppPreprocessor) + delete pCppPreprocessor; +} + +/************************************** +Function for setting the include +Paths +**************************************/ +void ParseManager::setIncludePath(const QStringList &includePath) +{ + m_includePaths = includePath; +} + +/************************************** +public Function that starts the parsing +all of the files in the sourceFiles +string list. +**************************************/ +void ParseManager::parse(const QStringList &sourceFiles) +{ + m_errormsgs.clear(); + if(pCppPreprocessor){ + delete pCppPreprocessor; + pCppPreprocessor = 0; + } + + if (! sourceFiles.isEmpty()) { + m_strHeaderFile = sourceFiles[0]; + pCppPreprocessor = new CppTools::Internal::CppPreprocessor(QPointer<CPlusPlus::ParseManager>(this)); + pCppPreprocessor->setIncludePaths(m_includePaths); + pCppPreprocessor->setFrameworkPaths(m_frameworkPaths); + parse(pCppPreprocessor, sourceFiles); + } +} + +/********************************************* +private function that prepare the filelist +to parse and starts the parser. +*********************************************/ +void ParseManager::parse(CppTools::Internal::CppPreprocessor *preproc, + const QStringList &files) +{ + if (files.isEmpty()) + return; + + //check if file is C++ header file + QStringList headers; + foreach (const QString &file, files) { + const QFileInfo fileInfo(file); + QString ext = fileInfo.suffix(); + if (ext.toLower() == "h") + headers.append(file); + } + + foreach (const QString &file, files) { + preproc->snapshot.remove(file); + } + preproc->setTodo(headers); + QString conf = QLatin1String("<configuration>"); + + preproc->run(conf); + for (int i = 0; i < headers.size(); ++i) { + QString fileName = headers.at(i); + preproc->run(fileName); + } +} + +//This function creates a class list for each class and its base classes in +//the header file that needs to be checked. +//e.g. +// Cl1 Cl2 +// __|__ __|__ +// | | | | +// Cl11 Cl12 Cl21 Cl22 +// +//==> list[0] = {Cl1, Cl11, Cl12} +// list[1] = {Cl2, Cl21, Cl22} + +QList<ParseManager::CLASSTREE*> ParseManager::CreateClassLists() +{ + QList<CLASSTREE*>ret; + QList<CLASSLISTITEM*> classlist; + QList<CLASSLISTITEM*> allclasslist; + + //Iteration over all parsed documents + if(getPreProcessor()){ + for (Snapshot::const_iterator it = getPreProcessor()->snapshot.begin() + ; it != getPreProcessor()->snapshot.end(); ++it) + { + Document::Ptr doc = (*it); + if(doc){ + QFileInfo fileinf(doc->fileName()); + QFileInfo fileinf1(m_strHeaderFile); + //Get the Translated unit + Control* ctrl = doc->control(); + TranslationUnit* trlUnit = ctrl->translationUnit(); + AST* pAst = trlUnit->ast(); + TranslationUnitAST *ptrAst = 0; + if(pAst && (ptrAst = pAst->asTranslationUnit())){ + //iteration over all translated declaration in this document + for (DeclarationListAST *pDecllist = ptrAst->declaration_list; pDecllist; pDecllist = pDecllist->next) { + if(pDecllist->value){ + SimpleDeclarationAST *pSimpleDec = pDecllist->value->asSimpleDeclaration(); + if(pSimpleDec){ + //Iteration over class specifier + for (SpecifierListAST *pSimpleDecDecllist = pSimpleDec->decl_specifier_list; pSimpleDecDecllist; pSimpleDecDecllist = pSimpleDecDecllist->next) { + ClassSpecifierAST * pclassspec = pSimpleDecDecllist->value->asClassSpecifier(); + if(pclassspec){ + CLASSLISTITEM* item = new CLASSLISTITEM(); + item->classspec = pclassspec; + item->trlUnit = trlUnit; + allclasslist.push_back(item); + //We found a class that is defined in the header file that needs to be checked + if(fileinf.fileName().toLower() == fileinf1.fileName().toLower()){ + CLASSTREE* cltree = new CLASSTREE(); + cltree->highestlevelclass = item; + cltree->classlist.push_back(item); + //now add all baseclasses from this class + ret.push_back(cltree); + } + } + } + } + } + } + } + } + } + } + //after we search for the classes we need to search for the baseclasses + foreach(CLASSTREE *cltree, ret){ + QList<CLASSLISTITEM*> baseclasslist; + getBaseClasses(cltree->highestlevelclass, baseclasslist, allclasslist); + cltree->classlist.append(baseclasslist); + } + return ret; +} + +/******************************************** +Gets all the baseclass from a class and +add those base classes into the baseclasslist +********************************************/ +void ParseManager::getBaseClasses(const CLASSLISTITEM* pclass, QList<CLASSLISTITEM*> &baseclasslist, const QList<CLASSLISTITEM*> &allclasslist) +{ + //iteration over the base_clause_list of the current class + QList<CLASSLISTITEM*>child; + for(BaseSpecifierListAST *pBaseSpecList = pclass->classspec->base_clause_list; pBaseSpecList; pBaseSpecList = pBaseSpecList->next) + { + BaseSpecifierAST *pBaseSpec = pBaseSpecList->value; + foreach(CLASSLISTITEM* pclspec, allclasslist) + { + if(pclspec->classspec->symbol->name()->isEqualTo(pBaseSpec->symbol->name())) + { + child.push_back(pclspec); + baseclasslist.push_back(pclspec); + break; + } + } + } + //call the function recursive because all the basclasses can have other base classes + foreach(CLASSLISTITEM* pchclass, child){ + getBaseClasses(pchclass, baseclasslist, allclasslist); + } +} + +/************************************************** +This function finds and creates all Elements wich +are significant for MetaDatas. +Those element will be added in the aparameter +lists. +**************************************************/ +void ParseManager::getElements(QList<FUNCTIONITEM*> &functionlist + , QList<PROPERTYITEM*> &propertylist + , QList<QENUMITEM*> &qenumlist + , QList<ENUMITEM*> &enumlist + , QList<QFLAGITEM*> &qflaglist + , QList<QDECLAREFLAGSITEM*> &qdeclareflaglist + , const QList<CLASSLISTITEM*> classitems + , const CLASSLISTITEM* highestlevelclass) +{ + foreach(CLASSLISTITEM* classitem, classitems){ + for (DeclarationListAST *pmemberlist = classitem->classspec->member_specifier_list; pmemberlist; pmemberlist = pmemberlist->next) { + /********** + Functions + **********/ + SimpleDeclarationAST *pdecl = pmemberlist->value->asSimpleDeclaration(); + if(pdecl){ + for(List<Declaration*>* decllist = pdecl->symbols; decllist; decllist = decllist->next) + { + Function* pfct = decllist->value->type()->asFunctionType(); + if(pfct){ + FUNCTIONITEM* item = new FUNCTIONITEM(); + item->init(); + item->trlUnit = classitem->trlUnit; + item->function = pfct; + item->ast = pdecl; + item->classAst = classitem->classspec; + item->highestlevelclass = highestlevelclass; + functionlist.push_back(item); + } + } + /****** + enum + ******/ + for(List<SpecifierAST*>* decllist = pdecl->decl_specifier_list; decllist; decllist = decllist->next) + { + EnumSpecifierAST * penum = decllist->value->asEnumSpecifier(); + if(penum){ + ENUMITEM* item = new ENUMITEM(); + item->init(); + item->ast = penum; + item->highestlevelclass = highestlevelclass; + item->trlUnit = classitem->trlUnit; + enumlist.push_back(item); + } + } + } + else{ + /********** + Q_PROPERTY + **********/ + QPropertyDeclarationAST *ppdecl = pmemberlist->value->asQPropertyDeclarationAST(); + if(ppdecl){ + PROPERTYITEM* item = new PROPERTYITEM(); + item->init(); + item->ast = ppdecl; + item->highestlevelclass = highestlevelclass; + item->trlUnit = classitem->trlUnit; + item->readdefined = (ppdecl->read_token > 0); + item->writedefined = (ppdecl->write_token > 0); + item->resetdefined = (ppdecl->reset_token > 0); + item->notifydefined = (ppdecl->notify_token > 0); + propertylist.push_back(item); + } + else{ + /********** + Q_ENUM + **********/ + QEnumDeclarationAST *pqenum = pmemberlist->value->asQEnumDeclarationAST(); + if(pqenum){ + QENUMITEM* item = new QENUMITEM(); + item->init(); + item->ast = pqenum; + item->highestlevelclass = highestlevelclass; + item->trlUnit = classitem->trlUnit; + qenumlist.push_back(item); + } + else{ + /********** + Q_FLAGS + **********/ + QFlagsDeclarationAST *pqflags = pmemberlist->value->asQFlagsDeclarationAST(); + if(pqflags){ + QFLAGITEM* item = new QFLAGITEM(); + item->init(); + item->ast = pqflags; + item->highestlevelclass = highestlevelclass; + item->trlUnit = classitem->trlUnit; + qflaglist.push_back(item); + } + else { + /**************** + Q_DECLARE_FLAGS + ****************/ + QDeclareFlagsDeclarationAST *pqdeclflags = pmemberlist->value->asQDeclareFlagsDeclarationAST(); + if(pqdeclflags){ + QDECLAREFLAGSITEM* item = new QDECLAREFLAGSITEM(); + item->init(); + item->ast = pqdeclflags; + item->highestlevelclass = highestlevelclass; + item->trlUnit = classitem->trlUnit; + qdeclareflaglist.push_back(item); + } + } + } + } + } + } + } +} + +/********************************************* +Function that starts the comare between the +parser result and their metadata content. +*********************************************/ +bool ParseManager::checkAllMetadatas(ParseManager* pInterfaceParserManager) +{ + bool ret = true; + + /************************************************ + Get all elements from the interface header file + ************************************************/ + QList<CLASSTREE*> ilookuplist = pInterfaceParserManager->CreateClassLists(); + QList<QList<FUNCTIONITEM*> > ifunctionslookuplist; + QList<QList<PROPERTYITEM*> > ipropertieslookuplist; + QList<QList<QENUMITEM*> > iqenumlookuplist; + QList<QList<ENUMITEM*> > ienumlookuplist; + QList<QList<QFLAGITEM*> > iqflaglookuplist; + QList<QList<QDECLAREFLAGSITEM*> > iqdeclareflaglookuplist; + foreach(CLASSTREE* iclasstree, ilookuplist){ + QList<FUNCTIONITEM*>functionlist; + QList<PROPERTYITEM*>propertylist; + QList<QENUMITEM*>qenumlist; + QList<ENUMITEM*>enumlist; + QList<QFLAGITEM*> qflaglist; + QList<QDECLAREFLAGSITEM*> qdeclareflag; + getElements(functionlist + , propertylist + , qenumlist + , enumlist + , qflaglist + , qdeclareflag + , iclasstree->classlist + , iclasstree->highestlevelclass); + if(functionlist.size() > 0) + ifunctionslookuplist.append(functionlist); + if(propertylist.size() > 0) + ipropertieslookuplist.append(propertylist); + if(qenumlist.size() > 0) + iqenumlookuplist.append(qenumlist); + if(enumlist.size() > 0) + ienumlookuplist.append(enumlist); + if(qflaglist.size() > 0) + iqflaglookuplist.append(qflaglist); + if(qdeclareflag.size() > 0) + iqdeclareflaglookuplist.append(qdeclareflag); + } + + /************************************************ + Get all elements from the compare header file + ************************************************/ + QList<CLASSTREE*> lookuplist = CreateClassLists(); + QList<QList<FUNCTIONITEM*> > functionslookuplist; + QList<QList<PROPERTYITEM*> > propertieslookuplist; + QList<QList<QENUMITEM*> > qenumlookuplist; + QList<QList<ENUMITEM*> > enumlookuplist; + QList<QList<QFLAGITEM*> > qflaglookuplist; + QList<QList<QDECLAREFLAGSITEM*> > qdeclareflaglookuplist; + foreach(CLASSTREE* classtree, lookuplist){ + QList<FUNCTIONITEM*>functionlist; + QList<PROPERTYITEM*>propertylist; + QList<QENUMITEM*>qenumlist; + QList<ENUMITEM*>enumlist; + QList<QFLAGITEM*> qflaglist; + QList<QDECLAREFLAGSITEM*> qdeclareflag; + getElements(functionlist + , propertylist + , qenumlist + , enumlist + , qflaglist + , qdeclareflag + , classtree->classlist + , classtree->highestlevelclass); + if(functionlist.size() > 0) + functionslookuplist.append(functionlist); + if(propertylist.size() > 0) + propertieslookuplist.append(propertylist); + if(qenumlist.size() > 0) + qenumlookuplist.append(qenumlist); + if(enumlist.size() > 0) + enumlookuplist.append(enumlist); + if(qflaglist.size() > 0) + qflaglookuplist.append(qflaglist); + if(qdeclareflag.size() > 0) + qdeclareflaglookuplist.append(qdeclareflag); + } + + /****************************** + Check for function + ******************************/ + QList<FUNCTIONITEM*> missingifcts = checkMetadataFunctions(functionslookuplist, ifunctionslookuplist); + if(missingifcts.size() > 0){ + foreach(FUNCTIONITEM* ifct, missingifcts){ + m_errormsgs.push_back(getErrorMessage(ifct)); + } + ret = false; + } + + /****************************** + Check for properies + ******************************/ + QList<PROPERTYITEM*> missingippts = checkMetadataProperties(propertieslookuplist, functionslookuplist, ipropertieslookuplist, ifunctionslookuplist); + if(missingippts.size() > 0){ + foreach(PROPERTYITEM* ippt, missingippts){ + m_errormsgs.push_back(getErrorMessage(ippt)); + } + ret = false; + } + + /****************************** + Check for enums + ******************************/ + QList<QENUMITEM*> missingiqenums = checkMetadataEnums(qenumlookuplist, enumlookuplist, iqenumlookuplist, ienumlookuplist); + if(missingiqenums.size() > 0){ + foreach(QENUMITEM* ienum, missingiqenums){ + m_errormsgs.push_back(getErrorMessage(ienum)); + } + ret = false; + } + + /****************************** + Check for flags + ******************************/ + QList<QFLAGITEM*> missingiqflags = checkMetadataFlags(qflaglookuplist, qdeclareflaglookuplist, enumlookuplist + , iqflaglookuplist, iqdeclareflaglookuplist, ienumlookuplist); + if(missingiqflags.size() > 0){ + foreach(QFLAGITEM* iflags, missingiqflags){ + m_errormsgs.push_back(getErrorMessage(iflags)); + } + ret = false; + } + + //now delet all Classitems + foreach(CLASSTREE* l, ilookuplist){ + l->classlist.clear(); + } + foreach(CLASSTREE* l, lookuplist){ + l->classlist.clear(); + } + //delete all functionitems + foreach(QList<FUNCTIONITEM*>l, ifunctionslookuplist){ + l.clear(); + } + foreach(QList<FUNCTIONITEM*>l, functionslookuplist){ + l.clear(); + } + //delete all properties + foreach(QList<PROPERTYITEM*>l, ipropertieslookuplist){ + l.clear(); + } + foreach(QList<PROPERTYITEM*>l, propertieslookuplist){ + l.clear(); + } + //delete all qenums + foreach(QList<QENUMITEM*>l, iqenumlookuplist){ + l.clear(); + } + foreach(QList<QENUMITEM*>l, iqenumlookuplist){ + l.clear(); + } + //delete all enums + foreach(QList<ENUMITEM*>l, ienumlookuplist){ + l.clear(); + } + foreach(QList<ENUMITEM*>l, enumlookuplist){ + l.clear(); + } + //delete all qflags + foreach(QList<QFLAGITEM*>l, iqflaglookuplist){ + l.clear(); + } + foreach(QList<QFLAGITEM*>l, qflaglookuplist){ + l.clear(); + } + //delete all qdeclareflags + foreach(QList<QDECLAREFLAGSITEM*>l, iqdeclareflaglookuplist){ + l.clear(); + } + foreach(QList<QDECLAREFLAGSITEM*>l, qdeclareflaglookuplist){ + l.clear(); + } + + return ret; +} + +//<------------------------------------------------------- Start of MetaData functions +/*********************************** +Function that checks all functions +which will occur in the MetaData +***********************************/ +QList<ParseManager::FUNCTIONITEM*> ParseManager::checkMetadataFunctions(const QList<QList<FUNCTIONITEM*> > &classfctlist, const QList<QList<FUNCTIONITEM*> > &iclassfctlist) +{ + QList<FUNCTIONITEM*> missingifcts; + //Compare each function from interface with function from header (incl. baseclass functions) + QList<FUNCTIONITEM*> ifcts; + foreach(QList<FUNCTIONITEM*>ifunctionlist, iclassfctlist){ + ifcts.clear(); + //check if one header class contains all function from one interface header class + if(classfctlist.count() > 0){ + foreach(QList<FUNCTIONITEM*>functionlist, classfctlist){ + QList<FUNCTIONITEM*> tmpl = containsAllMetadataFunction(functionlist, ifunctionlist); + if(tmpl.size() == 0) + ifcts.clear(); + else + ifcts.append(tmpl); + } + } + else { + foreach(FUNCTIONITEM *pfct, ifunctionlist) + pfct->classWichIsNotFound << "<all classes>"; + ifcts.append(ifunctionlist); + } + missingifcts.append(ifcts); + } + return missingifcts; +} + +/********************************************* +Helper function to check if a function will +occure in the MetaData. +*********************************************/ +bool ParseManager::isMetaObjFunction(FUNCTIONITEM* fct) +{ + if(fct->function->isInvokable() + || fct->function->isSignal() + || fct->function->isSlot()) + return true; + return false; +} + +/**************************************************** +Check if all function from iclassfctlist are defined +in the classfctlist as well. +It will return all the function they are missing. +****************************************************/ +QList<ParseManager::FUNCTIONITEM*> ParseManager::containsAllMetadataFunction(const QList<FUNCTIONITEM*> &classfctlist, const QList<FUNCTIONITEM*> &iclassfctlist) +{ + QList<FUNCTIONITEM*> ret; + foreach(FUNCTIONITEM* ifct, iclassfctlist){ + if(isMetaObjFunction(ifct)){ + bool found = false; + QStringList missingimplinclasses; + ClassSpecifierAST* clspec = 0; + foreach(FUNCTIONITEM* fct, classfctlist){ + if(clspec != fct->highestlevelclass->classspec){ + clspec = fct->highestlevelclass->classspec; + //get the classname + QString classname = ""; + unsigned int firsttoken = clspec->name->firstToken(); + classname += fct->trlUnit->spell(firsttoken); + if(missingimplinclasses.indexOf(classname) < 0) + missingimplinclasses.push_back(classname); + } + if(fct->isEqualTo(ifct, false)){ + found = true; + missingimplinclasses.clear(); + break; + } + } + if(!found){ + ifct->classWichIsNotFound.append(missingimplinclasses); + ret.push_back(ifct); + } + } + } + return ret; +} + +/************************************ +Function that gives back an error +string for a MetaData function +mismatch. +************************************/ +QString ParseManager::getErrorMessage(FUNCTIONITEM* fct) +{ + QString ret = ""; + QTextStream out(&ret); + QString fctstring = ""; + QString fcttype = ""; + + foreach(QString classname, fct->classWichIsNotFound){ + if(ret.size() > 0) + out << endl; + + fcttype = ""; + fctstring = classname; + fctstring += "::"; + + unsigned int firsttoken = fct->ast->firstToken(); + unsigned int lasttoken = fct->ast->lastToken(); + for(unsigned int i = firsttoken; i < lasttoken; i++){ + fctstring += fct->trlUnit->spell(i); + fctstring += " "; + } + + SimpleDeclarationAST *psdecl = fct->ast->asSimpleDeclaration(); + if(psdecl){ + for(List<Declaration*>* decllist = psdecl->symbols; decllist; decllist = decllist->next) + { + Function* pfct = decllist->value->type()->asFunctionType(); + if(pfct){ + fcttype = "type: "; + //Check for private, protected and public + if(pfct->isPublic()) + fcttype = "public "; + if(pfct->isProtected()) + fcttype = "protected "; + if(pfct->isPrivate()) + fcttype = "private "; + + if(pfct->isVirtual()) + fcttype += "virtual "; + if(pfct->isPureVirtual()) + fcttype += "pure virtual "; + + if(pfct->isSignal()) + fcttype += "Signal "; + if(pfct->isSlot()) + fcttype += "Slot "; + if(pfct->isNormal()) + fcttype += "Normal "; + if(pfct->isInvokable()) + fcttype += "Invokable "; + } + } + } + out << fcttype << fctstring; + } + return ret; +} +//---> + +//<------------------------------------------------------- Start of Q_PROPERTY checks +/*********************************** +Function that checks all Property +which will occur in the MetaData +***********************************/ +QList<ParseManager::PROPERTYITEM*> ParseManager::checkMetadataProperties(const QList<QList<PROPERTYITEM*> > &classproplist + , const QList<QList<FUNCTIONITEM*> > &classfctlist + , const QList<QList<PROPERTYITEM*> > &iclassproplist + , const QList<QList<FUNCTIONITEM*> > &iclassfctlist) +{ + QList<PROPERTYITEM*> missingifcts; + //assign the property functions + foreach(QList<PROPERTYITEM*>proplist, classproplist){ + foreach(PROPERTYITEM* prop, proplist){ + assignPropertyFunctions(prop, classfctlist); + } + } + + foreach(QList<PROPERTYITEM*>proplist, iclassproplist){ + foreach(PROPERTYITEM* prop, proplist){ + assignPropertyFunctions(prop, iclassfctlist); + } + } + + //Compare each qproperty from interface with qproperty from header (incl. baseclass functions) + QList<PROPERTYITEM*> ippts; + foreach(QList<PROPERTYITEM*>ipropertylist, iclassproplist){ + ippts.clear(); + //check if one header class contains all function from one interface header class + if(classproplist.count() > 0){ + foreach(QList<PROPERTYITEM*>propertylist, classproplist){ + QList<PROPERTYITEM*> tmpl = containsAllPropertyFunction(propertylist, ipropertylist); + if(tmpl.size() == 0) + ippts.clear(); + else + ippts.append(tmpl); + } + } + else { + foreach(PROPERTYITEM *pprop, ipropertylist) + pprop->classWichIsNotFound << "<all classes>"; + ippts.append(ipropertylist); + } + missingifcts.append(ippts); + } + return missingifcts; +} + +/************************************** +Function that resolves the dependensies +between Q_PROPERTY +and thier READ, WRITE, NOTIFY and RESET +functions. +***************************************/ +void ParseManager::assignPropertyFunctions(PROPERTYITEM* prop, const QList<QList<FUNCTIONITEM*> > &fctlookuplist) +{ + //get the name of the needed functions + QString type; + QString readfctname; + QString writefctname; + QString resetfctname; + QString notifyfctname; + + int needtofind = 0; + type = prop->trlUnit->spell(prop->ast->type_token); + if(prop->readdefined){ + readfctname = prop->trlUnit->spell(prop->ast->read_function_token); + needtofind++; + } + if(prop->writedefined){ + writefctname = prop->trlUnit->spell(prop->ast->write_function_token); + needtofind++; + } + if(prop->resetdefined){ + resetfctname = prop->trlUnit->spell(prop->ast->reset_function_token); + needtofind++; + } + if(prop->notifydefined){ + notifyfctname = prop->trlUnit->spell(prop->ast->notify_function_token); + needtofind++; + } + //Now iterate over all function to find all functions wich are defined in the Q_PROPERTY macro + if(needtofind > 0){ + prop->foundalldefinedfct = false; + foreach(QList<FUNCTIONITEM*> fctlist, fctlookuplist){ + foreach(FUNCTIONITEM* pfct, fctlist){ + QString fcttype =pfct->trlUnit->spell(pfct->ast->firstToken()); + //check the function type against the property type + QString fctname = pfct->trlUnit->spell(pfct->ast->firstToken() + 1); + if(prop->readdefined && fctname == readfctname){ + if(type != fcttype) + continue; + prop->readFct = pfct; + needtofind--; + } + if(prop->writedefined && fctname == writefctname){ + prop->writeFct = pfct; + needtofind--; + } + if(prop->resetdefined && fctname == resetfctname){ + prop->resetFct = pfct; + needtofind--; + } + if(prop->notifydefined && fctname == notifyfctname){ + prop->notifyFct = pfct; + needtofind--; + } + if(needtofind <= 0){ + //a flag that indicates if a function was missing + prop->foundalldefinedfct = true; + return; + } + } + } + } +} + +/************************************** +Function that checks if all functions +dependencies in Q_PROPERTY have the +same arguments and retunr value. +***************************************/ +QList<ParseManager::PROPERTYITEM*> ParseManager::containsAllPropertyFunction(const QList<PROPERTYITEM*> &classproplist, const QList<PROPERTYITEM*> &iclassproplist) +{ + QList<PROPERTYITEM*> ret; + foreach(PROPERTYITEM* ipropt, iclassproplist){ + if(ipropt->foundalldefinedfct){ + bool found = false; + QStringList missingimplinclasses; + ClassSpecifierAST* clspec = 0; + foreach(PROPERTYITEM* propt, classproplist){ + if(clspec != propt->highestlevelclass->classspec){ + clspec = propt->highestlevelclass->classspec; + //get the classname + QString classname = ""; + unsigned int firsttoken = clspec->name->firstToken(); + classname += propt->trlUnit->spell(firsttoken); + if(missingimplinclasses.indexOf(classname) < 0) + missingimplinclasses.push_back(classname); + } + if(propt->isEqualTo(ipropt)){ + found = true; + missingimplinclasses.clear(); + break; + } + } + if(!found){ + ipropt->classWichIsNotFound.append(missingimplinclasses); + ret.push_back(ipropt); + } + } + else{ + ret.push_back(ipropt); + } + } + return ret; +} + +/************************************ +Function that gives back an error +string for a Q_PROPERTY mismatch. +************************************/ +QString ParseManager::getErrorMessage(PROPERTYITEM* ppt) +{ + QString ret = ""; + QTextStream out(&ret); + QString pptstring = ""; + QString ppttype = ""; + + if(!ppt->foundalldefinedfct) + { + unsigned int firsttoken = ppt->highestlevelclass->classspec->name->firstToken(); + unsigned int lasttoken = ppt->highestlevelclass->classspec->name->lastToken(); + for(unsigned int i = firsttoken; i < lasttoken; i++){ + out << ppt->trlUnit->spell(i); + } + out << "::"; + firsttoken = ppt->ast->firstToken(); + lasttoken = ppt->ast->lastToken(); + for(unsigned int i = firsttoken; i <= lasttoken; i++){ + out << ppt->trlUnit->spell(i) << " "; + } + out << endl << " -"; + if(ppt->readdefined && !ppt->readFct) + out << "READ "; + if(ppt->writedefined && !ppt->writeFct) + out << "WRITE "; + if(ppt->resetdefined && !ppt->resetFct) + out << "RESET."; + if(ppt->notifydefined && !ppt->notifyFct) + out << "NOTIFY "; + out << "functions missing." << endl; + } + for(int i = 0; i < ppt->classWichIsNotFound.size(); i++){ + if(ret.size() > 0) + out << endl; + + pptstring = ppt->classWichIsNotFound[i]; + pptstring += "::"; + + unsigned int firsttoken = ppt->ast->firstToken(); + unsigned int lasttoken = ppt->ast->lastToken(); + for(unsigned int i = firsttoken; i <= lasttoken; i++){ + pptstring += ppt->trlUnit->spell(i); + pptstring += " "; + } + + out << ppttype << pptstring; + } + return ret; +} +//---> + + +//<------------------------------------------------------- Start of Q_ENUMS checks +/*********************************** +Function that checks all enums +which will occur in the MetaData +***********************************/ +QList<ParseManager::QENUMITEM*> ParseManager::checkMetadataEnums(const QList<QList<QENUMITEM*> > &classqenumlist + , const QList<QList<ENUMITEM*> > &classenumlist + , const QList<QList<QENUMITEM*> > &iclassqenumlist + , const QList<QList<ENUMITEM*> > &iclassenumlist) +{ + QList<QENUMITEM*> missingiqenums; + //assign the property functions + foreach(QList<QENUMITEM*>qenumlist, classqenumlist){ + foreach(QENUMITEM* qenum, qenumlist){ + assignEnumValues(qenum, classenumlist); + } + } + foreach(QList<QENUMITEM*>qenumlist, iclassqenumlist){ + foreach(QENUMITEM* qenum, qenumlist){ + assignEnumValues(qenum, iclassenumlist); + } + } + + //Compare each qenum from interface with qenum from header (incl. baseclass functions) + QList<QENUMITEM*> iqenums; + foreach(QList<QENUMITEM*>iqenumlist, iclassqenumlist){ + iqenums.clear(); + //check if one header class contains all function from one interface header class + if(classqenumlist.count() > 0){ + foreach(QList<QENUMITEM*>qenumlist, classqenumlist){ + QList<QENUMITEM*> tmpl = containsAllEnums(qenumlist, iqenumlist); + if(tmpl.size() == 0) + iqenums.clear(); + else + iqenums.append(tmpl); + + } + } + else { + foreach(QENUMITEM *qenum, iqenumlist) + qenum->classWichIsNotFound << "<all classes>"; + iqenums.append(iqenumlist); + } + missingiqenums.append(iqenums); + } + + return missingiqenums; +} + +/********************************************* +Helper function which creates a string out of +an enumerator including its values. +*********************************************/ +QStringList ParseManager::getEnumValueStringList(ENUMITEM *penum, QString mappedenumname/* = ""*/) +{ + QStringList ret; + EnumSpecifierAST *penumsec = penum->ast; + QString enumname = penum->trlUnit->spell(penumsec->name->firstToken()); + int enumvalue = 0; + //now iterrate over all enumitems and create a string like following: + //EnumName.EnumItemName.Value + //ConnectionState.disconnected.0 + for (EnumeratorListAST *plist = penum->ast->enumerator_list; plist; plist = plist->next) { + QString value = enumname; + if(mappedenumname.size() > 0) + value = mappedenumname; + value += "."; + value += penum->trlUnit->spell(plist->value->identifier_token); + value += "."; + if(plist->value->equal_token > 0 && plist->value->expression){ + QString v = penum->trlUnit->spell(plist->value->expression->firstToken()); + bool ch; + int newval = enumvalue; + if(v.indexOf("0x") >= 0) + newval = v.toInt(&ch, 16); + else + newval = v.toInt(&ch, 10); + if(ch) + enumvalue = newval; + } + value += QString::number(enumvalue); + enumvalue++; + // now add this enumitem string in the VALUE list + ret << value; + } + return ret; +} + +/************************************** +Function that resolves the dependensies +between Q_ENUMS and enums. +***************************************/ +void ParseManager::assignEnumValues(QENUMITEM* qenum, const QList<QList<ENUMITEM*> > &enumlookuplist) +{ + QString enumname; + for (EnumeratorListAST *plist = qenum->ast->enumerator_list; plist; plist = plist->next) { + EnumeratorAST *penum = plist->value->asEnumerator(); + if(penum){ + //get the name of the enum definition + enumname = qenum->trlUnit->spell(penum->firstToken()); + //iterate over all enums and find the one with the same name like enumname + bool found = false; + foreach (QList<ENUMITEM*> penumlist, enumlookuplist) { + foreach(ENUMITEM *penum, penumlist){ + EnumSpecifierAST *penumsec = penum->ast; + QString enumname1 = penum->trlUnit->spell(penumsec->name->firstToken()); + if(enumname == enumname1){ + qenum->values << getEnumValueStringList(penum); + found = true; + break; + } + } + if(!found) + qenum->foundallenums = false; + } + } + } +} + +/*********************************** +Function that checkt if the Q_ENUMS +are completed defined and if the +Enum values are the same. +***********************************/ +QList<ParseManager::QENUMITEM*> ParseManager::containsAllEnums(const QList<QENUMITEM*> &classqenumlist, const QList<QENUMITEM*> &iclassqenumlist) +{ + QList<QENUMITEM*> ret; + foreach(QENUMITEM* iqenum, iclassqenumlist){ + bool found = false; + QStringList missingimplinclasses; + ClassSpecifierAST* clspec = 0; + foreach(QENUMITEM* qenum, classqenumlist){ + if(clspec != qenum->highestlevelclass->classspec){ + clspec = qenum->highestlevelclass->classspec; + //get the classname + QString classname = ""; + unsigned int firsttoken = clspec->name->firstToken(); + classname += qenum->trlUnit->spell(firsttoken); + if(missingimplinclasses.indexOf(classname) < 0) + missingimplinclasses.push_back(classname); + } + if(qenum->isEqualTo(iqenum)){ + found = true; + missingimplinclasses.clear(); + break; + } + } + if(!found){ + iqenum->classWichIsNotFound.append(missingimplinclasses); + ret.push_back(iqenum); + } + } + return ret; +} + +/************************************ +Function that gives back an error +string for a Q_ENUMS mismatch. +************************************/ +QString ParseManager::getErrorMessage(QENUMITEM* qenum) +{ + QString ret = ""; + QTextStream out(&ret); + + if(!qenum->foundallenums) + { + unsigned int firsttoken = qenum->highestlevelclass->classspec->name->firstToken(); + unsigned int lasttoken = qenum->highestlevelclass->classspec->name->lastToken(); + for(unsigned int i = firsttoken; i < lasttoken; i++){ + out << qenum->trlUnit->spell(i); + } + out << "::"; + firsttoken = qenum->ast->firstToken(); + lasttoken = qenum->ast->lastToken(); + for(unsigned int i = firsttoken; i <= lasttoken; i++){ + out << qenum->trlUnit->spell(i) << " "; + } + out << endl << " - one or more Enums missing." << endl; + } + + for(int i = 0; i < qenum->classWichIsNotFound.size(); i++){ + if(ret.size() > 0) + out << endl; + + out << qenum->classWichIsNotFound[i] << "::"; + + unsigned int firsttoken = qenum->ast->firstToken(); + unsigned int lasttoken = qenum->ast->lastToken(); + for(unsigned int i = firsttoken; i <= lasttoken; i++){ + out << qenum->trlUnit->spell(i) << " "; + } + } + return ret; +} +//---> + +//<------------------------------------------------------- Start of Q_FLAGS checks +/*********************************** +Function that checks all flags +which will occur in the MetaData +***********************************/ +QList<ParseManager::QFLAGITEM*> ParseManager::checkMetadataFlags(const QList<QList<QFLAGITEM*> > &classqflaglist + , const QList<QList<QDECLAREFLAGSITEM*> > &classqdeclareflaglist + , const QList<QList<ENUMITEM*> > &classenumlist + , const QList<QList<QFLAGITEM*> > &iclassqflaglist + , const QList<QList<QDECLAREFLAGSITEM*> > &iclassqdeclareflaglist + , const QList<QList<ENUMITEM*> > &iclassenumlist) +{ + QList<QFLAGITEM*> missingqflags; + //assign the enums to the flags + foreach(QList<QFLAGITEM*>qflaglist, classqflaglist){ + foreach(QFLAGITEM* qflag, qflaglist){ + assignFlagValues(qflag, classqdeclareflaglist, classenumlist); + } + } + foreach(QList<QFLAGITEM*>qflaglist, iclassqflaglist){ + foreach(QFLAGITEM* qflag, qflaglist){ + assignFlagValues(qflag, iclassqdeclareflaglist, iclassenumlist); + } + } + + //Compare each qenum from interface with qenum from header (incl. baseclass functions) + QList<QFLAGITEM*> iqflags; + foreach(QList<QFLAGITEM*>iqflaglist, iclassqflaglist){ + iqflags.clear(); + //check if one header class contains all function from one interface header class + if(classqflaglist.count() >0){ + foreach(QList<QFLAGITEM*>qflaglist, classqflaglist){ + QList<QFLAGITEM*> tmpl = containsAllFlags(qflaglist, iqflaglist); + if(tmpl.size() == 0) + iqflags.clear(); + else + iqflags.append(tmpl); + + } + } + else { + foreach(QFLAGITEM *pflag, iqflaglist) + pflag->classWichIsNotFound << "<all classes>"; + iqflags.append(iqflaglist); + } + missingqflags.append(iqflags); + } + return missingqflags; +} + +/************************************** +Function that resolves the dependensies +between Q_FLAG, Q_DECLARE_FLAGS +and enums. +***************************************/ +void ParseManager::assignFlagValues(QFLAGITEM* qflags, const QList<QList<QDECLAREFLAGSITEM*> > &qdeclareflagslookuplist, const QList<QList<ENUMITEM*> > &enumlookuplist) +{ + QString qflagname; + QString enumname; + //read the flag names + for (EnumeratorListAST *plist = qflags->ast->enumerator_list; plist; plist = plist->next) { + EnumeratorAST *pflags = plist->value->asEnumerator(); + if(pflags){ + qflagname = qflags->trlUnit->spell(pflags->firstToken()); + enumname = qflagname; + //try to find if there is a deflare flag macro with the same name as in qflagname + bool found = false; + foreach(QList<QDECLAREFLAGSITEM*> qdeclarelist, qdeclareflagslookuplist){ + foreach(QDECLAREFLAGSITEM* qdeclare, qdeclarelist){ + QString declarename = qdeclare->trlUnit->spell(qdeclare->ast->flag_token); + if(declarename == qflagname){ + //now map the right enum name to the flag + enumname = qdeclare->trlUnit->spell(qdeclare->ast->enum_token); + found = true; + break; + } + } + if(found) + break; + } + //now we have the right enum name now we need to find the enum + found = false; + foreach(QList<ENUMITEM*> enumitemlist, enumlookuplist){ + foreach(ENUMITEM* enumitem, enumitemlist){ + EnumSpecifierAST *penumspec = enumitem->ast; + QString enumspecname = enumitem->trlUnit->spell(penumspec->name->firstToken()); + if(enumspecname == enumname){ + qflags->enumvalues << getEnumValueStringList(enumitem, qflagname); + found = true; + break; + } + } + if(found) + break; + } + if(!found) + qflags->foundallenums = false; + } + } +} + +/***************************************** +Function that compares if all enums +and flags assigned by using the Q_FLAGS +are complete defined. +*****************************************/ +QList<ParseManager::QFLAGITEM*> ParseManager::containsAllFlags(const QList<QFLAGITEM*> &classqflaglist, const QList<QFLAGITEM*> &iclassqflaglist) +{ + QList<QFLAGITEM*> ret; + foreach(QFLAGITEM* iqflags, iclassqflaglist){ + if(iqflags->foundallenums){ + bool found = false; + QStringList missingimplinclasses; + ClassSpecifierAST* clspec = 0; + foreach(QFLAGITEM* qflags, classqflaglist){ + if(clspec != qflags->highestlevelclass->classspec){ + clspec = qflags->highestlevelclass->classspec; + //get the classname + QString classname = ""; + unsigned int firsttoken = clspec->name->firstToken(); + classname += qflags->trlUnit->spell(firsttoken); + if(missingimplinclasses.indexOf(classname) < 0) + missingimplinclasses.push_back(classname); + } + if(qflags->isEqualTo(iqflags)){ + found = true; + missingimplinclasses.clear(); + break; + } + } + if(!found){ + iqflags->classWichIsNotFound.append(missingimplinclasses); + ret.push_back(iqflags); + } + } + else + ret.push_back(iqflags); + } + return ret; +} + +/************************************ +Function that gives back an error +string for a Q_FLAGS mismatch. +************************************/ +QString ParseManager::getErrorMessage(QFLAGITEM* pfg) +{ + QString ret = ""; + QTextStream out(&ret); + + if(!pfg->foundallenums) + { + unsigned int firsttoken = pfg->highestlevelclass->classspec->name->firstToken(); + unsigned int lasttoken = pfg->highestlevelclass->classspec->name->lastToken(); + for(unsigned int i = firsttoken; i < lasttoken; i++){ + out << pfg->trlUnit->spell(i); + } + out << "::"; + firsttoken = pfg->ast->firstToken(); + lasttoken = pfg->ast->lastToken(); + for(unsigned int i = firsttoken; i <= lasttoken; i++){ + out << pfg->trlUnit->spell(i) << " "; + } + out << endl << " - one or more Enums missing." << endl; + } + for(int i = 0; i < pfg->classWichIsNotFound.size(); i++){ + if(ret.size() > 0) + out << endl; + + out << pfg->classWichIsNotFound[i] << "::"; + + unsigned int firsttoken = pfg->ast->firstToken(); + unsigned int lasttoken = pfg->ast->lastToken(); + for(unsigned int i = firsttoken; i <= lasttoken; i++){ + out << pfg->trlUnit->spell(i) << " "; + } + } + return ret; +} +//---> diff --git a/src/tools/ICheck/ICheckLib/ParseManager.h b/src/tools/ICheck/ICheckLib/ParseManager.h new file mode 100644 index 0000000000000000000000000000000000000000..329fc8f56280a955cf77aa5e48fe072d091a7539 --- /dev/null +++ b/src/tools/ICheck/ICheckLib/ParseManager.h @@ -0,0 +1,300 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +** Description: +** +** The ParseManager parses and compares to different header files +** of its metadata. This can be used for checking if an Interface +** is implemented complete. +** +** How to use it: +** +** //Parse the interface header +** ParseManager* iParseManager = new ParseManager(); +** iParseManager->setIncludePath(iIncludepathlist); +** iParseManager->parse(iFilelist); +** +** //Parse the header that needs to be compared against the interface header +** ParseManager* chParseManager = new ParseManager(); +** chIncludepathlist << getQTIncludePath(); +** chParseManager->setIncludePath(chIncludepathlist); +** chParseManager->parse(chFilelist); +** +** if(!chParseManager->checkAllMetadatas(iParseManager)){ +** cout << "Folowing interface items are missing:" << endl; +** QStringList errorlist = chParseManager->getErrorMsg(); +** foreach(QString msg, errorlist){ +** cout << (const char *)msg.toLatin1() << endl; +** } +** return -1; +** } +** else +** cout << "Interface is full defined."; +** +**************************************************************************/ + + +#ifndef PARSEMANAGER_H +#define PARSEMANAGER_H + +#include <QObject> +#include <QList> +#include <QFuture> +#include <QStringList> +#include "cplusplus\CppDocument.h" + +namespace CppTools{ + namespace Internal{ + class CppPreprocessor; + } +} + +namespace CPlusPlus { + class TranslationUnit; + class AST; + class ClassSpecifierAST; + class SimpleDeclarationAST; + class QPropertyDeclarationAST; + class QEnumDeclarationAST; + class QFlagsDeclarationAST; + class QDeclareFlagsDeclarationAST; + class EnumSpecifierAST; + class Function; + + class ParseManager : public QObject + { + Q_OBJECT + struct CLASSLISTITEM + { + CPlusPlus::TranslationUnit* trlUnit; + ClassSpecifierAST* classspec; + }; + struct CLASSTREE + { + CLASSLISTITEM* highestlevelclass; + QList<CLASSLISTITEM*> classlist; + }; + struct FUNCTIONITEM + { + const CLASSLISTITEM* highestlevelclass; + CPlusPlus::TranslationUnit* trlUnit; + ClassSpecifierAST* classAst; + QStringList classWichIsNotFound; + CPlusPlus::Function* function; + SimpleDeclarationAST* ast; + + bool isEqualTo(FUNCTIONITEM* cpfct, bool ignoreName = true); + void init() + { + highestlevelclass = 0; + trlUnit = 0; + classAst = 0; + function = 0; + ast = 0; + } + }; + struct PROPERTYITEM + { + const CLASSLISTITEM* highestlevelclass; + QStringList classWichIsNotFound; + QPropertyDeclarationAST *ast; + CPlusPlus::TranslationUnit* trlUnit; + bool readdefined; + FUNCTIONITEM *readFct; + bool writedefined; + FUNCTIONITEM *writeFct; + bool resetdefined; + FUNCTIONITEM *resetFct; + bool notifydefined; + FUNCTIONITEM *notifyFct; + bool foundalldefinedfct; + + bool isEqualTo(PROPERTYITEM* cpppt); + void init() + { + highestlevelclass = 0; + ast = 0; + trlUnit = 0; + readdefined = false; + readFct = 0; + writedefined = false; + writeFct = 0; + resetdefined = false; + resetFct = 0; + notifydefined = false; + notifyFct = 0; + foundalldefinedfct = false; + } + }; + + struct QENUMITEM + { + const CLASSLISTITEM* highestlevelclass; + CPlusPlus::TranslationUnit* trlUnit; + QStringList classWichIsNotFound; + QEnumDeclarationAST* ast; + //an item in this list will be shown like: + //EnumName.EnumItemName.Value + //ConnectionState.disconnected.0 + QStringList values; + bool foundallenums; + + bool isEqualTo(QENUMITEM *cpenum); + void init() + { + highestlevelclass = 0; + trlUnit = 0; + ast = 0; + values.clear(); + foundallenums = true; + } + }; + + struct ENUMITEM + { + const CLASSLISTITEM* highestlevelclass; + CPlusPlus::TranslationUnit* trlUnit; + QStringList classWichIsNotFound; + EnumSpecifierAST* ast; + + void init() + { + highestlevelclass = 0; + trlUnit = 0; + ast = 0; + } + }; + + struct QFLAGITEM + { + const CLASSLISTITEM* highestlevelclass; + CPlusPlus::TranslationUnit* trlUnit; + QStringList classWichIsNotFound; + QFlagsDeclarationAST* ast; + QStringList enumvalues; + bool foundallenums; + + bool isEqualTo(QFLAGITEM *cpflag); + void init() + { + highestlevelclass = 0; + trlUnit = 0; + ast = 0; + enumvalues.clear(); + foundallenums = true; + } + }; + + struct QDECLAREFLAGSITEM + { + const CLASSLISTITEM* highestlevelclass; + CPlusPlus::TranslationUnit* trlUnit; + QStringList classWichIsNotFound; + QDeclareFlagsDeclarationAST* ast; + + void init() + { + highestlevelclass = 0; + trlUnit = 0; + ast = 0; + } + }; + + + public: + ParseManager(); + virtual ~ParseManager(); + void setIncludePath(const QStringList &includePath); + void parse(const QStringList &sourceFiles); + bool checkAllMetadatas(ParseManager* pInterfaceParserManager); + CppTools::Internal::CppPreprocessor *getPreProcessor() { return pCppPreprocessor; } + QList<CLASSTREE*> CreateClassLists(); + QStringList getErrorMsg() { return m_errormsgs; } + + private: + void parse(CppTools::Internal::CppPreprocessor *preproc, const QStringList &files); + void getBaseClasses(const CLASSLISTITEM* pclass, QList<CLASSLISTITEM*> &baseclasslist, const QList<CLASSLISTITEM*> &allclasslist); + void getElements(QList<FUNCTIONITEM*> &functionlist + , QList<PROPERTYITEM*> &propertylist + , QList<QENUMITEM*> &qenumlist + , QList<ENUMITEM*> &enumlist + , QList<QFLAGITEM*> &qflaglist + , QList<QDECLAREFLAGSITEM*> &qdeclareflaglist + , const QList<CLASSLISTITEM*> classitems + , const CLASSLISTITEM* highestlevelclass); + + //<--- for Metadata functions checks + QList<FUNCTIONITEM*> checkMetadataFunctions(const QList<QList<FUNCTIONITEM*> > &classfctlist, const QList<QList<FUNCTIONITEM*> > &iclassfctlist); + bool isMetaObjFunction(FUNCTIONITEM* fct); + QList<FUNCTIONITEM*> containsAllMetadataFunction(const QList<FUNCTIONITEM*> &classfctlist, const QList<FUNCTIONITEM*> &iclassfctlist); + QString getErrorMessage(FUNCTIONITEM* fct); + //---> + + //<--- for Q_PROPERTY functions checks + QList<PROPERTYITEM*> checkMetadataProperties(const QList<QList<PROPERTYITEM*> > &classproplist + , const QList<QList<FUNCTIONITEM*> > &classfctlist + , const QList<QList<PROPERTYITEM*> > &iclassproplist + , const QList<QList<FUNCTIONITEM*> > &iclassfctlist); + void assignPropertyFunctions(PROPERTYITEM* prop, const QList<QList<FUNCTIONITEM*> > &fctlookuplist); + QList<PROPERTYITEM*> containsAllPropertyFunction(const QList<PROPERTYITEM*> &classproplist, const QList<PROPERTYITEM*> &iclassproplist); + QString getErrorMessage(PROPERTYITEM* ppt); + //---> + + //<--- for Q_ENUMS checks + QList<QENUMITEM*> checkMetadataEnums(const QList<QList<QENUMITEM*> > &classqenumlist + , const QList<QList<ENUMITEM*> > &classenumlist + , const QList<QList<QENUMITEM*> > &iclassqenumlist + , const QList<QList<ENUMITEM*> > &iclassenumlist); + QStringList getEnumValueStringList(ENUMITEM *penum, QString mappedenumname = ""); + void assignEnumValues(QENUMITEM* qenum, const QList<QList<ENUMITEM*> > &enumlookuplist); + QList<QENUMITEM*> containsAllEnums(const QList<QENUMITEM*> &classqenumlist, const QList<QENUMITEM*> &iclassqenumlist); + QString getErrorMessage(QENUMITEM* qenum); + //---> + + //<--- for QFlags checks ---> + QList<QFLAGITEM*> checkMetadataFlags(const QList<QList<QFLAGITEM*> > &classqflaglist + , const QList<QList<QDECLAREFLAGSITEM*> > &classqdeclareflaglist + , const QList<QList<ENUMITEM*> > &classenumlist + , const QList<QList<QFLAGITEM*> > &iclassqflaglist + , const QList<QList<QDECLAREFLAGSITEM*> > &iclassqdeclareflaglist + , const QList<QList<ENUMITEM*> > &iclassenumlist); + void assignFlagValues(QFLAGITEM* qflags, const QList<QList<QDECLAREFLAGSITEM*> > &qdeclareflagslookuplist, const QList<QList<ENUMITEM*> > &enumlookuplist); + QList<QFLAGITEM*> containsAllFlags(const QList<QFLAGITEM*> &classqflaglist, const QList<QFLAGITEM*> &iclassqflaglist); + QString getErrorMessage(QFLAGITEM* pfg); + //---> + + private: + // cache + QStringList m_includePaths; + QStringList m_frameworkPaths; + QByteArray m_definedMacros; + CppTools::Internal::CppPreprocessor* pCppPreprocessor; + QString m_strHeaderFile; + QStringList m_errormsgs; + }; +} +#endif // PARSEMANAGER_H diff --git a/src/tools/ICheck/ICheckLib/ichecklib.cpp b/src/tools/ICheck/ICheckLib/ichecklib.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ae4cc0b8f12d149fc48098b268ef4c4be29348ba --- /dev/null +++ b/src/tools/ICheck/ICheckLib/ichecklib.cpp @@ -0,0 +1,60 @@ +#include "ichecklib.h" +#include "ParseManager.h" +#include <QtCore/QCoreApplication> +#include <QString> +#include <QStringList> +#include <iostream> +#include <QDebug> +#include <QDir> +#include <QFile> +#include <QFileInfo> +#include <QProcess> + +QStringList getQTIncludePath() +{ + QStringList ret; + QStringList processevironment = QProcess::systemEnvironment(); + foreach(QString item, processevironment){ + if(item.indexOf("QTDIR=") == 0){ + QString qtpath = item.remove("QTDIR="); + ret << qtpath + "\\include\\QtCore"; + break; + } + } + return ret; +} + +ICheckLib::ICheckLib() +: pParseManager(0) +{ +} + +void ICheckLib::ParseHeader(const QStringList& includePath, const QStringList& filelist) +{ + if(pParseManager) + delete pParseManager; + pParseManager = 0; + pParseManager = new CPlusPlus::ParseManager(); + pParseManager->setIncludePath(includePath); + pParseManager->parse(filelist); +} + +bool ICheckLib::check(const ICheckLib& ichecklib /*ICheckLib from interface header*/) +{ + if(pParseManager){ + CPlusPlus::ParseManager* cpparsemanager = ichecklib.pParseManager; + return pParseManager->checkAllMetadatas(cpparsemanager); + } + return false; +} + +QStringList ICheckLib::getErrorMsg() +{ + QStringList ret; + if(pParseManager){ + ret.append(pParseManager->getErrorMsg()); + } + else + ret << "no file was parsed."; + return ret; +} diff --git a/src/tools/ICheck/ICheckLib/ichecklib.h b/src/tools/ICheck/ICheckLib/ichecklib.h new file mode 100644 index 0000000000000000000000000000000000000000..3d7b5df3fa189df466c0607af2d9dd83743f1191 --- /dev/null +++ b/src/tools/ICheck/ICheckLib/ichecklib.h @@ -0,0 +1,21 @@ +#ifndef ICHECKLIB_H +#define ICHECKLIB_H + +#include <QStringList> +#include "ICheckLib_global.h" + +namespace CPlusPlus{ + class ParseManager; +} + +class ICHECKLIBSHARED_EXPORT ICheckLib { +public: + ICheckLib(); + void ParseHeader(const QStringList& includePath, const QStringList& filelist); + bool check(const ICheckLib& ichecklib /*ICheckLib from interface header*/); + QStringList getErrorMsg(); +private: + CPlusPlus::ParseManager* pParseManager; +}; + +#endif // ICHECKLIB_H diff --git a/src/tools/ICheck/ICheckLib/ichecklib_global.h b/src/tools/ICheck/ICheckLib/ichecklib_global.h new file mode 100644 index 0000000000000000000000000000000000000000..c6d6ef76d946ed9edbb43104b235c7924342683b --- /dev/null +++ b/src/tools/ICheck/ICheckLib/ichecklib_global.h @@ -0,0 +1,12 @@ +#ifndef ICHECKLIB_GLOBAL_H +#define ICHECKLIB_GLOBAL_H + +#include <QtCore/qglobal.h> + +#if defined(ICHECKLIB_LIBRARY) +# define ICHECKLIBSHARED_EXPORT Q_DECL_EXPORT +#else +# define ICHECKLIBSHARED_EXPORT Q_DECL_IMPORT +#endif + +#endif // ICHECKLIB_GLOBAL_H diff --git a/src/tools/tools.pro b/src/tools/tools.pro index e90b1d6e1710c598f3b9b45866e1a6d4e86ed0b8..017d2fd2b59cbec7f941d8f09a5755d9667151ca 100644 --- a/src/tools/tools.pro +++ b/src/tools/tools.pro @@ -1,2 +1,2 @@ TEMPLATE = subdirs -win32:SUBDIRS = qtcdebugger +win32:SUBDIRS = qtcdebugger ICheck