diff options
author | Jesper K. Pedersen <jesper.pedersen@kdab.com> | 2013-04-25 13:29:11 +0200 |
---|---|---|
committer | Jesper K. Pedersen <jesper.pedersen@kdab.com> | 2013-04-25 14:19:55 +0200 |
commit | ff615fc81ac67b52812dde6e08028018e233373c (patch) | |
tree | 4bc61cbf25fc701fc7528216b2a2f5f5c5b42eff | |
parent | b5b67207e6459e129368c13a8069359a74b503f1 (diff) |
Make it possible to extract information about methods
Change-Id: Id4faec0c4b540ef040043b1c76ae07e628a29c0e
Reviewed-by: Nicolas Arnaud-Cormos <nicolas@kdab.com>
-rw-r--r-- | examples/method-info.qs | 12 | ||||
-rw-r--r-- | objects/cppargument.cpp | 44 | ||||
-rw-r--r-- | objects/cppargument.h | 41 | ||||
-rw-r--r-- | objects/cppeditor.cpp | 10 | ||||
-rw-r--r-- | objects/cppeditor.h | 4 | ||||
-rw-r--r-- | objects/cppfunction.cpp | 149 | ||||
-rw-r--r-- | objects/cppfunction.h | 68 | ||||
-rw-r--r-- | scripting.pro | 8 | ||||
-rw-r--r-- | scriptrunner.cpp | 11 |
9 files changed, 345 insertions, 2 deletions
diff --git a/examples/method-info.qs b/examples/method-info.qs new file mode 100644 index 0000000..1d8da56 --- /dev/null +++ b/examples/method-info.qs @@ -0,0 +1,12 @@ +var fun = editors.current().currentFunction() +console.log("Name: " + fun.name) +console.log("Return Type: " + fun.returnType) +console.log("Arguments: " + fun.arguments.length) +for ( var i = 0; i < + fun.arguments.length; i++ ) { + var arg = fun.arguments[i] + console.log(" Argument: name:" + arg.name + " type:" + arg.type + " initializer: " + arg.initializer) +} +console.log("isVirtual=" + fun.isVirtual + " isOverride=" + fun.isOverride ++ " isFinal=" + fun.isFinal + " isVariadic=" + fun.isVariadic + " isConst=" ++ fun.isConst + " isVolatile=" + fun.isVolatile + " isPureVirtual=" + +fun.isPureVirtual) diff --git a/objects/cppargument.cpp b/objects/cppargument.cpp new file mode 100644 index 0000000..10224c6 --- /dev/null +++ b/objects/cppargument.cpp @@ -0,0 +1,44 @@ +#include "cppargument.h" + +#include <cplusplus/Symbol.h> +#include <cplusplus/Symbols.h> +#include <cplusplus/Overview.h> +#include <cplusplus/Literals.h> + +namespace Scripting { +namespace Internal { + + +CppArgument *CppArgument::create(CPlusPlus::Argument* argument) +{ + // Instance owned by QtScript + CppArgument* result = new CppArgument; + + CPlusPlus::Overview o; + result->m_name = o(argument->name()); + result->m_type = o(argument->type()); + result->m_initializer = argument->initializer() ? QString::fromUtf8(argument->initializer()->chars()) : QString(); + return result; +} + +QString CppArgument::name() const +{ + return m_name; +} + +QString CppArgument::type() const +{ + return m_type; +} + +QString CppArgument::initializer() const +{ + return m_initializer; +} + +CppArgument::CppArgument() +{ +} + +} // namespace Internal +} // namespace Scripting diff --git a/objects/cppargument.h b/objects/cppargument.h new file mode 100644 index 0000000..5eaae36 --- /dev/null +++ b/objects/cppargument.h @@ -0,0 +1,41 @@ +#ifndef SCRIPTING_INTERNAL_CPPARGUMENT_H +#define SCRIPTING_INTERNAL_CPPARGUMENT_H + +#include <QObject> +#include <QMetaType> + +namespace CPlusPlus { + class Argument; +} + +namespace Scripting { +namespace Internal { + +class CppArgument : public QObject +{ + Q_OBJECT + Q_PROPERTY(QString name READ name) + Q_PROPERTY(QString type READ type) + Q_PROPERTY(QString initializer READ initializer) + +public: + static CppArgument* create( CPlusPlus::Argument* ); + + QString name() const; + QString type() const; + QString initializer() const; + +private: + CppArgument(); + + QString m_name; + QString m_type; + QString m_initializer; +}; + +} // namespace Internal +} // namespace Scripting + +Q_DECLARE_METATYPE(Scripting::Internal::CppArgument*) + +#endif // SCRIPTING_INTERNAL_CPPARGUMENT_H diff --git a/objects/cppeditor.cpp b/objects/cppeditor.cpp index c408e43..0226ca7 100644 --- a/objects/cppeditor.cpp +++ b/objects/cppeditor.cpp @@ -3,6 +3,7 @@ #include <coreplugin/actionmanager/actionmanager.h> #include <cppeditor/cppeditorconstants.h> #include "utils/signalwaiter.h" +#include "cppfunction.h" namespace Scripting { namespace Internal { @@ -17,6 +18,15 @@ void CppEditor::switchDeclarationDefinition() Core::ActionManager::command(::CppEditor::Constants::SWITCH_DECLARATION_DEFINITION)->action()->trigger(); } +CppFunction *CppEditor::currentFunction() const +{ + return functionAt(editor()->currentLine(), editor()->currentColumn()); +} + +CppFunction* CppEditor::functionAt(int line, int column) const +{ + return CppFunction::create(line, column, editor()->document()->fileName()); +} /** \brief Wait for the editor to signal that it has been initialized after opening a file diff --git a/objects/cppeditor.h b/objects/cppeditor.h index c76b5a5..e9e499c 100644 --- a/objects/cppeditor.h +++ b/objects/cppeditor.h @@ -13,6 +13,8 @@ namespace Scripting { namespace Internal { +class CppFunction; + class CppEditor : public BaseTextEditor { Q_OBJECT @@ -21,6 +23,8 @@ public: public slots: void switchDeclarationDefinition(); + CppFunction* functionAt(int line, int column) const; + CppFunction* currentFunction() const; protected: void waitForInitialized(); diff --git a/objects/cppfunction.cpp b/objects/cppfunction.cpp new file mode 100644 index 0000000..611b22c --- /dev/null +++ b/objects/cppfunction.cpp @@ -0,0 +1,149 @@ +#include "cppfunction.h" +#include <cplusplus/Symbol.h> +#include <cpptools/ModelManagerInterface.h> +#include <cplusplus/Overview.h> +#include "cppargument.h" + +namespace Scripting { +namespace Internal { + +CppFunction::CppFunction() +{ +} + +CppFunction *CppFunction::create(int line, int column, const QString &fileName) +{ + const CPlusPlus::Function* fun = function(line, column, fileName ); + if (!fun) + return 0; + + // The fun object might be destructed at any time, so we need to collect all the information. + CppFunction* result = new CppFunction; // QtScript takes ownership + result->m_name = extractName(fun); + result->m_returnType = extractReturnType(fun); + result->m_arguments = extractArguments(fun); + result->m_isVirtual = fun->isVirtual(); + result->m_isOverride = fun->isOverride(); + result->m_isFinal = fun->isFinal(); + result->m_isVariadic = fun->isVariadic(); + result->m_isConst = fun->isConst(); + result->m_isVolatile = fun->isVolatile(); + result->m_isPureVirtual = fun->isPureVirtual(); + + return result; +} + +CPlusPlus::Function *CppFunction::function(int line, int column, const QString &fileName) +{ + const CPlusPlus::Snapshot snapshot = CPlusPlus::CppModelManagerInterface::instance()->snapshot(); + const CPlusPlus::Document::Ptr document = snapshot.document(fileName); + if (!document) + return 0; + + CPlusPlus::Symbol *symbol = document->lastVisibleSymbolAt(line, column); + if (!symbol) + return 0; + + // Find the enclosing function scope (which might be several levels up, or we might be standing on it) + CPlusPlus::Scope *scope; + if (symbol->isScope()) + scope = symbol->asScope(); + else + scope = symbol->enclosingScope(); + + while (scope && !scope->isFunction() ) + scope = scope->enclosingScope(); + + if (!scope) + return 0; + + return scope->asFunction(); +} + +QString CppFunction::extractName(const CPlusPlus::Function *function) +{ + const CPlusPlus::Overview o; + QString result = o(function->name()); + + // Prepend namespace "Foo::Foo::foo()" up to empty root namespace + for (const CPlusPlus::Symbol *owner = function->enclosingNamespace(); + owner; owner = owner->enclosingNamespace()) { + const QString name = o(owner->name()); + if (name.isEmpty()) { + break; + } else { + result.prepend(QLatin1String("::")); + result.prepend(name); + } + } + + return result; +} + +QString CppFunction::extractReturnType(const CPlusPlus::Function *function) +{ + return CPlusPlus::Overview()(function->returnType()); +} + +QList<CppArgument*> CppFunction::extractArguments(const CPlusPlus::Function *function) +{ + QList<CppArgument*> result; + for (unsigned int i=0; i <function->argumentCount(); ++i ) { + result.append(CppArgument::create(function->argumentAt(i)->asArgument())); + } + return result; +} + +QString CppFunction::name() const +{ + return m_name; +} + +QString CppFunction::returnType() const +{ + return m_returnType; +} + +QList<CppArgument *> CppFunction::arguments() const +{ + return m_arguments; +} + +bool CppFunction::isVirtual() const +{ + return m_isVirtual; +} + +bool CppFunction::isOverride() const +{ + return m_isOverride; +} + +bool CppFunction::isFinal() const +{ + return m_isFinal; +} + +bool CppFunction::isVariadic() const +{ + return m_isVariadic; +} + +bool CppFunction::isConst() const +{ + return m_isConst; +} + +bool CppFunction::isVolatile() const +{ + return m_isVolatile; +} + +bool CppFunction::isPureVirtual() const +{ + return m_isPureVirtual; +} + + +} // namespace Internal +} // namespace Scripting diff --git a/objects/cppfunction.h b/objects/cppfunction.h new file mode 100644 index 0000000..7140de7 --- /dev/null +++ b/objects/cppfunction.h @@ -0,0 +1,68 @@ +#ifndef SCRIPTING_INTERNAL_CPPFUNCTION_H +#define SCRIPTING_INTERNAL_CPPFUNCTION_H + +#include <QObject> +#include <QMetaType> +#include <QList> + +namespace CPlusPlus { + class Function; +} + +namespace Scripting { +namespace Internal { + +class CppArgument; + +class CppFunction : public QObject +{ + Q_OBJECT + Q_PROPERTY( QString name READ name ) + Q_PROPERTY( QString returnType READ returnType ) + Q_PROPERTY( QList<CppArgument*> arguments READ arguments ) + Q_PROPERTY( bool isVirtual READ isVirtual ) + Q_PROPERTY( bool isOverride READ isOverride ) + Q_PROPERTY( bool isFinal READ isFinal ) + Q_PROPERTY( bool isVariadic READ isVariadic ) + Q_PROPERTY( bool isConst READ isConst ) + Q_PROPERTY( bool isVolatile READ isVolatile ) + Q_PROPERTY( bool isPureVirtual READ isPureVirtual ) + +public: + static CppFunction* create(int line, int column, const QString& fileName); + QString name() const; + QString returnType() const; + QList<CppArgument*> arguments() const; + bool isVirtual() const; + bool isOverride() const; + bool isFinal() const; + bool isVariadic() const; + bool isConst() const; + bool isVolatile() const; + bool isPureVirtual() const; + +private: + CppFunction(); + static CPlusPlus::Function* function(int line,int column, const QString& fileName); + static QString extractName(const CPlusPlus::Function* function); + static QString extractReturnType(const CPlusPlus::Function* function); + static QList<CppArgument *> extractArguments(const CPlusPlus::Function* function); + + QString m_name; + QString m_returnType; + QList<CppArgument*> m_arguments; + bool m_isVirtual; + bool m_isOverride; + bool m_isFinal; + bool m_isVariadic; + bool m_isConst; + bool m_isVolatile; + bool m_isPureVirtual; +}; + +} // namespace Internal +} // namespace Scripting + +Q_DECLARE_METATYPE(Scripting::Internal::CppFunction*) + +#endif // SCRIPTING_INTERNAL_CPPFUNCTION_H diff --git a/scripting.pro b/scripting.pro index c73ec43..67284c6 100644 --- a/scripting.pro +++ b/scripting.pro @@ -19,7 +19,9 @@ SOURCES += scriptingplugin.cpp \ objects/texteditor.cpp \ scriptwrappers.cpp \ enumwappers.cpp \ - utils/dialogs.cpp + utils/dialogs.cpp \ + objects/cppfunction.cpp \ + objects/cppargument.cpp HEADERS += scriptingplugin.h \ scripting_global.h \ @@ -37,7 +39,9 @@ HEADERS += scriptingplugin.h \ scriptwrappers.h \ objects/enums.h \ enumwappers.h \ - utils/dialogs.h + utils/dialogs.h \ + objects/cppfunction.h \ + objects/cppargument.h # Qt Creator linking diff --git a/scriptrunner.cpp b/scriptrunner.cpp index 097548f..bad389b 100644 --- a/scriptrunner.cpp +++ b/scriptrunner.cpp @@ -44,6 +44,8 @@ #include "scriptwrappers.h" #include "enumwappers.h" #include "utils/dialogs.h" +#include "objects/cppfunction.h" +#include "objects/cppargument.h" using namespace Scripting; using namespace Scripting::Internal; @@ -81,6 +83,7 @@ ErrorMessage ScriptRunner::runScript(const QString &sourceCode, const QString fi return ErrorMessage(); } +Q_DECLARE_METATYPE(QList<CppArgument*>) ScriptRunner::QScriptEnginePtr ScriptRunner::ensureEngineInitialized() { @@ -91,6 +94,14 @@ ScriptRunner::QScriptEnginePtr ScriptRunner::ensureEngineInitialized() qRegisterMetaType<Editor*>("Editor*"); SharedTools::registerQObject<Editor>(m_engine.data()); + qRegisterMetaType<CppFunction*>("CppFunction*"); + SharedTools::registerQObject<CppFunction>(m_engine.data()); + + qRegisterMetaType<CppArgument*>("CppArgument*"); + SharedTools::registerQObject<CppArgument>(m_engine.data()); + + qScriptRegisterSequenceMetaType< QList<CppArgument*> >(m_engine.data()); + registerGlobal(new Console, QLatin1String("console")); registerGlobal(new Editors, QLatin1String("editors")); registerGlobal(new Dialogs, QLatin1String("dialogs")); |