summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesper K. Pedersen <jesper.pedersen@kdab.com>2013-04-25 13:29:11 +0200
committerJesper K. Pedersen <jesper.pedersen@kdab.com>2013-04-25 14:19:55 +0200
commitff615fc81ac67b52812dde6e08028018e233373c (patch)
tree4bc61cbf25fc701fc7528216b2a2f5f5c5b42eff
parentb5b67207e6459e129368c13a8069359a74b503f1 (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.qs12
-rw-r--r--objects/cppargument.cpp44
-rw-r--r--objects/cppargument.h41
-rw-r--r--objects/cppeditor.cpp10
-rw-r--r--objects/cppeditor.h4
-rw-r--r--objects/cppfunction.cpp149
-rw-r--r--objects/cppfunction.h68
-rw-r--r--scripting.pro8
-rw-r--r--scriptrunner.cpp11
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"));