diff --git a/CMakeLists.txt b/CMakeLists.txt index 1bdefec..92d052c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,46 +1,46 @@ project(ruby) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ruby_SOURCE_DIR}/cmake/) enable_testing() find_package(KDE4 REQUIRED) find_package(KDevPlatform REQUIRED) include_directories( ${KDEVPLATFORM_INCLUDE_DIR} ${KDE4_INCLUDES} ${KDE4_INCLUDE_DIR}/threadweaver ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ) add_subdirectory(parser) add_subdirectory(duchain) add_subdirectory(navigation) add_subdirectory(app_templates) set(kdevrubylanguagesupport_PART_SRCS - parsejob.cpp + rubyparsejob.cpp rubylanguagesupport.cpp ) kde4_add_plugin(kdevrubylanguagesupport ${kdevrubylanguagesupport_PART_SRCS}) target_link_libraries(kdevrubylanguagesupport ${KDE4_KDEUI_LIBS} ${KDE4_KTEXTEDITOR_LIBS} ${KDE4_THREADWEAVER_LIBRARIES} ${KDEVPLATFORM_INTERFACES_LIBRARIES} ${KDEVPLATFORM_LANGUAGE_LIBRARIES} ${KDEVPLATFORM_PROJECT_LIBRARIES} kdev4rubyparser kdevrubyduchain kdevrubynavigation ) install(TARGETS kdevrubylanguagesupport DESTINATION ${PLUGIN_INSTALL_DIR}) ########### install files ############### install(FILES kdevrubysupport.desktop DESTINATION ${SERVICES_INSTALL_DIR}) install(FILES kdevrubysupport.rc DESTINATION ${DATA_INSTALL_DIR}/kdevrubysupport) diff --git a/parsejob.cpp b/parsejob.cpp deleted file mode 100644 index a5b8a39..0000000 --- a/parsejob.cpp +++ /dev/null @@ -1,171 +0,0 @@ -/* This file is part of KDevelop - * - * Copyright 2008-2010 Alexander Dymo - * Copyright 2011 Miquel Sabaté - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Library General Public License as - * published by the Free Software Foundation; either version 2 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write to the - * Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -/* TODO: Clean This mess */ - -#include -#include - -#include -#include - -#include "parsejob.h" -#include "rubylanguagesupport.h" -#include -#include -#include - - -using namespace KDevelop; - -namespace Ruby -{ - -ParseJob::ParseJob(const KUrl & url, RubyLanguageSupport * parent) - : KDevelop::ParseJob(url) - , m_parser (new RubyParser) - , m_lastAst(NULL) - , m_top (NULL) -{ - m_parent = parent; - m_url = url; -} - -ParseJob::~ParseJob() -{ - /* There's nothing to do here */ -} - -RubyLanguageSupport * ParseJob::ruby() const -{ - return RubyLanguageSupport::self(); -} - -void ParseJob::run() -{ - //Happens during shutdown - if (!ruby()) - return abortJob(); - - if (abortRequested()) - return abortJob(); - - KDevelop::UrlParseLock urlLock(document()); - { - DUChainReadLocker lock(DUChain::lock()); - bool needsUpdate = true; - static const IndexedString langString("Ruby"); - foreach(const ParsingEnvironmentFilePointer & file, DUChain::self()->allEnvironmentFiles(document())) { - if (file->language() != langString) - continue; - if (file->needsUpdate()) { - needsUpdate = true; - break; - } else - needsUpdate = false; - } - if (!(minimumFeatures() & TopDUContext::ForceUpdate || minimumFeatures() & Resheduled) && !needsUpdate) { - kDebug() << "Already up to date" << document().str(); - return; - } - } - - QReadLocker parseLock(ruby()->language()->parseLock()); - KDevelop::ProblemPointer p = readContents(); - if (p || abortRequested()) - return abortJob(); - - /* - * NOTE: Although the parser can retrieve the contents on its own, - * it's better to use contents().contents because this way the contents - * are converted in utf8 format always. - */ - m_parser->setContents(contents().contents); - m_parser->setCurrentDocument(m_url); - m_lastAst = m_parser->parse(); -/* TODO: I'm not sure about the code below ;) - KDevelop::ReferencedTopDUContext top; - { - KDevelop::DUChainReadLocker lock(KDevelop::DUChain::lock()); - top = KDevelop::DUChain::self()->chainForDocument(document()); - } - if (top) { - kDebug() << "re-compiling" << document().str(); - KDevelop::DUChainWriteLocker lock(KDevelop::DUChain::lock()); - top->clearImportedParentContexts(); - top->parsingEnvironmentFile()->clearModificationRevisions(); - top->clearProblems(); - } else - kDebug() << "compiling" << document().str();*/ - - if (m_lastAst != NULL) { - if (abortRequested()) - return abortJob(); - - EditorIntegrator editor; - DeclarationBuilder builder(&editor); -// m_top = builder.build(document(), m_lastAst, m_top); - m_parser->freeAst(m_lastAst); - setDuChain(m_top); - - DUChainWriteLocker lock(DUChain::lock()); - m_top->setFeatures(minimumFeatures()); - KDevelop::ParsingEnvironmentFilePointer file = m_top->parsingEnvironmentFile(); - file->setModificationRevision(contents().modification); - KDevelop::DUChain::self()->updateContextEnvironment(m_top->topContext(), file.data()); - kDebug() << "**** Parsing Succeeded ****"; - - /* TODO: Here will go highlighting handling ;) */ - } else { - kWarning() << "**** Parsing Failed ****"; - DUChainWriteLocker lock; - m_top = DUChain::self()->chainForDocument(document()); - if ( m_top ) { - m_top->parsingEnvironmentFile()->clearModificationRevisions(); - m_top->clearProblems(); - } - else { - ParsingEnvironmentFile * file = new ParsingEnvironmentFile(document()); - static const IndexedString langString("Ruby"); - file->setLanguage(langString); - m_top = new TopDUContext(document(), RangeInRevision(0, 0, INT_MAX, INT_MAX), file); - DUChain::self()->addDocumentChain(m_top); - } - - setDuChain(m_top); - } - - DUChainWriteLocker lock(DUChain::lock()); - foreach (ProblemPointer p, m_parser->m_problems) { - kDebug() << "Added problem to context"; - m_top->addProblem(p); - } - setDuChain(m_top); - - if (abortRequested()) - return abortJob(); -} - -} // End of namespace ruby - - -#include "parsejob.moc" - diff --git a/parsejob.h b/parsejob.h deleted file mode 100644 index 685d609..0000000 --- a/parsejob.h +++ /dev/null @@ -1,82 +0,0 @@ -/* This file is part of KDevelop - * - * Copyright 2008-2010 Alexander Dymo - * Copyright (C) 2011 Miquel Sabaté - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - - -#ifndef RUBY_PARSEJOB_H -#define RUBY_PARSEJOB_H - - -#include -#include -#include - - -class RubyLanguageSupport; - -namespace Ruby -{ - -class RubyParser; - -class ParseJob : public KDevelop::ParseJob -{ - Q_OBJECT - -public: - enum { Resheduled = KDevelop::TopDUContext::LastFeature }; - - /** - * Constructor. - * - * @param url the url of the file to parse. - * @param parent the RubyLanguageSupport this ParseJob is parented to. - */ - ParseJob(const KUrl & url, RubyLanguageSupport * parent); - - /** - * Destructor. - */ - virtual ~ParseJob(); - -protected: - /** - * Runs this ParseJob. - */ - virtual void run(); - -private: - /** - * @return static accessor to avoid casting. - */ - RubyLanguageSupport * ruby() const; - -private: - const RubyLanguageSupport * m_parent; - KUrl m_url; - RubyParser * m_parser; - RubyAst * m_lastAst; - KDevelop::ReferencedTopDUContext m_top; -}; - -} // End of namespace ruby - - -#endif - diff --git a/rubylanguagesupport.cpp b/rubylanguagesupport.cpp index efe0b8c..6be1f9f 100644 --- a/rubylanguagesupport.cpp +++ b/rubylanguagesupport.cpp @@ -1,301 +1,301 @@ /* * This file is part of KDevelop * * Copyright 2006-2010 Alexander Dymo * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "rubylanguagesupport.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include -#include "parsejob.h" +#include "rubyparsejob.h" #include "navigation/railsswitchers.h" #include "navigation/railsdataprovider.h" using namespace Ruby; #define RUBY_FILE_LAUNCH_CONFIGURATION_NAME i18n("Current Ruby File") #define RUBY_CURRENT_FUNCTION_LAUNCH_CONFIGURATION_NAME i18n("Current Ruby Test Function") K_PLUGIN_FACTORY(KDevRubySupportFactory, registerPlugin(); ) K_EXPORT_PLUGIN(KDevRubySupportFactory("kdevrubysupport")) RubyLanguageSupport* RubyLanguageSupport::m_self = 0; RubyLanguageSupport::RubyLanguageSupport( QObject* parent, const QVariantList& /*args*/ ) : KDevelop::IPlugin( KDevRubySupportFactory::componentData(), parent ) , KDevelop::ILanguageSupport() , m_railsSwitchers(new Ruby::RailsSwitchers(this)) , m_rubyFileLaunchConfiguration(0) , m_rubyCurrentFunctionLaunchConfiguration(0) { KDEV_USE_EXTENSION_INTERFACE( KDevelop::ILanguageSupport ) setXMLFile( "kdevrubysupport.rc" ); m_self = this; connect( core()->documentController(), SIGNAL( documentLoaded( KDevelop::IDocument* ) ), this, SLOT( documentLoaded( KDevelop::IDocument* ) ) ); connect( core()->documentController(), SIGNAL( documentClosed( KDevelop::IDocument* ) ), this, SLOT( documentClosed( KDevelop::IDocument* ) ) ); connect( core()->documentController(), SIGNAL( documentStateChanged( KDevelop::IDocument* ) ), this, SLOT( documentChanged( KDevelop::IDocument* ) ) ); connect( core()->documentController(), SIGNAL( documentContentChanged( KDevelop::IDocument* ) ), this, SLOT( documentChanged( KDevelop::IDocument* ) ) ); connect( core()->documentController(), SIGNAL( documentActivated( KDevelop::IDocument* ) ), this, SLOT( documentActivated( KDevelop::IDocument* ) ) ); connect( core()->projectController(), SIGNAL( projectOpened( KDevelop::IProject* ) ), this, SLOT( projectOpened( KDevelop::IProject* ) ) ); connect( core()->projectController(), SIGNAL( projectClosing( KDevelop::IProject* ) ), this, SLOT( projectClosing( KDevelop::IProject* ) ) ); KActionCollection* actions = actionCollection(); KAction *action = actions->addAction("ruby_switch_to_controller"); action->setText(i18n("Switch To Controller")); action->setShortcut(Qt::CTRL | Qt::ALT | Qt::Key_1); connect(action, SIGNAL(triggered(bool)), m_railsSwitchers, SLOT(switchToController())); action = actions->addAction("ruby_switch_to_model"); action->setText(i18n("Switch To Model")); action->setShortcut(Qt::CTRL | Qt::ALT | Qt::Key_2); connect(action, SIGNAL(triggered(bool)), m_railsSwitchers, SLOT(switchToModel())); action = actions->addAction("ruby_switch_to_view"); action->setText(i18n("Switch To View")); action->setShortcut(Qt::CTRL | Qt::ALT | Qt::Key_3); connect(action, SIGNAL(triggered(bool)), m_railsSwitchers, SLOT(switchToView())); action = actions->addAction("ruby_switch_to_test"); action->setText(i18n("Switch To Test")); action->setShortcut(Qt::CTRL | Qt::ALT | Qt::Key_4); connect(action, SIGNAL(triggered(bool)), m_railsSwitchers, SLOT(switchToTest())); action = actions->addAction("ruby_run_current_file"); action->setText(i18n("Run Current File")); action->setShortcut(Qt::META | Qt::Key_F9); connect(action, SIGNAL(triggered(bool)), this, SLOT(runCurrentFile())); action = actions->addAction("ruby_run_current_test_function"); action->setText(i18n("Run Current Test Function")); action->setShortcut(Qt::META | Qt::SHIFT | Qt::Key_F9); connect(action, SIGNAL(triggered(bool)), this, SLOT(runCurrentTestFunction())); m_viewsQuickOpenDataProvider = new RailsDataProvider(Ruby::RailsDataProvider::Views); m_testsQuickOpenDataProvider = new RailsDataProvider(Ruby::RailsDataProvider::Tests); KDevelop::IQuickOpen* quickOpen = core()->pluginController()->extensionForPlugin("org.kdevelop.IQuickOpen"); if (quickOpen) { quickOpen->registerProvider(RailsDataProvider::scopes(), QStringList(i18n("Rails Views")), m_viewsQuickOpenDataProvider); quickOpen->registerProvider(RailsDataProvider::scopes(), QStringList(i18n("Rails Tests")), m_testsQuickOpenDataProvider); } } RubyLanguageSupport::~RubyLanguageSupport() { } RubyLanguageSupport* RubyLanguageSupport::self() { return m_self; } KDevelop::ParseJob* RubyLanguageSupport::createParseJob(const KUrl &url) { return new ParseJob(url, this); } QString RubyLanguageSupport::name() const { return "Ruby"; } QStringList RubyLanguageSupport::extensions() const { return QStringList() << "ILanguageSupport"; } void RubyLanguageSupport::documentActivated(KDevelop::IDocument * document) { Q_UNUSED(document) } void RubyLanguageSupport::documentLoaded(KDevelop::IDocument *document) { kDebug() << "loaded document"; core()->languageController()->backgroundParser()->addDocument(document->url()); } void RubyLanguageSupport::documentClosed(KDevelop::IDocument *document) { Q_UNUSED(document) } void RubyLanguageSupport::projectOpened(KDevelop::IProject *project) { //parse project files KDevelop::BackgroundParser *parser = core()->languageController()->backgroundParser(); foreach (const KDevelop::ProjectFileItem *file, project->files()) parser->addDocument(file->url()); } void RubyLanguageSupport::projectClosing(KDevelop::IProject *project) { Q_UNUSED(project) } void RubyLanguageSupport::documentChanged(KDevelop::IDocument *document) { kDebug() << "loaded document"; core()->languageController()->backgroundParser()->addDocument(document->url()); } void RubyLanguageSupport::runCurrentFile() { KDevelop::IDocument *activeDocument = KDevelop::ICore::self()->documentController()->activeDocument(); if (!activeDocument) return; //todo: adymo: check that this file is actually a ruby source //todo: adymo: disable this action in the UI if current file is not a ruby source if (!m_rubyFileLaunchConfiguration) m_rubyFileLaunchConfiguration = findOrCreateLaunchConfiguration(RUBY_FILE_LAUNCH_CONFIGURATION_NAME); if (!m_rubyFileLaunchConfiguration) return; KConfigGroup cfg = m_rubyFileLaunchConfiguration->config(); setUpLaunchConfigurationBeforeRun(cfg, activeDocument); cfg.writeEntry("Arguments", QStringList() << activeDocument->url().toLocalFile()); cfg.sync(); core()->runController()->execute("execute", m_rubyFileLaunchConfiguration); } void RubyLanguageSupport::runCurrentTestFunction() { KDevelop::IDocument *activeDocument = KDevelop::ICore::self()->documentController()->activeDocument(); if (!activeDocument) return; //todo: adymo: check that this file is actually a ruby source //todo: adymo: disable this action in the UI if current file is not a ruby source if (!m_rubyCurrentFunctionLaunchConfiguration) m_rubyCurrentFunctionLaunchConfiguration = findOrCreateLaunchConfiguration(RUBY_CURRENT_FUNCTION_LAUNCH_CONFIGURATION_NAME); if (!m_rubyCurrentFunctionLaunchConfiguration) return; //find function under the cursor (if any) QString currentFunction = findFunctionUnderCursor(activeDocument); kDebug(9047) << "current function" << currentFunction; if (currentFunction.isEmpty()) return; KConfigGroup cfg = m_rubyCurrentFunctionLaunchConfiguration->config(); setUpLaunchConfigurationBeforeRun(cfg, activeDocument); QStringList args; args << activeDocument->url().toLocalFile() << "-n" << currentFunction; cfg.writeEntry("Arguments", args.join(" ")); cfg.sync(); core()->runController()->execute("execute", m_rubyCurrentFunctionLaunchConfiguration); } QString RubyLanguageSupport::findFunctionUnderCursor(KDevelop::IDocument *doc) { QString function; KDevelop::DUChainReadLocker lock( KDevelop::DUChain::lock() ); KDevelop::TopDUContext* topContext = KDevelop::DUChainUtils::standardContextForUrl( doc->url() ); if (!topContext) return ""; KDevelop::CursorInRevision cursor = KDevelop::CursorInRevision(doc->cursorPosition().line(), doc->cursorPosition().column()); KDevelop::DUContext* context = topContext->findContextAt(cursor); if (!context) return ""; kDebug(9047) << "CONTEXT ID" << context->localScopeIdentifier(); return context->localScopeIdentifier().toString(); } void RubyLanguageSupport::setUpLaunchConfigurationBeforeRun(KConfigGroup &cfg, KDevelop::IDocument *activeDocument) { KUrl railsRoot = RailsSwitchers::findRailsRoot(activeDocument->url()); if (!railsRoot.isEmpty()) cfg.writeEntry("Working Directory", railsRoot); else cfg.writeEntry("Working Directory", activeDocument->url().directory()); } KDevelop::ILaunchConfiguration* RubyLanguageSupport::findOrCreateLaunchConfiguration(const QString& name) { foreach (KDevelop::ILaunchConfiguration *config, core()->runController()->launchConfigurations()) { if (config->name() == name) return config; } KDevelop::ILaunchConfiguration *config = 0; IExecutePlugin* executePlugin = core()->pluginController()->pluginForExtension("org.kdevelop.IExecutePlugin")->extension(); KDevelop::LaunchConfigurationType* type = core()->runController()->launchConfigurationTypeForId(executePlugin->nativeAppConfigTypeId()); if (!type) return 0; KDevelop::ILaunchMode* mode = core()->runController()->launchModeForId("execute"); if (!mode) return 0; KDevelop::ILauncher *launcher = 0; foreach (KDevelop::ILauncher *l, type->launchers()) { if (l->supportedModes().contains("execute")) launcher = l; } if (!launcher) return 0; config = core()->runController()->createLaunchConfiguration(type, qMakePair(mode->id(), launcher->id()), 0, name); KConfigGroup cfg = config->config(); cfg.writeEntry("isExecutable", true); cfg.writeEntry("Executable", "ruby"); cfg.sync(); return config; } #include "rubylanguagesupport.moc" // kate: space-indent on; indent-width 4; tab-width 4; replace-tabs on