├── .gitignore ├── .gitlab-ci.yml ├── .kde-ci.yml ├── CMakeLists.txt ├── ExtraDesktop.sh ├── Gemfile ├── Guardfile ├── LICENSE ├── LICENSES └── CC0-1.0.txt ├── Messages.sh ├── README.md ├── app_templates ├── CMakeLists.txt ├── rubygem │ ├── %{APPNAMELC}.gemspec │ ├── %{PROJECTDIRNAME}.kdev4 │ ├── Gemfile │ ├── Rakefile │ ├── lib │ │ └── %{APPNAMELC}.rb │ ├── rubygem.kdevtemplate │ └── test │ │ └── test_helper.rb └── simple_ruby_app │ ├── %{APPNAMELC}.rb │ ├── %{PROJECTDIRNAME}.kdev4 │ ├── .kdev4 │ └── %{PROJECTDIRNAME}.kdev4 │ └── simple_ruby_app.kdevtemplate ├── codegen ├── refactoring.cpp └── refactoring.h ├── completion ├── CMakeLists.txt ├── context.cpp ├── context.h ├── helpers.cpp ├── helpers.h ├── items │ ├── keyworditem.cpp │ ├── keyworditem.h │ ├── normalitem.cpp │ ├── normalitem.h │ ├── requirefileitem.cpp │ └── requirefileitem.h ├── model.cpp ├── model.h ├── tests │ ├── CMakeLists.txt │ ├── completion.cpp │ └── completion.h ├── worker.cpp └── worker.h ├── documentation ├── builtins.rb └── kdevruby_doc.rb ├── duchain ├── CMakeLists.txt ├── builders │ ├── contextbuilder.cpp │ ├── contextbuilder.h │ ├── declarationbuilder.cpp │ ├── declarationbuilder.h │ ├── typebuilder.cpp │ ├── typebuilder.h │ ├── usebuilder.cpp │ └── usebuilder.h ├── declarations │ ├── methoddeclaration.cpp │ ├── methoddeclaration.h │ ├── moduledeclaration.cpp │ ├── moduledeclaration.h │ ├── variabledeclaration.cpp │ └── variabledeclaration.h ├── editorintegrator.cpp ├── editorintegrator.h ├── expressionvisitor.cpp ├── expressionvisitor.h ├── helpers.cpp ├── helpers.h ├── loader.cpp ├── loader.h ├── navigation │ ├── declarationnavigationcontext.cpp │ ├── declarationnavigationcontext.h │ ├── includenavigationcontext.cpp │ ├── includenavigationcontext.h │ ├── navigationwidget.cpp │ └── navigationwidget.h ├── rubyducontext.cpp ├── rubyducontext.h ├── tests │ ├── CMakeLists.txt │ ├── benchmarks.cpp │ ├── benchmarks.h │ ├── duchain.cpp │ ├── duchain.h │ ├── duchaintestbase.cpp │ ├── duchaintestbase.h │ ├── uses.cpp │ └── uses.h └── types │ ├── classtype.cpp │ └── classtype.h ├── highlighting.cpp ├── highlighting.h ├── kdevrubylanguagesupport.json ├── kdevrubysupport.categories ├── kdevrubysupport.qrc ├── kdevrubysupport.rc ├── languagesupport.cpp ├── languagesupport.h ├── launcher.cpp ├── launcher.h ├── parsejob.cpp ├── parsejob.h ├── parser ├── CMakeLists.txt ├── README.md ├── ast.cpp ├── ast.h ├── astvisitor.cpp ├── astvisitor.h ├── hash.c ├── main.c ├── node.c ├── node.h ├── parser.cpp ├── parser.h ├── parser.y └── tools │ ├── fancy.rb │ ├── gperf.rb │ ├── gperf.txt │ ├── holy.rb │ ├── parser_spec.rb │ └── tests │ ├── array.rb │ ├── array.txt │ ├── assign.rb │ ├── assign.txt │ ├── begin_end.rb │ ├── begin_end.txt │ ├── block.rb │ ├── block.txt │ ├── case.rb │ ├── case.txt │ ├── class.rb │ ├── class.txt │ ├── comment.rb │ ├── comment.txt │ ├── comments │ ├── expected.txt │ └── test.rb │ ├── errors │ ├── from18to19.rb │ ├── from19to20.rb │ └── from20to21.rb │ ├── except.rb │ ├── except.txt │ ├── for.rb │ ├── for.txt │ ├── function.rb │ ├── function.txt │ ├── global.rb │ ├── global.txt │ ├── hash.rb │ ├── hash.txt │ ├── heredoc.rb │ ├── heredoc.txt │ ├── ifelse.rb │ ├── ifelse.txt │ ├── method_call.rb │ ├── method_call.txt │ ├── modifiers.rb │ ├── modifiers.txt │ ├── module.rb │ ├── module.txt │ ├── numeric.rb │ ├── numeric.txt │ ├── operators.rb │ ├── operators.txt │ ├── regexp.rb │ ├── regexp.txt │ ├── rocket.rb │ ├── rocket.txt │ ├── ruby20.rb │ ├── ruby20.txt │ ├── semicolon.rb │ ├── semicolon.txt │ ├── simple.rb │ ├── simple.txt │ ├── string.rb │ ├── string.txt │ ├── symbol.rb │ ├── symbol.txt │ ├── utf8.rb │ ├── utf8.txt │ ├── while.rb │ └── while.txt ├── po ├── bs │ └── kdevruby.po ├── ca │ └── kdevruby.po ├── ca@valencia │ └── kdevruby.po ├── cs │ └── kdevruby.po ├── de │ └── kdevruby.po ├── en_GB │ └── kdevruby.po ├── eo │ └── kdevruby.po ├── es │ └── kdevruby.po ├── et │ └── kdevruby.po ├── eu │ └── kdevruby.po ├── fi │ └── kdevruby.po ├── fr │ └── kdevruby.po ├── ga │ └── kdevruby.po ├── gl │ └── kdevruby.po ├── hu │ └── kdevruby.po ├── it │ └── kdevruby.po ├── ja │ └── kdevruby.po ├── ka │ └── kdevruby.po ├── ko │ └── kdevruby.po ├── lt │ └── kdevruby.po ├── mai │ └── kdevruby.po ├── mr │ └── kdevruby.po ├── nds │ └── kdevruby.po ├── nl │ └── kdevruby.po ├── nn │ └── kdevruby.po ├── pl │ └── kdevruby.po ├── pt │ └── kdevruby.po ├── pt_BR │ └── kdevruby.po ├── ru │ └── kdevruby.po ├── sk │ └── kdevruby.po ├── sl │ └── kdevruby.po ├── sv │ └── kdevruby.po ├── th │ └── kdevruby.po ├── tr │ └── kdevruby.po ├── ug │ └── kdevruby.po ├── uk │ └── kdevruby.po ├── zh_CN │ └── kdevruby.po └── zh_TW │ └── kdevruby.po └── rails ├── CMakeLists.txt ├── dataprovider.cpp ├── dataprovider.h ├── helpers.cpp ├── helpers.h ├── quickopendata.cpp ├── quickopendata.h ├── support.cpp ├── support.h ├── switchers.cpp ├── switchers.h └── tests ├── CMakeLists.txt ├── rails.cpp └── rails.h /.gitignore: -------------------------------------------------------------------------------- 1 | # general 2 | apidocs 3 | .kdev4 4 | *.kdev4 5 | *~ 6 | *.bak 7 | doxygen.log 8 | build 9 | *.patch 10 | *.diff 11 | *.orig 12 | *.rej 13 | *.swp 14 | massif.out.* 15 | callgrind.out.* 16 | .*kate-swp 17 | 18 | # from kdiff3 19 | *.BACKUP.* 20 | *.BASE.* 21 | *.LOCAL.* 22 | *.REMOTE.* 23 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: None 2 | # SPDX-License-Identifier: CC0-1.0 3 | 4 | include: 5 | - project: sysadmin/ci-utilities 6 | file: 7 | - /gitlab-templates/linux.yml 8 | - /gitlab-templates/freebsd.yml 9 | -------------------------------------------------------------------------------- /.kde-ci.yml: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: None 2 | # SPDX-License-Identifier: CC0-1.0 3 | 4 | Dependencies: 5 | - 'on': ['@all'] 6 | 'require': 7 | 'frameworks/extra-cmake-modules': '@stable' 8 | 'frameworks/ki18n': '@stable' 9 | 'frameworks/ktexteditor': '@stable' 10 | 'kdevelop/kdevelop': '@stable' 11 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0) 2 | 3 | project(kdev-ruby) 4 | 5 | set(VERSION_MAJOR 1) 6 | set(VERSION_MINOR 90) 7 | set(VERSION_PATCH 90) 8 | 9 | set(CMAKE_CXX_STANDARD 17) 10 | set(CMAKE_CXX_STANDARD_REQUIRED YES) 11 | 12 | find_package (ECM "5.14.0" REQUIRED NO_MODULE) 13 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_MODULE_PATH}) 14 | 15 | include(GenerateExportHeader) 16 | include(KDEInstallDirs) 17 | include(KDECMakeSettings) 18 | include(KDECompilerSettings NO_POLICY_SCOPE) 19 | include(ECMQtDeclareLoggingCategory) 20 | 21 | set(QT_MIN_VERSION "5.5.0") 22 | find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED Core Widgets) 23 | if(BUILD_TESTING) 24 | find_package(Qt5Test ${QT_MIN_VERSION} CONFIG REQUIRED) 25 | endif() 26 | set(KF5_DEP_VERSION "5.15.0") 27 | find_package(KF5 ${KF5_DEP_VERSION} REQUIRED COMPONENTS 28 | TextEditor 29 | I18n 30 | ) 31 | set(KDEVPLATFORM_DEP_VERSION "5.2.40") 32 | find_package(KDevPlatform ${KDEVPLATFORM_DEP_VERSION} CONFIG) 33 | set_package_properties(KDevPlatform PROPERTIES 34 | TYPE REQUIRED 35 | ) 36 | 37 | find_package(BISON REQUIRED) 38 | 39 | # needed for parser/ module prefix with includes for some minimal namespacing 40 | include_directories( 41 | ${CMAKE_CURRENT_BINARY_DIR} 42 | ${CMAKE_CURRENT_SOURCE_DIR} 43 | ) 44 | 45 | add_definitions(-DQT_NO_URL_CAST_FROM_STRING) 46 | 47 | add_definitions( -DTRANSLATION_DOMAIN=\"kdevruby\" ) 48 | 49 | add_subdirectory(parser) 50 | add_subdirectory(duchain) 51 | add_subdirectory(rails) 52 | add_subdirectory(completion) 53 | add_subdirectory(app_templates) 54 | 55 | set(ruby_PLUGIN_SRCS 56 | highlighting.cpp 57 | languagesupport.cpp 58 | launcher.cpp 59 | parsejob.cpp 60 | codegen/refactoring.cpp 61 | ) 62 | ecm_qt_declare_logging_category(ruby_PLUGIN_SRCS 63 | HEADER debug.h 64 | IDENTIFIER KDEV_RUBY 65 | CATEGORY_NAME "kdevelop.languages.ruby" 66 | ) 67 | qt5_add_resources(ruby_PLUGIN_SRCS 68 | kdevrubysupport.qrc 69 | ) 70 | kdevplatform_add_plugin(kdevrubylanguagesupport JSON kdevrubylanguagesupport.json SOURCES ${ruby_PLUGIN_SRCS}) 71 | 72 | target_link_libraries(kdevrubylanguagesupport 73 | KF5::I18n 74 | KF5::TextEditor 75 | 76 | KDev::Language 77 | KDev::Util 78 | 79 | kdevrubyparser 80 | kdevrubyduchain 81 | kdevrubycompletion 82 | kdevrubyrails 83 | ) 84 | 85 | install(FILES documentation/builtins.rb DESTINATION ${KDE_INSTALL_DATADIR}/kdevrubysupport/documentation/) 86 | 87 | # kdebugsettings file 88 | install(FILES kdevrubysupport.categories DESTINATION ${KDE_INSTALL_CONFDIR}) 89 | 90 | ki18n_install(po) 91 | 92 | feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES) 93 | -------------------------------------------------------------------------------- /ExtraDesktop.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | #This file outputs in a separate line each file with a .desktop syntax 3 | #that needs to be translated but has a non .desktop extension 4 | find -name \*.kdevtemplate -print 5 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gem 'libnotify' 4 | gem 'rb-inotify', '~> 0.9.0' 5 | gem 'guard', '~> 2.6.0' 6 | gem 'rspec', '~> 3.1.0' 7 | gem 'guard-rspec' 8 | -------------------------------------------------------------------------------- /Messages.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | files=`find . -name \*.rc -o -name \*.ui` 3 | if [ "x$files" != "x" ]; then 4 | $EXTRACTRC $files >> rc.cpp 5 | fi 6 | $XGETTEXT `find . -name \*.cc -o -name \*.cpp -o -name \*.h` -o $podir/kdevruby.pot 7 | rm -f rc.cpp 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # KDevelop Ruby Support 2 | 3 | This is a [KDevelop](https://www.kdevelop.org/) language plugin that 4 | implements the support for the Ruby programming language. It provides 5 | everything that you can expect from a KDevelop language plugin such as: 6 | 7 | - Parsing of full projects. 8 | - Semantic highlighting. 9 | - Code browsing. 10 | - Full code completion. 11 | 12 | ## Build and Install 13 | 14 | Some distributions have this plugin as a precompiled package already. If you 15 | want to build this plugin yourself, the page on 16 | [KDE TechBase](https://techbase.kde.org/Projects/KDevelop4/Ruby) has all the 17 | info you need and more. 18 | 19 | If you're using Mac OSX, you can also try out the old plugin maintained by 20 | Alexander Dymo that can be installed through 21 | [Homebrew](https://github.com/adymo/homebrew-kde). 22 | 23 | ## Contributing 24 | 25 | All the basic info that you need can be found in 26 | [KDE TechBase](https://techbase.kde.org/Projects/KDevelop4/Ruby). 27 | 28 | The preferred way to report bugs is through the [KDE Bugtracking 29 | System](https://bugs.kde.org), and patches should be submitted through 30 | [Review Board](https://git.reviewboard.kde.org/r/new/). That being said, 31 | you can also submit issues and pull requests through the Github 32 | [mirror](https://github.com/mssola/kdev-ruby). 33 | 34 | The coding style used in this plugin is of my 35 | [own](https://github.com/mssola/conventions/blob/master/cpp.md). This coding 36 | style is compliant with the [KDE Coding 37 | Style](https://techbase.kde.org/Policies/Kdelibs_Coding_Style) as described in 38 | [this](https://github.com/mssola/conventions/blob/master/cpp.md#compliance-with-other-coding-conventions) 39 | section. When writing patches you should at least follow the KDE Coding Style. 40 | 41 | ## License 42 | 43 | This plugin is licensed under the `GPLv3+`. Read the `LICENSE` file for more 44 | information about this. There is some legacy code that is licensed under the 45 | `LGPLv2+` though. 46 | 47 | -------------------------------------------------------------------------------- /app_templates/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(apptemplate_DIRS 2 | simple_ruby_app 3 | rubygem 4 | ) 5 | 6 | kdevplatform_add_app_templates(${apptemplate_DIRS}) 7 | -------------------------------------------------------------------------------- /app_templates/rubygem/%{APPNAMELC}.gemspec: -------------------------------------------------------------------------------- 1 | # coding: UTF-8 2 | 3 | Gem::Specification.new do |s| 4 | s.name = "%{APPNAMELC}" 5 | s.version = "0.0.1" 6 | s.platform = Gem::Platform::RUBY 7 | s.authors = ["Author's name"] 8 | s.email = ["author at example dot com"] 9 | s.summary = "WARNING: Update the summary" 10 | s.description = "WARNING: Update the description" 11 | s.required_rubygems_version = ">= 1.3.6" 12 | 13 | # The list of files to be contained in the gem 14 | s.files = ['Rakefile', '%{APPNAMELC}.gemspec', 'Gemfile', 15 | 'test/test_helper.rb', 'lib/%{APPNAMELC}.rb'] 16 | s.require_path = 'lib' 17 | end 18 | -------------------------------------------------------------------------------- /app_templates/rubygem/%{PROJECTDIRNAME}.kdev4: -------------------------------------------------------------------------------- 1 | [Project] 2 | Name=%{APPNAME} 3 | Manager=KDevGenericManager 4 | -------------------------------------------------------------------------------- /app_templates/rubygem/Gemfile: -------------------------------------------------------------------------------- 1 | gemspec 2 | -------------------------------------------------------------------------------- /app_templates/rubygem/Rakefile: -------------------------------------------------------------------------------- 1 | begin 2 | require 'bundler' 3 | Bundler.setup 4 | rescue LoadError 5 | $stderr.puts 'You need to have Bundler installed to be able build this gem.' 6 | end 7 | 8 | gemspec = eval(File.read(Dir["*.gemspec"].first)) 9 | 10 | 11 | desc "Validate the gemspec" 12 | task :validate do 13 | gemspec.validate 14 | end 15 | 16 | desc "Build gem locally" 17 | task :build => :validate do 18 | system "gem build #{gemspec.name}.gemspec" 19 | FileUtils.mkdir_p "pkg" 20 | FileUtils.mv "#{gemspec.name}-#{gemspec.version}.gem", "pkg" 21 | end 22 | 23 | desc "Install gem locally" 24 | task :install => :build do 25 | system "gem install pkg/#{gemspec.name}-#{gemspec.version}" 26 | end 27 | 28 | desc "Remove generated files" 29 | task :clean do 30 | FileUtils.rm_rf "pkg" 31 | end 32 | -------------------------------------------------------------------------------- /app_templates/rubygem/lib/%{APPNAMELC}.rb: -------------------------------------------------------------------------------- 1 | # NOTE: Typically you want to create a subdirectory named '%{APPNAMELC}' 2 | # and then require files from it. 3 | 4 | module Gem 5 | # My Gem 6 | end 7 | -------------------------------------------------------------------------------- /app_templates/rubygem/rubygem.kdevtemplate: -------------------------------------------------------------------------------- 1 | # KDE Config File 2 | [General] 3 | Name=RubyGem 4 | Name[ca]=RubyGem 5 | Name[ca@valencia]=RubyGem 6 | Name[cs]=RubyGem 7 | Name[de]=RubyGem 8 | Name[en_GB]=RubyGem 9 | Name[eo]=RubyGem 10 | Name[es]=RubyGem 11 | Name[et]=RubyGem 12 | Name[eu]=RubyGem 13 | Name[fi]=RubyGem 14 | Name[fr]=RubyGem 15 | Name[gl]=RubyGem 16 | Name[hi]=RubyGem 17 | Name[it]=RubyGem 18 | Name[ka]=RubyGem 19 | Name[ko]=RubyGem 20 | Name[nl]=RubyGem 21 | Name[nn]=RubyGem 22 | Name[pl]=RubyGem 23 | Name[pt]=RubyGem 24 | Name[pt_BR]=RubyGem 25 | Name[ru]=Пакет Ruby («gem») 26 | Name[sk]=RubyGem 27 | Name[sl]=RubyGem 28 | Name[sv]=RubyGem 29 | Name[tr]=RubyGem 30 | Name[uk]=RubyGem 31 | Name[x-test]=xxRubyGemxx 32 | Name[zh_CN]=RubyGem 33 | Name[zh_TW]=RubyGem 34 | Category=Ruby 35 | Comment=Generate a simple RubyGem 36 | Comment[ca]=Genera una RubyGem senzilla 37 | Comment[ca@valencia]=Genera una RubyGem senzilla 38 | Comment[cs]=Vygenerovat jednoduchý RubyGem 39 | Comment[de]=Generiert ein einfaches RubyGem-Programm 40 | Comment[en_GB]=Generate a simple RubyGem 41 | Comment[eo]=Generi simplan RubyGem 42 | Comment[es]=Generar un sencillo RubyGem 43 | Comment[et]=Lihtsa RubyGemi genereerimine 44 | Comment[eu]=Sortu «RubyGem» sinple bat 45 | Comment[fi]=Luo yksinkertainen RubyGem 46 | Comment[fr]=Générer un simple RubyGem 47 | Comment[gl]=Xerar unha RubyGem simple. 48 | Comment[hi]=एक सरल RubyGem बनाएँ 49 | Comment[it]=Genera un semplice pacchetto RubyGem 50 | Comment[ka]=მარტივი RubyGem-ის გენერაცია 51 | Comment[ko]=간단한 RubyGem 생성 52 | Comment[nl]=Een eenvoudige RubyGem genereren 53 | Comment[nn]=Lag ein enkel RubyGem 54 | Comment[pl]=Tworzy prosty RubyGem 55 | Comment[pt]=Gerar um RubyGem simples 56 | Comment[pt_BR]=Gera um RubyGem simples 57 | Comment[sk]=Vygenerovať jednoduchý RubyGem 58 | Comment[sl]=Generiraj enostaven RubyGem 59 | Comment[sv]=Skapa en enkelt RubyGem 60 | Comment[tr]=Basit bir RubyGem oluştur 61 | Comment[uk]=Створити простий RubyGem 62 | Comment[x-test]=xxGenerate a simple RubyGemxx 63 | Comment[zh_CN]=生成一个简单的 RubyGem 64 | Comment[zh_TW]=產生簡單的 RubyGem 65 | ShowFilesAfterGeneration=lib/%{APPNAMELC}.rb 66 | -------------------------------------------------------------------------------- /app_templates/rubygem/test/test_helper.rb: -------------------------------------------------------------------------------- 1 | # Here it goes the test helper 2 | -------------------------------------------------------------------------------- /app_templates/simple_ruby_app/%{APPNAMELC}.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | puts 'Hello World' 4 | -------------------------------------------------------------------------------- /app_templates/simple_ruby_app/%{PROJECTDIRNAME}.kdev4: -------------------------------------------------------------------------------- 1 | [Project] 2 | Name=%{APPNAME} 3 | Manager=KDevGenericManager 4 | -------------------------------------------------------------------------------- /app_templates/simple_ruby_app/.kdev4/%{PROJECTDIRNAME}.kdev4: -------------------------------------------------------------------------------- 1 | [Launch] 2 | Launch Configurations=Launch Configuration 0 3 | 4 | [Launch][Launch Configuration 0] 5 | Configured Launch Modes=execute 6 | Configured Launchers=nativeAppLauncher 7 | Name=New Native Application Configuration 8 | Type=Native Application 9 | 10 | [Launch][Launch Configuration 0][Data] 11 | Arguments=%{APPNAMELC}.rb 12 | Dependencies=@Variant(\x00\x00\x00\t\x00\x00\x00\x00\x00) 13 | Dependency Action=Nothing 14 | EnvironmentGroup=default 15 | Executable=ruby 16 | Working Directory=file://%{PROJECTDIR}/ 17 | isExecutable=true 18 | -------------------------------------------------------------------------------- /app_templates/simple_ruby_app/simple_ruby_app.kdevtemplate: -------------------------------------------------------------------------------- 1 | # KDE Config File 2 | [General] 3 | Name=Simple Ruby Application 4 | Name[ca]=Una aplicació senzilla en Ruby 5 | Name[ca@valencia]=Una aplicació senzilla en Ruby 6 | Name[cs]=Jednoduchá aplikace Ruby 7 | Name[de]=Einfaches Ruby-Programm 8 | Name[en_GB]=Simple Ruby Application 9 | Name[eo]=Simpla Ruby-aplikaĵo 10 | Name[es]=Aplicación sencilla en Ruby 11 | Name[et]=Lihtne Ruby rakendus 12 | Name[eu]=Ruby aplikazio sinple bat 13 | Name[fi]=Yksinkertainen Ruby-sovellus 14 | Name[fr]=Application simple Ruby 15 | Name[gl]=Aplicación simple de Ruby 16 | Name[hi]=सरल रूबी अनुप्रयोग 17 | Name[it]=Semplice applicazione in Ruby 18 | Name[ka]=Ruby-ის მარტივი აპლიკაცია 19 | Name[ko]=간단한 Ruby 앱 20 | Name[nl]=Eenvoudig Ruby-programma 21 | Name[nn]=Enkelt Ruby-program 22 | Name[pl]=Prosta aplikacja Ruby 23 | Name[pt]=Aplicação Simples em Ruby 24 | Name[pt_BR]=Aplicativo Ruby simples 25 | Name[sk]=Jednoduchá Ruby aplikácia 26 | Name[sl]=Enostavna aplikacija Ruby 27 | Name[sv]=Enkelt Ruby-program 28 | Name[tr]=Basit Ruby Uygulaması 29 | Name[uk]=Проста програма мовою Ruby 30 | Name[x-test]=xxSimple Ruby Applicationxx 31 | Name[zh_CN]=简单的 Ruby 应用程序 32 | Name[zh_TW]=簡易 Ruby 應用程式 33 | Category=Ruby 34 | Comment=Generate a simple Ruby application 35 | Comment[ca]=Genera una aplicació senzilla en Ruby 36 | Comment[ca@valencia]=Genera una aplicació senzilla en Ruby 37 | Comment[cs]=Generovat jednoduchou aplikaci Ruby 38 | Comment[de]=Generiert ein einfaches Ruby-Programm 39 | Comment[en_GB]=Generate a simple Ruby application 40 | Comment[eo]=Generi simplan Ruby-aplikaĵon 41 | Comment[es]=Generar una aplicación sencilla en Ruby 42 | Comment[et]=Lihtsa Ruby rakenduse genereerimine 43 | Comment[eu]=Sortu Ruby aplikazio sinple bat 44 | Comment[fi]=Luo yksinkertainen Ruby-sovellus 45 | Comment[fr]=Générer une application simple Ruby. 46 | Comment[gl]=Xerar unha aplicación simple de Ruby 47 | Comment[hi]=एक सरल रूबी अनुप्रयोग बनाएँ 48 | Comment[it]=Genera una semplice applicazione in Ruby 49 | Comment[ka]=მარტივი Ruby-ის აპის გენერაცია 50 | Comment[ko]=간단한 Ruby 앱 생성 51 | Comment[nl]=Een eenvoudig Ruby-programma genereren 52 | Comment[nn]=Lag eit enkelt Ruby-program 53 | Comment[pl]=Tworzy prostą aplikację Ruby 54 | Comment[pt]=Gerar uma aplicação simples em Ruby 55 | Comment[pt_BR]=Gera um aplicativo Ruby simples 56 | Comment[sk]=Vygenerovať jednoduchú Ruby aplikáciu 57 | Comment[sl]=Generiraj enostavno aplikacijo Ruby 58 | Comment[sv]=Skapa ett enkelt Ruby-program 59 | Comment[tr]=Basit bir Ruby uygulaması oluştur 60 | Comment[uk]=Створити просту програму мовою Ruby 61 | Comment[x-test]=xxGenerate a simple Ruby applicationxx 62 | Comment[zh_CN]=生成一个简单的 Ruby 应用程序 63 | Comment[zh_TW]=產生簡單的 Ruby 應用程式 64 | ShowFilesAfterGeneration=%{APPNAMELC}.rb 65 | -------------------------------------------------------------------------------- /codegen/refactoring.cpp: -------------------------------------------------------------------------------- 1 | /* This file is part of KDevelop 2 | * 3 | * Copyright (C) 2014-2015 Miquel Sabaté Solà 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | #include 20 | 21 | using namespace ruby; 22 | 23 | Refactoring::Refactoring(QObject *parent) : BasicRefactoring(parent) 24 | { 25 | } 26 | 27 | -------------------------------------------------------------------------------- /codegen/refactoring.h: -------------------------------------------------------------------------------- 1 | /* This file is part of KDevelop 2 | * 3 | * Copyright (C) 2014-2015 Miquel Sabaté Solà 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | #ifndef RUBY_REFACTORING_H 20 | #define RUBY_REFACTORING_H 21 | 22 | #include 23 | 24 | namespace ruby { 25 | 26 | struct Refactoring : public KDevelop::BasicRefactoring 27 | { 28 | explicit Refactoring(QObject *parent = nullptr); 29 | }; 30 | 31 | } 32 | 33 | #endif // REFACTORING_H 34 | 35 | -------------------------------------------------------------------------------- /completion/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | if(BUILD_TESTING) 2 | add_subdirectory(tests) 3 | endif() 4 | 5 | set(rubycompletion_SRCS 6 | context.cpp 7 | model.cpp 8 | worker.cpp 9 | helpers.cpp 10 | 11 | items/normalitem.cpp 12 | items/keyworditem.cpp 13 | items/requirefileitem.cpp 14 | ) 15 | ecm_qt_declare_logging_category(rubycompletion_SRCS 16 | HEADER completiondebug.h 17 | IDENTIFIER COMPLETION 18 | CATEGORY_NAME "kdevelop.languages.ruby.completion" 19 | ) 20 | 21 | add_library(kdevrubycompletion SHARED ${rubycompletion_SRCS}) 22 | 23 | generate_export_header(kdevrubycompletion EXPORT_MACRO_NAME KDEVRUBYCOMPLETION_EXPORT 24 | EXPORT_FILE_NAME completionexport.h) 25 | 26 | target_link_libraries(kdevrubycompletion LINK_PRIVATE 27 | KDev::Interfaces 28 | KDev::Language 29 | KDev::Util 30 | 31 | kdevrubyduchain 32 | kdevrubyparser 33 | ) 34 | 35 | install(TARGETS kdevrubycompletion DESTINATION ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) 36 | -------------------------------------------------------------------------------- /completion/helpers.cpp: -------------------------------------------------------------------------------- 1 | /* This file is part of KDevelop 2 | * 3 | * Copyright (C) 2012-2015 Miquel Sabaté Solà 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | 28 | using namespace KDevelop; 29 | 30 | namespace ruby 31 | { 32 | 33 | const QString indentString(KTextEditor::Document *document) 34 | { 35 | KTextEditor::ConfigInterface *iface = qobject_cast(document); 36 | if (iface->configValue("replace-tabs").toBool()) { 37 | return QString(iface->configValue("indent-width").toUInt(), ' '); 38 | } 39 | return "\t"; 40 | } 41 | 42 | QString getIndendation(const QString &line) 43 | { 44 | return line.left(line.indexOf(QRegExp("\\S"), 0)); 45 | } 46 | 47 | QString getArgumentList(Declaration *decl, QList *highlighting) 48 | { 49 | Q_UNUSED(highlighting); // TODO 50 | QString ret("("); 51 | QVector params; 52 | 53 | if (DUContext *ctx = DUChainUtils::argumentContext(decl)) 54 | params = ctx->localDeclarations(); 55 | 56 | // TODO: this is just too simplistic 57 | 58 | bool first = true; 59 | foreach (Declaration *d, params) { 60 | if (first) { 61 | first = false; 62 | } else { 63 | ret += ", "; 64 | } 65 | ret += d->identifier().toString(); 66 | } 67 | ret += ")"; 68 | return ret; 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /completion/helpers.h: -------------------------------------------------------------------------------- 1 | /* This file is part of KDevelop 2 | * 3 | * Copyright (C) 2012-2015 Miquel Sabaté Solà 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | 20 | #ifndef RUBYCOMPLETIONHELPERS_H 21 | #define RUBYCOMPLETIONHELPERS_H 22 | 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | 29 | namespace KTextEditor { 30 | class Document; 31 | } 32 | 33 | namespace KDevelop { 34 | class Declaration; 35 | } 36 | 37 | namespace ruby { 38 | 39 | class NormalItem; 40 | 41 | /** 42 | * Get a string representing an indentation. 43 | * 44 | * @param document The current document. 45 | * @returns a QString containing the indentation to be used. 46 | */ 47 | const QString KDEVRUBYCOMPLETION_EXPORT indentString(KTextEditor::Document *document); 48 | 49 | /// Get the indentation of a given @p line. 50 | QString KDEVRUBYCOMPLETION_EXPORT getIndendation(const QString &line); 51 | 52 | /** 53 | * Get the representation of the arguments list of a method declaration. 54 | * @param decl The declaration of the method. 55 | * @param highlighting A list of the highlighted items of the text. You 56 | * usually want this list empty before calling this method. 57 | * @note the DUChain must be locked. 58 | * @returns a QString representing the argument list of the given method. 59 | */ 60 | QString KDEVRUBYCOMPLETION_EXPORT getArgumentList(KDevelop::Declaration *decl, QList *highlighting); 61 | 62 | } 63 | 64 | 65 | #endif // RUBYCOMPLETIONHELPERS_H 66 | -------------------------------------------------------------------------------- /completion/items/keyworditem.h: -------------------------------------------------------------------------------- 1 | /* This file is part of KDevelop 2 | * 3 | * Copyright (C) 2012-2015 Miquel Sabaté Solà 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | #ifndef RUBY_KEYWORD_ITEM_H 20 | #define RUBY_KEYWORD_ITEM_H 21 | 22 | #include 23 | #include 24 | 25 | namespace ruby { 26 | 27 | /** 28 | * @class KeywordItem 29 | * 30 | * A completion item for a ruby keyword. Depending on how it's initialized 31 | * this class, it will add some extra code. 32 | */ 33 | class KDEVRUBYCOMPLETION_EXPORT KeywordItem 34 | : public KDevelop::NormalDeclarationCompletionItem 35 | { 36 | public: 37 | /** 38 | * Constructor. 39 | * @param ctx The code completion context. 40 | * @param keyword The keyword that this item is representing. 41 | * @param customReplacement If the \p line is set to false, it can be used 42 | * for additional power on how the keyword gets replaced. To place the 43 | * cursor, use %CURSOR%. You can select a word with 44 | * %SELECT%word%ENDSELECT%. Finally, use %END% to place an end keyword 45 | * indented to the indentation level of the line we execute the item on. 46 | * If the \p line is set to true, this parameter only acts as a descriptor. 47 | * @param line Set to true if you want that the whole line gets replaced. 48 | * False by default. 49 | */ 50 | explicit KeywordItem(KDevelop::CodeCompletionContext::Ptr ctx, 51 | const QString &keyword, 52 | const QString &customReplacement = QString(""), 53 | bool line = false); 54 | 55 | /// Re-implemented from KDevelop::NormalDeclarationCompletionItem. 56 | void execute(KTextEditor::View *view, 57 | const KTextEditor::Range &word) override; 58 | 59 | /// Re-implemented from KDevelop::NormalDeclarationCompletionItem. 60 | QVariant data(const QModelIndex &index, 61 | int role, 62 | const KDevelop::CodeCompletionModel *model) const override; 63 | 64 | private: 65 | QString m_keyword; 66 | QString m_replacement; 67 | bool m_wholeLine; 68 | }; 69 | 70 | } 71 | 72 | #endif // RUBY_KEYWORD_ITEM_H 73 | -------------------------------------------------------------------------------- /completion/items/normalitem.cpp: -------------------------------------------------------------------------------- 1 | /* This file is part of KDevelop 2 | * 3 | * Copyright (C) 2012-2015 Miquel Sabaté Solà 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | 20 | // KDevelop 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | // Ruby 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | 34 | using namespace KDevelop; 35 | 36 | namespace ruby 37 | { 38 | 39 | NormalItem::NormalItem(DeclarationPointer decl, 40 | CodeCompletionContext::Ptr context, 41 | int inheritanceDepth) 42 | : NormalDeclarationCompletionItem(decl, context, inheritanceDepth) 43 | { 44 | /* There's nothing to do here */ 45 | } 46 | 47 | QVariant NormalItem::data(const QModelIndex &index, int role, 48 | const CodeCompletionModel *model) const 49 | { 50 | if (!m_declaration) { 51 | return QVariant(); 52 | } 53 | 54 | DUChainReadLocker rlock; 55 | 56 | Declaration* dec = const_cast(m_declaration.data()); 57 | switch (role) { 58 | case CodeCompletionModel::ItemSelected: 59 | return QVariant(NavigationWidget::shortDescription(dec)); 60 | case Qt::DisplayRole: 61 | switch (index.column()) { 62 | case CodeCompletionModel::Postfix: 63 | return QVariant(); 64 | case CodeCompletionModel::Prefix: { 65 | ModuleDeclaration *moDec = dynamic_cast(dec); 66 | if (moDec) { 67 | if (moDec->isModule()) { 68 | return i18n("module"); 69 | } 70 | return i18n("class"); 71 | } 72 | return QVariant(); 73 | } 74 | case CodeCompletionModel::Arguments: 75 | if (FunctionType::Ptr fType = dec->type()) { 76 | return getArgumentList(m_declaration.data(), nullptr); 77 | } 78 | break; 79 | } 80 | break; 81 | } 82 | rlock.unlock(); 83 | 84 | return NormalDeclarationCompletionItem::data(index, role, model); 85 | } 86 | 87 | QWidget * NormalItem::createExpandingWidget(const CodeCompletionModel *model) const 88 | { 89 | return new NavigationWidget(m_declaration, model->currentTopContext()); 90 | } 91 | 92 | bool NormalItem::createsExpandingWidget() const 93 | { 94 | return true; 95 | } 96 | 97 | } 98 | -------------------------------------------------------------------------------- /completion/items/normalitem.h: -------------------------------------------------------------------------------- 1 | /* This file is part of KDevelop 2 | * 3 | * Copyright (C) 2012-2015 Miquel Sabaté Solà 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | 20 | #ifndef RUBY_NORMALITEM_H 21 | #define RUBY_NORMALITEM_H 22 | 23 | 24 | #include 25 | #include 26 | 27 | 28 | namespace ruby { 29 | 30 | /** 31 | * @class NormalItem 32 | * This is the NormalDeclarationCompletionItem to be used for this plugin. 33 | */ 34 | class KDEVRUBYCOMPLETION_EXPORT NormalItem : public KDevelop::NormalDeclarationCompletionItem 35 | { 36 | public: 37 | /// Constructor. 38 | explicit NormalItem(KDevelop::DeclarationPointer decl = KDevelop::DeclarationPointer(), 39 | KDevelop::CodeCompletionContext::Ptr context = KDevelop::CodeCompletionContext::Ptr(), 40 | int inheritanceDepth = 0); 41 | 42 | /// Re-implemented from KDevelop::NormalDeclarationCompletionItem. 43 | QVariant data(const QModelIndex &index, 44 | int role, 45 | const KDevelop::CodeCompletionModel *model) const override; 46 | 47 | protected: 48 | /// Re-implemented from KDevelop::NormalDeclarationCompletionItem. 49 | QWidget * createExpandingWidget(const KDevelop::CodeCompletionModel *model) const override; 50 | 51 | /// Re-implemented from KDevelop::NormalDeclarationCompletionItem. 52 | bool createsExpandingWidget() const override; 53 | }; 54 | 55 | } 56 | 57 | 58 | #endif // RUBYNORMALITEM_H 59 | -------------------------------------------------------------------------------- /completion/items/requirefileitem.cpp: -------------------------------------------------------------------------------- 1 | /* This file is part of KDevelop 2 | * 3 | * Copyright (C) 2012-2015 Miquel Sabaté Solà 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | // KDE 20 | #include 21 | #include 22 | 23 | // Ruby 24 | #include 25 | 26 | using namespace KTextEditor; 27 | 28 | namespace ruby 29 | { 30 | 31 | RequireFileItem::RequireFileItem(const KDevelop::IncludeItem &include, const char closing) 32 | : BaseIncludeFileItem(include), m_closing(closing) 33 | { 34 | } 35 | 36 | void RequireFileItem::execute(View *view, const Range &word) 37 | { 38 | KTextEditor::Document *document = view->document(); 39 | 40 | QString text = includeItem.name; 41 | if (includeItem.isDirectory) { 42 | text += "/"; 43 | } else if (text.endsWith(".rb")) { 44 | text.chop(3); // .rb 45 | } 46 | 47 | // Close the item if needed. 48 | const QString textAfter = document->text(Range(word.end(), document->documentEnd())); 49 | bool found = false; 50 | for (int i = 0; textAfter[i] != '\n' && i < textAfter.length(); i++) { 51 | if (textAfter[i] == m_closing) { 52 | found = true; 53 | break; 54 | } 55 | } 56 | if (!found) { 57 | text += m_closing; 58 | } 59 | 60 | document->replaceText(word, text); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /completion/items/requirefileitem.h: -------------------------------------------------------------------------------- 1 | /* This file is part of KDevelop 2 | * 3 | * Copyright (C) 2012-2015 Miquel Sabaté Solà 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | 20 | #ifndef RUBY_REQUIREFILEITEM_H 21 | #define RUBY_REQUIREFILEITEM_H 22 | 23 | #include 24 | #include 25 | 26 | namespace ruby { 27 | 28 | using BaseIncludeFileItem = 29 | KDevelop::AbstractIncludeFileCompletionItem; 30 | 31 | /** 32 | * @class RequireFileItem 33 | * This class is the completion item for completing required files. 34 | */ 35 | class RequireFileItem : public BaseIncludeFileItem 36 | { 37 | public: 38 | /// Constructor 39 | RequireFileItem(const KDevelop::IncludeItem &include, const char closing); 40 | 41 | /// Re-implemented from KDevelop::AbstractIncludeFileCompletionItem 42 | void execute(KTextEditor::View *View, 43 | const KTextEditor::Range &word) override; 44 | 45 | private: 46 | /// The character that may enclose this item. 47 | char m_closing; 48 | }; 49 | 50 | } 51 | 52 | #endif /* RUBY_REQUIREFILEITEM_H */ 53 | -------------------------------------------------------------------------------- /completion/model.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of KDevelop 3 | * Copyright (C) 2012-2015 Miquel Sabaté Solà 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | #include 20 | #include 21 | 22 | namespace ruby 23 | { 24 | 25 | CodeCompletionModel::CodeCompletionModel(QObject *parent) 26 | : KDevelop::CodeCompletionModel(parent) 27 | { 28 | } 29 | 30 | CodeCompletionModel::~CodeCompletionModel() 31 | { 32 | } 33 | 34 | KDevelop::CodeCompletionWorker * CodeCompletionModel::createCompletionWorker() 35 | { 36 | return new ruby::CodeCompletionWorker(this); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /completion/model.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of KDevelop 3 | * Copyright (C) 2012-2015 Miquel Sabaté Solà 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | 20 | #ifndef RUBY_COMPLETION_MODEL_H 21 | #define RUBY_COMPLETION_MODEL_H 22 | 23 | 24 | #include 25 | #include 26 | 27 | 28 | namespace ruby { 29 | 30 | /** 31 | * @class CodeCompletionModel 32 | * This is the code completion model for the Ruby language support. 33 | */ 34 | class KDEVRUBYCOMPLETION_EXPORT CodeCompletionModel : public KDevelop::CodeCompletionModel 35 | { 36 | Q_OBJECT 37 | 38 | public: 39 | /// Constructor. 40 | explicit CodeCompletionModel(QObject *parent); 41 | 42 | /// Destructor. 43 | ~CodeCompletionModel() override; 44 | 45 | protected: 46 | /// Re-implemented from KDevelop::CodeCompletionModel. 47 | KDevelop::CodeCompletionWorker *createCompletionWorker() override; 48 | }; 49 | 50 | } 51 | 52 | 53 | #endif /* RUBY_COMPLETION_MODEL_H */ 54 | -------------------------------------------------------------------------------- /completion/tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}) 3 | 4 | ecm_add_test( 5 | completion.cpp 6 | ../../duchain/tests/duchaintestbase.cpp 7 | 8 | TEST_NAME completion 9 | 10 | LINK_LIBRARIES 11 | 12 | Qt5::Test 13 | 14 | KDev::Interfaces 15 | KDev::Tests 16 | 17 | kdevrubyduchain 18 | kdevrubyparser 19 | kdevrubycompletion 20 | ) 21 | 22 | -------------------------------------------------------------------------------- /completion/tests/completion.h: -------------------------------------------------------------------------------- 1 | /* This file is part of KDevelop 2 | * 3 | * Copyright (C) 2012-2015 Miquel Sabaté Solà 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | 20 | #ifndef RUBYCOMPLETION_H 21 | #define RUBYCOMPLETION_H 22 | 23 | 24 | #include 25 | 26 | 27 | namespace ruby { 28 | 29 | /** 30 | * @class TestCompletion 31 | * The Code completion test suite. 32 | */ 33 | class TestCompletion : public DUChainTestBase 34 | { 35 | Q_OBJECT 36 | 37 | public: 38 | /// Constructor. 39 | TestCompletion(); 40 | 41 | protected: 42 | /// Re-implemented from DUChainTestBase. 43 | KDevelop::TopDUContext * parse(const QByteArray &code, const QString &id) override; 44 | 45 | private: 46 | /// Verify that all the items in @p shoulda are contained in @p list. 47 | void shouldContain(const QStringList &list, const QStringList &shoulda, bool sameSize = false); 48 | 49 | private slots: 50 | void standardAccess(); 51 | void baseClass(); 52 | void moduleMixins(); 53 | void memberAccess(); 54 | void checkSubclassing(); 55 | void classMemberAccess(); 56 | void fileChoose(); 57 | }; 58 | 59 | } 60 | 61 | 62 | #endif // RUBYCOMPLETION_H 63 | -------------------------------------------------------------------------------- /completion/worker.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of KDevelop 3 | * Copyright (C) 2012-2015 Miquel Sabaté Solà 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | #include 25 | 26 | 27 | namespace ruby 28 | { 29 | 30 | CodeCompletionWorker::CodeCompletionWorker(CodeCompletionModel *parent) 31 | : KDevelop::CodeCompletionWorker(parent) 32 | { 33 | /* There's nothing to do here */ 34 | } 35 | 36 | KDevelop::CodeCompletionContext* CodeCompletionWorker::createCompletionContext(const KDevelop::DUContextPointer& context, const QString &contextText, 37 | const QString &followingText, const KDevelop::CursorInRevision &position) const 38 | { 39 | return new ruby::CodeCompletionContext(context, contextText, followingText, position); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /completion/worker.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of KDevelop 3 | * Copyright (C) 2012-2015 Miquel Sabaté Solà 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | 20 | #ifndef RUBY_COMPLETION_WORKER_H 21 | #define RUBY_COMPLETION_WORKER_H 22 | 23 | 24 | #include 25 | #include 26 | 27 | 28 | namespace ruby { 29 | 30 | class CodeCompletionModel; 31 | class CodeCompletionContext; 32 | 33 | /** 34 | * @class CodeCompletionWorker 35 | * This is the worker for the code completion. 36 | */ 37 | class KDEVRUBYCOMPLETION_EXPORT CodeCompletionWorker : public KDevelop::CodeCompletionWorker 38 | { 39 | Q_OBJECT 40 | 41 | public: 42 | /// Constructor 43 | explicit CodeCompletionWorker(CodeCompletionModel *parent); 44 | 45 | protected: 46 | /// Re-implemented from KDevelop::CodeCompletionWorker 47 | KDevelop::CodeCompletionContext *createCompletionContext(const KDevelop::DUContextPointer& context, 48 | const QString &contextText, 49 | const QString &followingText, 50 | const KDevelop::CursorInRevision &position) const override; 51 | }; 52 | 53 | } 54 | 55 | 56 | #endif /* RUBY_COMPLETION_WORKER_H */ 57 | -------------------------------------------------------------------------------- /duchain/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | set(rubyduchain_SRCS 3 | expressionvisitor.cpp 4 | editorintegrator.cpp 5 | rubyducontext.cpp 6 | helpers.cpp 7 | loader.cpp 8 | 9 | builders/declarationbuilder.cpp 10 | builders/usebuilder.cpp 11 | builders/contextbuilder.cpp 12 | builders/typebuilder.cpp 13 | types/classtype.cpp 14 | 15 | navigation/declarationnavigationcontext.cpp 16 | navigation/navigationwidget.cpp 17 | navigation/includenavigationcontext.cpp 18 | declarations/methoddeclaration.cpp 19 | declarations/variabledeclaration.cpp 20 | declarations/moduledeclaration.cpp 21 | ) 22 | ecm_qt_declare_logging_category(rubyduchain_SRCS 23 | HEADER duchaindebug.h 24 | IDENTIFIER DUCHAIN 25 | CATEGORY_NAME "kdevelop.languages.ruby.duchain" 26 | ) 27 | 28 | add_library(kdevrubyduchain SHARED ${rubyduchain_SRCS}) 29 | 30 | generate_export_header(kdevrubyduchain EXPORT_MACRO_NAME KDEVRUBYDUCHAIN_EXPORT 31 | EXPORT_FILE_NAME duchainexport.h) 32 | 33 | target_link_libraries(kdevrubyduchain LINK_PRIVATE 34 | KDev::Language 35 | KDev::Util 36 | 37 | kdevrubyparser 38 | ) 39 | 40 | install(TARGETS kdevrubyduchain DESTINATION ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) 41 | 42 | if(BUILD_TESTING) 43 | add_subdirectory(tests) 44 | endif() 45 | -------------------------------------------------------------------------------- /duchain/builders/typebuilder.cpp: -------------------------------------------------------------------------------- 1 | /* This file is part of KDevelop 2 | * 3 | * Copyright 2010 Alexander Dymo 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU Library General Public License as 7 | * published by the Free Software Foundation; either version 2 of the 8 | * License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public 16 | * License along with this program; if not, write to the 17 | * Free Software Foundation, Inc., 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | 21 | #include 22 | 23 | using namespace ruby; 24 | 25 | TypeBuilder::TypeBuilder() : TypeBuilderBase() 26 | { 27 | } 28 | 29 | -------------------------------------------------------------------------------- /duchain/builders/typebuilder.h: -------------------------------------------------------------------------------- 1 | /* This file is part of KDevelop 2 | * 3 | * Copyright 2010 Alexander Dymo 4 | * 5 | * This program is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU Library General Public License as 7 | * published by the Free Software Foundation; either version 2 of the 8 | * License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public 16 | * License along with this program; if not, write to the 17 | * Free Software Foundation, Inc., 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | 21 | #ifndef RUBY_TYPE_BUILDER_H 22 | #define RUBY_TYPE_BUILDER_H 23 | 24 | #include 25 | #include 26 | 27 | namespace ruby { 28 | 29 | using TypeBuilderBase = 30 | KDevelop::AbstractTypeBuilder; 31 | 32 | /** 33 | * @class TypeBuilder 34 | * 35 | * It's just declared to feed the chain of DUChain classes but it's not 36 | * really used for anything. 37 | */ 38 | struct KDEVRUBYDUCHAIN_EXPORT TypeBuilder : public TypeBuilderBase 39 | { 40 | TypeBuilder(); 41 | }; 42 | 43 | } 44 | 45 | #endif // RUBY_TYPE_BUILDER_H 46 | 47 | -------------------------------------------------------------------------------- /duchain/builders/usebuilder.h: -------------------------------------------------------------------------------- 1 | /* This file is part of KDevelop 2 | * 3 | * Copyright (C) 2011-2015 Miquel Sabaté Solà 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | #ifndef RUBY_USE_BUILDER_H 20 | #define RUBY_USE_BUILDER_H 21 | 22 | #include 23 | 24 | #include 25 | #include 26 | 27 | namespace ruby { 28 | 29 | using UseBuilderBase = 30 | KDevelop::AbstractUseBuilder; 31 | 32 | /** 33 | * @class UseBuilder 34 | * 35 | * A class which iterates the AST to extract uses of definitions. 36 | */ 37 | class KDEVRUBYDUCHAIN_EXPORT UseBuilder : public UseBuilderBase 38 | { 39 | public: 40 | explicit UseBuilder(EditorIntegrator *editor); 41 | 42 | protected: 43 | /// Methods re-implemented from AstVisitor. 44 | 45 | bool declaredInContext(const QByteArray &name) const override; 46 | 47 | void visitName(Ast *node) override; 48 | void visitClassName(Ast *node) override; 49 | void visitMixin(Ast *node, bool include) override; 50 | void visitMethodCall(Ast *node) override; 51 | void visitRequire(Ast *node, bool relative = false) override; 52 | 53 | private: 54 | /// @internal Visit the method call members from the given @p node. 55 | void visitMethodCallMembers(Ast *node); 56 | 57 | private: 58 | /// Used at the method call visitor to keep track of the last context. 59 | KDevelop::DUContext *m_lastCtx; 60 | 61 | /** 62 | * The method call visitor uses this to track the depth of 63 | * the recursion level. 64 | */ 65 | int m_depth; 66 | 67 | /** 68 | * Used in the method call to tell if the previous recursion level 69 | * consisted of a class/module. 70 | */ 71 | bool m_classMethod; 72 | }; 73 | 74 | } 75 | 76 | #endif // RUBY_USE_BUILDER_H 77 | -------------------------------------------------------------------------------- /duchain/declarations/variabledeclaration.cpp: -------------------------------------------------------------------------------- 1 | /* This file is part of KDevelop 2 | * 3 | * Copyright (C) 2011-2015 Miquel Sabaté Solà 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | #include 20 | #include 21 | 22 | namespace ruby { 23 | 24 | REGISTER_DUCHAIN_ITEM(VariableDeclaration); 25 | 26 | VariableDeclaration::VariableDeclaration(VariableDeclarationData &data) 27 | : KDevelop::Declaration(data) 28 | { 29 | } 30 | 31 | VariableDeclaration::VariableDeclaration(VariableDeclarationData &data, 32 | const KDevelop::RangeInRevision &range) 33 | : KDevelop::Declaration(data, range) 34 | { 35 | } 36 | 37 | VariableDeclaration::VariableDeclaration(const VariableDeclaration &rhs) 38 | : KDevelop::Declaration(*new VariableDeclarationData(*rhs.d_func())) 39 | { 40 | } 41 | 42 | VariableDeclaration::VariableDeclaration(const KDevelop::RangeInRevision &range, 43 | KDevelop::DUContext *context) 44 | : KDevelop::Declaration(*new VariableDeclarationData, range) 45 | { 46 | d_func_dynamic()->setClassId(this); 47 | if (context) { 48 | setContext(context); 49 | } 50 | } 51 | 52 | void VariableDeclaration::setVariableKind(const Node *node) 53 | { 54 | if (node) { 55 | d_func_dynamic()->kind = node->flags; 56 | } 57 | } 58 | 59 | void VariableDeclaration::setVariableKind(int kind) 60 | { 61 | d_func_dynamic()->kind = kind; 62 | } 63 | 64 | int VariableDeclaration::variableKind() const 65 | { 66 | return d_func()->kind; 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /duchain/editorintegrator.cpp: -------------------------------------------------------------------------------- 1 | /* This file is part of KDevelop 2 | * 3 | * Copyright 2006 Hamish Rodda 4 | * Copyright 2010 Alexander Dymo 5 | * Copyright (C) 2011-2015 Miquel Sabaté Solà 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU Library General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public 18 | * License along with this program; if not, write to the 19 | * Free Software Foundation, Inc., 20 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 21 | */ 22 | 23 | #include 24 | 25 | #include 26 | 27 | using namespace KDevelop; 28 | namespace ruby { 29 | 30 | EditorIntegrator::EditorIntegrator() 31 | { 32 | } 33 | 34 | const CursorInRevision EditorIntegrator::findPosition(const Node *node, 35 | Edge edge) const 36 | { 37 | Q_ASSERT(node); 38 | 39 | if (edge == Edge::BackEdge) { 40 | return CursorInRevision(node->pos.end_line - 1, node->pos.end_col); 41 | } 42 | return CursorInRevision(node->pos.start_line - 1, node->pos.start_col); 43 | } 44 | 45 | const RangeInRevision EditorIntegrator::findRange(const Node *from, 46 | const Node *to) const 47 | { 48 | CursorInRevision c_from = findPosition(from, Edge::FrontEdge); 49 | CursorInRevision c_to = findPosition(to, Edge::BackEdge); 50 | 51 | return RangeInRevision(c_from, c_to); 52 | } 53 | 54 | const RangeInRevision EditorIntegrator::findRange(const Node *node) const 55 | { 56 | CursorInRevision c_from = findPosition(node, Edge::FrontEdge); 57 | CursorInRevision c_to = findPosition(node, Edge::BackEdge); 58 | 59 | return RangeInRevision(c_from, c_to); 60 | } 61 | 62 | const IndexedString & EditorIntegrator::url() const 63 | { 64 | return m_session->currentDocument; 65 | } 66 | 67 | void EditorIntegrator::setParseSession(Parser *session) 68 | { 69 | m_session = session; 70 | } 71 | 72 | Parser * EditorIntegrator::parseSession() const 73 | { 74 | return m_session; 75 | } 76 | 77 | const QString EditorIntegrator::tokenToString(const Node *node) const 78 | { 79 | return m_session->symbol(node); 80 | } 81 | 82 | } 83 | -------------------------------------------------------------------------------- /duchain/editorintegrator.h: -------------------------------------------------------------------------------- 1 | /* This file is part of KDevelop 2 | * 3 | * Copyright 2006 Hamish Rodda 4 | * Copyright 2010 Alexander Dymo 5 | * Copyright (C) 2011-2015 Miquel Sabaté Solà 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU Library General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public 18 | * License along with this program; if not, write to the 19 | * Free Software Foundation, Inc., 20 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 21 | */ 22 | 23 | #ifndef RUBY_EDITOR_INTEGRATOR_H 24 | #define RUBY_EDITOR_INTEGRATOR_H 25 | 26 | #include 27 | #include 28 | 29 | #include 30 | 31 | namespace ruby { 32 | 33 | class Parser; 34 | struct Node; 35 | 36 | /** 37 | * The different positions around a Node. 38 | */ 39 | enum class Edge { FrontEdge, BackEdge }; 40 | 41 | /** 42 | * @class EditorIntegrator 43 | * 44 | * The EditorIntegrator for the Ruby plugin. 45 | */ 46 | class KDEVRUBYDUCHAIN_EXPORT EditorIntegrator 47 | { 48 | public: 49 | EditorIntegrator(); 50 | 51 | /** 52 | * Find the position of the given node at the given edge. 53 | * 54 | * @param node the node to localize. 55 | * @param edge the edge this method has to look at. 56 | */ 57 | const KDevelop::CursorInRevision findPosition(const Node *node, 58 | Edge edge = Edge::BackEdge) const; 59 | 60 | /** 61 | * Find the range between the given nodes. 62 | * 63 | * @param from the former node. 64 | * @param to the latter node. 65 | */ 66 | const KDevelop::RangeInRevision findRange(const Node *from, 67 | const Node *to) const; 68 | 69 | /** 70 | * Get the range of the given node. 71 | * 72 | * @param node the node to get its range. 73 | */ 74 | const KDevelop::RangeInRevision findRange(const Node *node) const; 75 | 76 | /** 77 | * Get the url of the document we are editing. 78 | * 79 | * @return the url of the document we are editing. 80 | */ 81 | const KDevelop::IndexedString & url() const; 82 | 83 | /** 84 | * Set the parse session (parser) for this EditorIntegrator. 85 | * 86 | * @param session the given RubyParser. 87 | */ 88 | void setParseSession(Parser *session); 89 | 90 | /** 91 | * Implemented to make the AbstractUseBuilder happy. 92 | * 93 | * @return Get the parse session for this EditorIntegrator. 94 | */ 95 | Parser * parseSession() const; 96 | 97 | /** 98 | * @return a QString that represents the value of the token 99 | * (not the node's name). 100 | */ 101 | const QString tokenToString(const Node *node) const; 102 | 103 | private: 104 | Parser *m_session; 105 | }; 106 | 107 | } 108 | 109 | #endif // RUBY_EDITOR_INTEGRATOR_H 110 | -------------------------------------------------------------------------------- /duchain/navigation/includenavigationcontext.cpp: -------------------------------------------------------------------------------- 1 | /* This file is part of KDevelop 2 | * 3 | * Copyright (C) 2011-2015 Miquel Sabaté Solà 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | 20 | // Ruby 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | 27 | namespace ruby 28 | { 29 | 30 | IncludeNavigationContext::IncludeNavigationContext(const KDevelop::IncludeItem &item, 31 | KDevelop::TopDUContextPointer topContext) 32 | : AbstractIncludeNavigationContext(item, topContext, KDevelop::RubyParsingEnvironment) 33 | { 34 | /* There's nothing to do here! */ 35 | } 36 | 37 | void IncludeNavigationContext::getFileInfo(KDevelop::TopDUContext* duchain) 38 | { 39 | modifyHtml() += QString("%1: %2") 40 | .arg(labelHighlight(i18nc("Count of files this header was included into", "Required by"))) 41 | .arg(duchain->importers().count()); 42 | modifyHtml() += "
"; 43 | } 44 | 45 | bool IncludeNavigationContext::filterDeclaration(KDevelop::Declaration *decl) 46 | { 47 | VariableDeclaration *vd = dynamic_cast(decl); 48 | return !vd; 49 | } 50 | 51 | QString IncludeNavigationContext::declarationKind(const KDevelop::DeclarationPointer& decl) 52 | { 53 | const MethodDeclaration *md = dynamic_cast(decl.data()); 54 | if (md) 55 | return (md->isClassMethod()) ? "Class method" : "Instance method"; 56 | 57 | const ModuleDeclaration *mDecl = dynamic_cast(decl.data()); 58 | if (mDecl) 59 | return (mDecl->isModule()) ? "Module": "Class"; 60 | return KDevelop::AbstractNavigationContext::declarationKind(decl); 61 | } 62 | 63 | } 64 | 65 | -------------------------------------------------------------------------------- /duchain/navigation/includenavigationcontext.h: -------------------------------------------------------------------------------- 1 | /* This file is part of KDevelop 2 | * 3 | * Copyright (C) 2011-2015 Miquel Sabaté Solà 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | 20 | #ifndef INCLUDENAVIGATIONCONTEXT_H 21 | #define INCLUDENAVIGATIONCONTEXT_H 22 | 23 | 24 | #include 25 | #include 26 | 27 | 28 | namespace ruby { 29 | 30 | /** 31 | * @class IncludeNavigationContext 32 | * 33 | * The include navigation context for Ruby scripts. 34 | */ 35 | class KDEVRUBYDUCHAIN_EXPORT IncludeNavigationContext 36 | : public KDevelop::AbstractIncludeNavigationContext 37 | { 38 | public: 39 | /** 40 | * Constructor. 41 | * 42 | * @param item The include item in which we want to retrieve the info. 43 | * @param topContext The top context associated with the given item. 44 | */ 45 | explicit IncludeNavigationContext(const KDevelop::IncludeItem &item, 46 | KDevelop::TopDUContextPointer topContext); 47 | 48 | protected: 49 | /// Re-implemented from KDevelop::AbstractIncludeNavigationContext 50 | void getFileInfo(KDevelop::TopDUContext *duchain) override; 51 | 52 | /** 53 | * Re-implemented from KDevelop::AbstractIncludeNavigationContext to 54 | * prevent variable declarations to appear on the widget. 55 | */ 56 | bool filterDeclaration(KDevelop::Declaration *decl) override; 57 | 58 | /** 59 | * Re-implemented from KDevelop::AbstractNavigationContext so we can also 60 | * show to the user if this declaration has some special meaning for 61 | * the Ruby interpreter. 62 | */ 63 | QString declarationKind(const KDevelop::DeclarationPointer& decl) override; 64 | }; 65 | 66 | } 67 | 68 | 69 | #endif /* INCLUDENAVIGATIONCONTEXT_H */ 70 | -------------------------------------------------------------------------------- /duchain/navigation/navigationwidget.cpp: -------------------------------------------------------------------------------- 1 | /* This file is part of KDevelop 2 | * 3 | * Copyright (C) 2011-2015 Miquel Sabaté Solà 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | 25 | namespace ruby 26 | { 27 | using namespace KDevelop; 28 | 29 | NavigationWidget::NavigationWidget( KDevelop::DeclarationPointer decl, 30 | KDevelop::TopDUContextPointer topContext, 31 | KDevelop::AbstractNavigationWidget::DisplayHints hints) 32 | { 33 | setDisplayHints(hints); 34 | initBrowser(200); 35 | 36 | auto context = NavigationContextPointer(new DeclarationNavigationContext(decl, topContext)); 37 | setContext(context); 38 | } 39 | 40 | NavigationWidget::NavigationWidget(const KDevelop::IncludeItem &item, 41 | KDevelop::TopDUContextPointer topContext, 42 | KDevelop::AbstractNavigationWidget::DisplayHints hints) 43 | { 44 | setDisplayHints(hints); 45 | initBrowser(200); 46 | 47 | auto context = NavigationContextPointer(new IncludeNavigationContext(item, topContext)); 48 | setContext(context); 49 | } 50 | 51 | QString NavigationWidget::shortDescription(KDevelop::Declaration *decl) 52 | { 53 | NavigationContextPointer ctx(new DeclarationNavigationContext(DeclarationPointer(decl), TopDUContextPointer())); 54 | return ctx->html(true); 55 | } 56 | 57 | QString NavigationWidget::shortDescription(const KDevelop::IncludeItem &item) 58 | { 59 | NavigationContextPointer ctx(new IncludeNavigationContext(item, TopDUContextPointer())); 60 | return ctx->html(true); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /duchain/navigation/navigationwidget.h: -------------------------------------------------------------------------------- 1 | /* This file is part of KDevelop 2 | * 3 | * Copyright (C) 2011-2015 Miquel Sabaté Solà 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | 20 | #ifndef NAVIGATIONWIDGET_H 21 | #define NAVIGATIONWIDGET_H 22 | 23 | 24 | #include 25 | #include 26 | 27 | 28 | namespace KDevelop { class IncludeItem; } 29 | 30 | namespace ruby { 31 | 32 | /** 33 | * @class NavigationWidget 34 | * 35 | * The NavigationWidget for the Ruby plugin. 36 | */ 37 | class KDEVRUBYDUCHAIN_EXPORT NavigationWidget : public KDevelop::AbstractNavigationWidget 38 | { 39 | Q_OBJECT 40 | 41 | public: 42 | /** 43 | * Constructor. 44 | * 45 | * @param decl A pointer to the involved declaration. 46 | * @param topContext The involved Top Context. 47 | */ 48 | explicit NavigationWidget(KDevelop::DeclarationPointer decl, 49 | KDevelop::TopDUContextPointer topContext, 50 | KDevelop::AbstractNavigationWidget::DisplayHints hints = KDevelop::AbstractNavigationWidget::NoHints); 51 | 52 | /** 53 | * Constructor. 54 | * 55 | * @param item The involved Include Item. 56 | * @param topContext The involved Top Context. 57 | */ 58 | explicit NavigationWidget(const KDevelop::IncludeItem &item, 59 | KDevelop::TopDUContextPointer topContext, 60 | KDevelop::AbstractNavigationWidget::DisplayHints hints = KDevelop::AbstractNavigationWidget::NoHints); 61 | 62 | /** 63 | * Creates a compact html description given a Declaration. 64 | * 65 | * @param decl The given Declaration. 66 | */ 67 | static QString shortDescription(KDevelop::Declaration *decl); 68 | 69 | /** 70 | * Creates a compact html description given an Include item. 71 | * 72 | * @param decl The given Include item. 73 | */ 74 | static QString shortDescription(const KDevelop::IncludeItem &item); 75 | }; 76 | 77 | } 78 | 79 | 80 | #endif // NAVIGATIONWIDGET_H 81 | -------------------------------------------------------------------------------- /duchain/rubyducontext.cpp: -------------------------------------------------------------------------------- 1 | /* This file is part of KDevelop 2 | * 3 | * Copyright (C) 2011-2015 Miquel Sabaté Solà 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | #include 20 | 21 | #include 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | using namespace KDevelop; 29 | namespace ruby { 30 | 31 | REGISTER_DUCHAIN_ITEM_WITH_DATA(RubyTopDUContext, TopDUContextData); 32 | REGISTER_DUCHAIN_ITEM_WITH_DATA(RubyNormalDUContext, DUContextData); 33 | 34 | template<> 35 | KDevelop::AbstractNavigationWidget * RubyTopDUContext::createNavigationWidget(Declaration *decl, 36 | TopDUContext *topContext, 37 | AbstractNavigationWidget::DisplayHints hints) const 38 | { 39 | if (!decl) { 40 | QUrl u = QUrl::fromLocalFile(url().str()); 41 | IncludeItem i; 42 | i.pathNumber = -1; 43 | i.name = u.fileName(); 44 | i.isDirectory = false; 45 | i.basePath = KIO::upUrl(u); 46 | return new NavigationWidget(i, TopDUContextPointer(topContext), hints); 47 | } 48 | return new NavigationWidget(DeclarationPointer(decl), TopDUContextPointer(topContext), hints); 49 | } 50 | 51 | template<> 52 | KDevelop::AbstractNavigationWidget * RubyNormalDUContext::createNavigationWidget(Declaration *decl, TopDUContext *topContext, 53 | AbstractNavigationWidget::DisplayHints hints) const 54 | { 55 | if (!decl) { 56 | if (owner()) { 57 | return new NavigationWidget(DeclarationPointer(owner()), TopDUContextPointer(topContext), hints); 58 | } 59 | return nullptr; 60 | } 61 | return new NavigationWidget(DeclarationPointer(decl), TopDUContextPointer(topContext), hints); 62 | } 63 | 64 | }; 65 | 66 | -------------------------------------------------------------------------------- /duchain/rubyducontext.h: -------------------------------------------------------------------------------- 1 | /* This file is part of KDevelop 2 | * 3 | * Copyright (C) 2011-2015 Miquel Sabaté Solà 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | #ifndef RUBY_DUCONTEXT_H 20 | #define RUBY_DUCONTEXT_H 21 | 22 | #include 23 | 24 | namespace KDevelop { 25 | class Declaration; 26 | class TopDUContext; 27 | } 28 | 29 | namespace ruby { 30 | 31 | template 32 | class RubyDUContext : public BaseContext 33 | { 34 | public: 35 | template 36 | explicit RubyDUContext(Data &data) : BaseContext(data) 37 | { 38 | }; 39 | 40 | /** 41 | * Parameters will be reached to the base-class. 42 | */ 43 | template 44 | RubyDUContext(const Param1 &p1, const Param2 &p2, 45 | bool isInstantiationContext) 46 | : BaseContext(p1, p2, isInstantiationContext) 47 | { 48 | static_cast(this)->d_func_dynamic()->setClassId(this); 49 | } 50 | 51 | /** 52 | * Both parameters will be reached to the base-class. This fits TopDUContext. 53 | */ 54 | template 55 | explicit RubyDUContext(const Param1 &p1, const Param2 &p2, const Param3 &p3) 56 | : BaseContext(p1, p2, p3) 57 | { 58 | static_cast(this)->d_func_dynamic()->setClassId(this); 59 | } 60 | 61 | template 62 | explicit RubyDUContext(const Param1 &p1, const Param2 &p2) 63 | : BaseContext(p1, p2) 64 | { 65 | static_cast(this)->d_func_dynamic()->setClassId(this); 66 | } 67 | 68 | /** 69 | * Create a Navigation Widget for user-interaction within the quickopen list. 70 | * 71 | * @param decl A member-declaration of this context the navigation-widget should be created for. Zero to create a widget for this context. 72 | * @param topContext Top-context from where the navigation-widget is triggered. 73 | */ 74 | KDevelop::AbstractNavigationWidget * createNavigationWidget(KDevelop::Declaration *decl = nullptr, 75 | KDevelop::TopDUContext *topContext = nullptr, 76 | KDevelop::AbstractNavigationWidget::DisplayHints hints = KDevelop::AbstractNavigationWidget::NoHints) const override; 77 | 78 | public: 79 | enum { Identity = BaseContext::Identity + 41 }; 80 | }; 81 | 82 | using RubyTopDUContext = RubyDUContext; 83 | using RubyNormalDUContext = RubyDUContext; 84 | 85 | } 86 | 87 | #endif // RUBY_DUCONTEXT_H 88 | -------------------------------------------------------------------------------- /duchain/tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}) 3 | 4 | include(ECMAddTests) 5 | 6 | macro(ruby_unit_test testname) 7 | ecm_add_test( 8 | ${testname}.cpp duchaintestbase.cpp TEST_NAME ${testname} 9 | 10 | LINK_LIBRARIES 11 | 12 | Qt5::Test 13 | 14 | KDev::Interfaces 15 | KDev::Tests 16 | 17 | kdevrubyduchain 18 | kdevrubyparser 19 | ) 20 | endmacro() 21 | 22 | ruby_unit_test(benchmarks) 23 | ruby_unit_test(duchain) 24 | ruby_unit_test(uses) 25 | -------------------------------------------------------------------------------- /duchain/tests/benchmarks.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of KDevelop 3 | * Copyright (C) 2012-2015 Miquel Sabaté Solà 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | 20 | // Qt + KDE 21 | #include 22 | 23 | // Ruby 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | 31 | QTEST_MAIN(ruby::Benchmarks) 32 | 33 | using namespace KDevelop; 34 | namespace ruby 35 | { 36 | 37 | Benchmarks::Benchmarks() 38 | { 39 | /* There's nothing to do here */ 40 | } 41 | 42 | const QByteArray Benchmarks::getBuiltinsFile() 43 | { 44 | const QString &fileName = builtinsFile().str(); 45 | QFile file(fileName); 46 | bool opened = file.open(QIODevice::ReadOnly); 47 | Q_ASSERT(opened); 48 | const QByteArray &txt = file.readAll(); 49 | file.close(); 50 | return txt; 51 | } 52 | 53 | void Benchmarks::parser() 54 | { 55 | const QByteArray &contents = getBuiltinsFile(); 56 | 57 | QBENCHMARK { 58 | Parser parser; 59 | parser.setContents(contents); 60 | parser.parse(); 61 | } 62 | } 63 | 64 | void Benchmarks::declarationBuilder() 65 | { 66 | const QByteArray &contents = getBuiltinsFile(); 67 | Parser parser(builtinsFile(), contents); 68 | Ast * ast = parser.parse(); 69 | EditorIntegrator editor; 70 | editor.setParseSession(&parser); 71 | 72 | QBENCHMARK { 73 | DeclarationBuilder builder(&editor); 74 | ReferencedTopDUContext top = builder.build(builtinsFile(), ast); 75 | } 76 | } 77 | 78 | } 79 | 80 | -------------------------------------------------------------------------------- /duchain/tests/benchmarks.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of KDevelop 3 | * Copyright (C) 2012-2015 Miquel Sabaté Solà 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | 20 | #ifndef RUBY_BENCHMARKS_H 21 | #define RUBY_BENCHMARKS_H 22 | 23 | 24 | #include 25 | 26 | 27 | namespace ruby { 28 | /** 29 | * @class Benchmarks 30 | * Benchmark some parts of this plugin. 31 | */ 32 | class Benchmarks : public DUChainTestBase 33 | { 34 | Q_OBJECT 35 | 36 | public: 37 | /// Constructor. 38 | Benchmarks(); 39 | 40 | private: 41 | /// @returns the builtins file as a QIODevice opened in ReadOnly mode. 42 | const QByteArray getBuiltinsFile(); 43 | 44 | private slots: 45 | /// Benchmarks the parser. 46 | void parser(); 47 | 48 | /// Benchmarks the DeclarationBuilder class. 49 | void declarationBuilder(); 50 | }; 51 | 52 | } 53 | 54 | 55 | #endif /* RUBY_BENCHMARKS_H */ 56 | -------------------------------------------------------------------------------- /duchain/tests/duchaintestbase.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of KDevelop 3 | * Copyright (C) 2012-2015 Miquel Sabaté Solà 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | 20 | // Qt + KDevelop 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | // Ruby 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | 36 | using namespace KDevelop; 37 | namespace ruby 38 | { 39 | 40 | DUChainTestBase::DUChainTestBase() 41 | { 42 | /* There's nothing to do here */ 43 | } 44 | 45 | TopDUContext * DUChainTestBase::parse(const QByteArray &code, const QString &id) 46 | { 47 | QUrl url("/tmp/kdevruby_" + id + ".rb"); 48 | QFile f(url.path()); 49 | f.open(QIODevice::WriteOnly); 50 | f.write(code); 51 | f.close(); 52 | 53 | return DUChain::self()->waitForUpdate(KDevelop::IndexedString(url.path()), 54 | TopDUContext::AllDeclarationsContextsAndUses | TopDUContext::ForceUpdate); 55 | } 56 | 57 | Declaration * DUChainTestBase::getBuiltinDeclaration(const QString &name, TopDUContext *top, DUContext *ctx) 58 | { 59 | QStringList list = name.split("#"); 60 | DUContext *context = (ctx) ? ctx : top->childContexts().first(); 61 | AbstractType::Ptr type = getBuiltinsType(list.first(), context); 62 | auto sType = type.staticCast(); 63 | Declaration *d = sType->declaration(top); 64 | 65 | QualifiedIdentifier id(list.first() + "::" + list.last()); 66 | QList decls = d->internalContext()->findDeclarations(id); 67 | return (decls.isEmpty()) ? nullptr : decls.last(); 68 | } 69 | 70 | void DUChainTestBase::initTestCase() 71 | { 72 | AutoTestShell::init(); 73 | TestCore::initialize(Core::NoUi); 74 | 75 | DUChain::self()->disablePersistentStorage(); 76 | KDevelop::CodeRepresentation::setDiskChangesForbidden(true); 77 | } 78 | 79 | void DUChainTestBase::cleanupTestCase() 80 | { 81 | TestCore::shutdown(); 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /duchain/tests/duchaintestbase.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of KDevelop 3 | * Copyright (C) 2012-2015 Miquel Sabaté Solà 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | 20 | #ifndef RUBY_DUCHAINTESTBASE_H 21 | #define RUBY_DUCHAINTESTBASE_H 22 | 23 | 24 | // Qt + KDevelop 25 | #include 26 | #include 27 | #include 28 | 29 | /* 30 | * This macro is used to annotate that the only purpose of a test is to 31 | * check that the code does not crash. 32 | */ 33 | #define DOES_NOT_CRASH QVERIFY(true) 34 | 35 | 36 | namespace ruby { 37 | 38 | /** 39 | * Manage pointer to TopDUContexts and release them properly, even if a test 40 | * fails. Shamelessly copied from the PHP plugin :) 41 | */ 42 | struct DUChainReleaser { 43 | DUChainReleaser(KDevelop::TopDUContext *top) : m_top(top) {} 44 | ~DUChainReleaser() 45 | { 46 | KDevelop::DUChainWriteLocker lock; 47 | KDevelop::DUChain::self()->removeDocumentChain(m_top); 48 | } 49 | KDevelop::TopDUContext *m_top; 50 | }; 51 | 52 | 53 | /** 54 | * @class DUChainTestBase 55 | * The base class for all DUChain Test classes. 56 | */ 57 | class DUChainTestBase : public QObject 58 | { 59 | Q_OBJECT 60 | 61 | public: 62 | DUChainTestBase(); 63 | 64 | protected: 65 | /** 66 | * Parse the given @p code that belongs to the test identified by @p id. 67 | * 68 | * @returns the KDevelop::TopDUContext for the given code, or nullptr if 69 | * something failed (i.e. parse error). 70 | */ 71 | virtual KDevelop::TopDUContext * parse(const QByteArray &code, const QString &id); 72 | 73 | 74 | /** 75 | * Get a builtin method declaration. 76 | * 77 | * @param name The name of the method in a format such as "String#bytesize" 78 | * @param top The TopDUContext that we've got from parsing. 79 | * @param ctx Optional DUContext. Set this when you don't want a child 80 | * context from the @p top to be used. 81 | * @returns the Declaration of the required builtin method. 82 | */ 83 | KDevelop::Declaration * getBuiltinDeclaration(const QString &name, KDevelop::TopDUContext *top, 84 | KDevelop::DUContext *ctx = nullptr); 85 | 86 | public slots: 87 | void initTestCase(); 88 | void cleanupTestCase(); 89 | }; 90 | 91 | } 92 | 93 | 94 | #endif /* RUBY_DUCHAINTESTBASE_H */ 95 | -------------------------------------------------------------------------------- /duchain/tests/uses.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of KDevelop 3 | * Copyright (C) 2012-2015 Miquel Sabaté Solà 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | 20 | #ifndef RUBY_USES_H 21 | #define RUBY_USES_H 22 | 23 | 24 | #include 25 | 26 | 27 | namespace ruby { 28 | 29 | /** 30 | * @class TestUseBuilder 31 | * Test the UseBuilder class from the DUChain. 32 | */ 33 | class TestUseBuilder : public DUChainTestBase 34 | { 35 | Q_OBJECT 36 | 37 | public: 38 | TestUseBuilder(); 39 | 40 | protected: 41 | /// Re-implemented from DUChainTestBase. 42 | KDevelop::TopDUContext * parse(const QByteArray &code, const QString &id) override; 43 | 44 | private: 45 | /// Compare the uses of the given declaration @p dec with the given @p range. 46 | void compareUses(KDevelop::Declaration *dec, const KDevelop::RangeInRevision &range); 47 | 48 | /** 49 | * Let's compare the uses of the given declaration @p dec with the given 50 | * @p ranges that we expect these uses are enclosed to. 51 | */ 52 | void compareUses(KDevelop::Declaration *dec, QList ranges); 53 | 54 | private slots: 55 | // Basic stuff 56 | void stringInterpolation(); 57 | void alias(); 58 | void assignment(); 59 | void checkSubClassing(); 60 | void instanceVariable(); 61 | void classVariable(); 62 | void exceptions(); 63 | 64 | // Contexts 65 | void block(); 66 | void checkMethodArgumentsContext(); 67 | void checkMethodLocalDeclarations(); 68 | void instanceClassMethods(); 69 | void globals1(); 70 | void globals2(); 71 | void globals3(); 72 | void defaultGlobals(); 73 | void classModulesScopes(); 74 | 75 | // Method calls 76 | void builtinUses(); 77 | void chained(); 78 | void fromClassAndAbove(); 79 | void super(); 80 | void moduleMixins1(); 81 | void moduleMixins2(); 82 | void exprIsCalling(); 83 | void stringCalling(); 84 | 85 | // Others 86 | void nestedIdentifier(); 87 | }; 88 | 89 | } 90 | 91 | #endif /* RUBY_USES_H */ 92 | -------------------------------------------------------------------------------- /duchain/types/classtype.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of KDevelop 3 | * Copyright (C) 2012-2015 Miquel Sabaté Solà 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | #include 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | using namespace KDevelop; 26 | using namespace ruby; 27 | 28 | REGISTER_TYPE(ClassType); 29 | 30 | ClassType::ClassType() : KDevelop::StructureType(createData()) 31 | { 32 | } 33 | 34 | ClassType::ClassType(const ClassType &rhs) 35 | : KDevelop::StructureType(copyData(*rhs.d_func())) 36 | { 37 | } 38 | 39 | ClassType::ClassType(ClassTypeData &data) 40 | : KDevelop::StructureType(data) 41 | { 42 | } 43 | 44 | void ClassType::addContentType(AbstractType::Ptr typeToAdd) 45 | { 46 | if (!typeToAdd) { // TODO: not sure :/ 47 | return; 48 | } 49 | auto type = mergeTypes(contentType().abstractType(), typeToAdd); 50 | d_func_dynamic()->contentType = IndexedType(type); 51 | } 52 | 53 | const IndexedType & ClassType::contentType() const 54 | { 55 | return d_func()->contentType; 56 | } 57 | 58 | bool ClassType::isUseful() const 59 | { 60 | // TODO: this is utter crap. 61 | return KDevelop::StructureType::toString() != QStringLiteral("Object"); 62 | } 63 | 64 | AbstractType * ClassType::clone() const 65 | { 66 | return new ClassType(*this); 67 | } 68 | 69 | uint ClassType::hash() const 70 | { 71 | return KDevHash(StructureType::hash()) << 72 | (contentType().abstractType() ? contentType().abstractType()->hash() : 0); 73 | } 74 | 75 | bool ClassType::equals(const AbstractType *rhs) const 76 | { 77 | if (!KDevelop::StructureType::equals(rhs)) { 78 | return false; 79 | } 80 | 81 | if (const ClassType *rhsClass = dynamic_cast(rhs)) { 82 | return rhsClass->contentType() == contentType(); 83 | } 84 | return false; 85 | } 86 | 87 | QString ClassType::toString() const 88 | { 89 | QString prefix = StructureType::toString(); 90 | AbstractType::Ptr content = contentType().abstractType(); 91 | return content ? i18n("%1 of %2", prefix, content->toString()) : prefix; 92 | } 93 | 94 | QString ClassType::containerToString() const 95 | { 96 | return KDevelop::StructureType::toString(); 97 | } 98 | 99 | -------------------------------------------------------------------------------- /duchain/types/classtype.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of KDevelop 3 | * Copyright (C) 2012-2015 Miquel Sabaté Solà 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | #ifndef RUBY_CLASS_TYPE_H 20 | #define RUBY_CLASS_TYPE_H 21 | 22 | #include 23 | #include 24 | 25 | namespace ruby { 26 | 27 | struct KDEVRUBYDUCHAIN_EXPORT ClassTypeData : public KDevelop::StructureTypeData 28 | { 29 | ClassTypeData() : KDevelop::StructureTypeData(), contentType() 30 | { 31 | } 32 | 33 | /// Copy constructor. @param rhs data to copy. 34 | explicit ClassTypeData(const ClassTypeData &rhs) 35 | : KDevelop::StructureTypeData(rhs) 36 | , contentType(rhs.contentType) 37 | { 38 | } 39 | 40 | /// The type of the content. 41 | KDevelop::IndexedType contentType; 42 | }; 43 | 44 | /** 45 | * @class ClassType 46 | * 47 | * This is the type to be used when declaring classes in this plugin. It's 48 | * similar to the Python's VariableLengthContainer in that in Ruby, every class 49 | * can potentially become a container. The contained type can be accessed 50 | * through the methods addContentType(newType) and contentType(). 51 | */ 52 | struct KDEVRUBYDUCHAIN_EXPORT ClassType : public KDevelop::StructureType 53 | { 54 | using BaseType = KDevelop::StructureType; 55 | using Data = ClassTypeData; 56 | using Ptr = KDevelop::TypePtr; 57 | 58 | /// The different constructors. 59 | ClassType(); 60 | explicit ClassType(const ClassType &rhs); 61 | explicit ClassType(ClassTypeData &data); 62 | 63 | /// Add the given type @p typeToAdd to the contents. 64 | void addContentType(AbstractType::Ptr typeToAdd); 65 | 66 | /// @returns the content type. 67 | const KDevelop::IndexedType & contentType() const; 68 | 69 | /// Get if this class is useful. 70 | bool isUseful() const; 71 | 72 | /// Create a clone of this type. 73 | AbstractType * clone() const override; 74 | 75 | /// The hash-value for this type. 76 | uint hash() const override; 77 | 78 | /// @returns this type as a string. 79 | QString toString() const override; 80 | 81 | /// @returns true if @p rhs is the same as this type 82 | bool equals(const AbstractType *rhs) const override; 83 | 84 | /// @returns the container's type as a string. 85 | QString containerToString() const; 86 | 87 | enum { Identity = 41 /** The id of this Type. */ }; 88 | 89 | protected: 90 | TYPE_DECLARE_DATA(ClassType); 91 | }; 92 | 93 | } 94 | 95 | #endif // CLASSTYPE_H 96 | -------------------------------------------------------------------------------- /highlighting.cpp: -------------------------------------------------------------------------------- 1 | /* This file is part of KDevelop 2 | * 3 | * Copyright (C) 2011-2015 Miquel Sabaté Solà 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | #include 20 | 21 | #include 22 | #include 23 | 24 | using namespace ruby; 25 | 26 | using namespace KDevelop; 27 | 28 | //BEGIN RubyHighlightingInstance 29 | 30 | HighlightingInstance::HighlightingInstance(const CodeHighlighting *h) 31 | : CodeHighlightingInstance(h) 32 | { 33 | } 34 | 35 | CodeHighlightingType HighlightingInstance::typeForDeclaration( 36 | Declaration *decl, DUContext *ctx) const 37 | { 38 | VariableDeclaration *vd = dynamic_cast(decl); 39 | if (decl && !decl->isFunctionDeclaration() && 40 | decl->abstractType() && !vd) { 41 | return CodeHighlightingType::Enum; 42 | } 43 | return CodeHighlightingInstance::typeForDeclaration(decl, ctx); 44 | } 45 | 46 | bool HighlightingInstance::useRainbowColor(KDevelop::Declaration *dec) const 47 | { 48 | return dynamic_cast(dec); 49 | } 50 | 51 | //END RubyHighlightingInstance 52 | 53 | //BEGIN RubyHighlighting 54 | 55 | ruby::Highlighting::Highlighting(QObject *parent) 56 | : CodeHighlighting(parent) 57 | { 58 | } 59 | 60 | KDevelop::CodeHighlightingInstance* Highlighting::createInstance() const 61 | { 62 | return new HighlightingInstance(this); 63 | } 64 | 65 | //END RubyHighlighting 66 | -------------------------------------------------------------------------------- /highlighting.h: -------------------------------------------------------------------------------- 1 | /* This file is part of KDevelop 2 | * 3 | * Copyright (C) 2011-2015 Miquel Sabaté Solà 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | #ifndef RUBY_HIGHLIGHTING_H 20 | #define RUBY_HIGHLIGHTING_H 21 | 22 | #include 23 | 24 | namespace ruby { 25 | 26 | /** 27 | * @class HighlightingInstance 28 | * 29 | * The HighlightingInstance to be applied in a Ruby file. 30 | */ 31 | class HighlightingInstance : public KDevelop::CodeHighlightingInstance 32 | { 33 | public: 34 | explicit HighlightingInstance(const KDevelop::CodeHighlighting *h); 35 | 36 | /** 37 | * Return type of highlighting to be applied according 38 | * to the given declaration. 39 | * 40 | * @param decl The involved declaration. 41 | * @param ctx The context from where the declaration is used. 42 | */ 43 | KDevelop::CodeHighlightingType typeForDeclaration(KDevelop::Declaration *decl, 44 | KDevelop::DUContext *ctx) const override; 45 | 46 | /** 47 | * Re-implemented from CodeHighlightingInstance to decide whether to 48 | * apply auto-generated rainbow colors or not. 49 | * 50 | * @param dec The involved declaration. 51 | */ 52 | bool useRainbowColor(KDevelop::Declaration *dec) const override; 53 | }; 54 | 55 | /** 56 | * @class Highlighting 57 | * 58 | * This is a subclass of KDevelop::CodeHighlighting and it 59 | * represents the code highlighting for the Ruby language. 60 | */ 61 | class Highlighting : public KDevelop::CodeHighlighting 62 | { 63 | Q_OBJECT 64 | 65 | public: 66 | explicit Highlighting(QObject *parent); 67 | 68 | private: 69 | /** 70 | * Extends base class CodeHighlighting's createInstance() method to use 71 | * this plugin's defined one. 72 | */ 73 | KDevelop::CodeHighlightingInstance * createInstance() const override; 74 | }; 75 | 76 | } 77 | 78 | #endif // RUBYHIGHLIGHTING_H 79 | 80 | -------------------------------------------------------------------------------- /kdevrubysupport.categories: -------------------------------------------------------------------------------- 1 | # KDebugSettings data file 2 | # Format: 3 | # lognamedescription 4 | 5 | kdevelop.languages.ruby KDevelop plugin: Ruby language support 6 | kdevelop.languages.ruby.completion KDevelop plugin: Ruby language support - completion 7 | kdevelop.languages.ruby.duchain KDevelop plugin: Ruby language support - duchain 8 | kdevelop.languages.ruby.parser KDevelop plugin: Ruby language support - parser 9 | -------------------------------------------------------------------------------- /kdevrubysupport.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | kdevrubysupport.rc 5 | 6 | 7 | -------------------------------------------------------------------------------- /kdevrubysupport.rc: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Navigation 6 | 7 | 8 | Rails Navigation 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | &Run 17 | 18 | 19 | 20 | 21 | Code 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /languagesupport.h: -------------------------------------------------------------------------------- 1 | /* This file is part of KDevelop 2 | * 3 | * Copyright 2006-2010 Alexander Dymo 4 | * Copyright (C) 2014-2015 Miquel Sabaté Solà 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU Library General Public License as 8 | * published by the Free Software Foundation; either version 2 of the 9 | * License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public 17 | * License along with this program; if not, write to the 18 | * Free Software Foundation, Inc., 19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | */ 21 | 22 | #ifndef RUBY_LANGUAGE_SUPPORT_H 23 | #define RUBY_LANGUAGE_SUPPORT_H 24 | 25 | #include 26 | #include 27 | 28 | #include 29 | 30 | namespace ruby { 31 | 32 | class Highlighting; 33 | class Launcher; 34 | struct Refactoring; 35 | 36 | namespace rails { 37 | class Support; 38 | } 39 | 40 | /** 41 | * @class LanguageSupport 42 | * 43 | * This is the class that represents the KDevelop Ruby Plugin. This class 44 | * also connects all the actions related to Rails navigation. And last, but 45 | * not least, this class also enables the plugin to execute the current Ruby 46 | * file or test functions. 47 | */ 48 | class LanguageSupport 49 | : public KDevelop::IPlugin 50 | , public KDevelop::ILanguageSupport 51 | { 52 | Q_OBJECT 53 | Q_INTERFACES(KDevelop::ILanguageSupport) 54 | 55 | public: 56 | explicit LanguageSupport(QObject *parent, const QVariantList &args = {}); 57 | ~LanguageSupport() override; 58 | 59 | /** 60 | * @return an instance of this LanguageSupport. 61 | */ 62 | static LanguageSupport * self(); 63 | 64 | /** 65 | * @return the name of the language. 66 | */ 67 | QString name() const override; 68 | 69 | /** 70 | * @return the ParseJob that is going to be used by the Background 71 | * parser to parse the given @p url. 72 | */ 73 | KDevelop::ParseJob * createParseJob(const KDevelop::IndexedString &url) override; 74 | 75 | /** 76 | * @return the Code Highlighting for the Ruby language. 77 | */ 78 | KDevelop::ICodeHighlighting * codeHighlighting() const override; 79 | 80 | /** 81 | * @returns the ContextMenuExtension for the Php plugin. 82 | */ 83 | KDevelop::ContextMenuExtension contextMenuExtension(KDevelop::Context* context, QWidget* parent) override; 84 | 85 | /** 86 | * @return the version of Ruby to be picked. 87 | */ 88 | enum ruby_version version() const; 89 | 90 | /** 91 | * Setup the actions defined by this plugin. 92 | */ 93 | void createActionsForMainWindow(Sublime::MainWindow *window, 94 | QString &xmlFile, 95 | KActionCollection &actions) override; 96 | 97 | private: 98 | Highlighting *m_highlighting; 99 | Refactoring *m_refactoring; 100 | Launcher *m_launcher; 101 | enum ruby_version m_version; 102 | 103 | rails::Support *m_rails; 104 | }; 105 | 106 | } 107 | 108 | #endif // RUBY_LANGUAGE_SUPPORT_H 109 | 110 | -------------------------------------------------------------------------------- /launcher.h: -------------------------------------------------------------------------------- 1 | /* This file is part of KDevelop 2 | * 3 | * Copyright (C) 2014-2015 Miquel Sabaté Solà 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | #ifndef RUBY_LAUNCHER_H 20 | #define RUBY_LAUNCHER_H 21 | 22 | #include 23 | 24 | namespace KDevelop { 25 | class IDocument; 26 | class ILaunchConfiguration; 27 | } 28 | 29 | namespace ruby { 30 | 31 | class LanguageSupport; 32 | 33 | /** 34 | * @class Launcher 35 | * 36 | * The class responsible for all the default launcher for this plugin. It's 37 | * only used by the LanguageSupport class, but I rather have this functionality 38 | * in this separate class than having a bloated LanguageSupport class. 39 | */ 40 | class Launcher : public QObject 41 | { 42 | public: 43 | explicit Launcher(LanguageSupport *support); 44 | 45 | /** 46 | * Setup the Main Window actions. 47 | * 48 | * @param actions The main window actions to be modified. 49 | */ 50 | void setupActions(KActionCollection &actions); 51 | 52 | private: 53 | /** 54 | * @internal Find or create a launch for a the given @p name. 55 | * @return the launch configuration for the given @p name. 56 | */ 57 | KDevelop::ILaunchConfiguration * launchConfiguration(const QString &name); 58 | 59 | private slots: 60 | /// The slot that allows this plugin to run the current Ruby file. 61 | void runCurrentFile(); 62 | 63 | /// The slot that allows this plugin to run the current test function. 64 | void runCurrentTest(); 65 | 66 | private: 67 | LanguageSupport *m_support; 68 | KDevelop::ILaunchConfiguration *m_file; 69 | KDevelop::ILaunchConfiguration *m_function; 70 | }; 71 | 72 | } 73 | 74 | #endif // RUBY_LAUNCHER_H 75 | 76 | -------------------------------------------------------------------------------- /parsejob.h: -------------------------------------------------------------------------------- 1 | /* This file is part of KDevelop 2 | * 3 | * Copyright 2008-2010 Alexander Dymo 4 | * Copyright (C) 2011-2015 Miquel Sabaté Solà 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation; either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License along 17 | * with this program; if not, write to the Free Software Foundation, Inc., 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 | */ 20 | 21 | #ifndef RUBY_PARSE_JOB_H 22 | #define RUBY_PARSE_JOB_H 23 | 24 | #include 25 | 26 | namespace ruby { 27 | 28 | class LanguageSupport; 29 | class Parser; 30 | 31 | /** 32 | * @class ParseJob 33 | * 34 | * This is a subclass of KDevelop::ParseJob and does the parse 35 | * job for the Ruby language. 36 | */ 37 | class ParseJob : public KDevelop::ParseJob 38 | { 39 | Q_OBJECT 40 | 41 | public: 42 | enum { Rescheduled = KDevelop::TopDUContext::LastFeature }; 43 | 44 | /** 45 | * Constructor. 46 | * 47 | * @param url the url of the file to parse. 48 | * @param languageSupport the ILanguageSupport of this plugin. 49 | */ 50 | ParseJob(const KDevelop::IndexedString &url, 51 | KDevelop::ILanguageSupport *languageSupport); 52 | ~ParseJob() override; 53 | 54 | protected: 55 | /** 56 | * Runs this ParseJob. Both of the parameters being passed come from 57 | * ThreadWeaver and they are both ignored in the implementation. 58 | */ 59 | void run(ThreadWeaver::JobPointer pointer, 60 | ThreadWeaver::Thread *thread) override; 61 | 62 | private: 63 | /** 64 | * @return static accessor to avoid casting. 65 | */ 66 | LanguageSupport * ruby() const; 67 | 68 | Parser *m_parser; 69 | 70 | private: 71 | KDevelop::ReferencedTopDUContext m_duContext; 72 | }; 73 | 74 | } 75 | 76 | #endif // RUBY_PARSE_JOB_H 77 | 78 | -------------------------------------------------------------------------------- /parser/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | bison_target(RUBY_PARSER parser.y ${CMAKE_CURRENT_BINARY_DIR}/parser_gen.c) 3 | 4 | set(rubyparser_SRCS 5 | node.c 6 | ${BISON_RUBY_PARSER_OUTPUTS} 7 | parser.cpp 8 | astvisitor.cpp 9 | ast.cpp 10 | ) 11 | ecm_qt_declare_logging_category(rubyparser_SRCS 12 | HEADER parserdebug.h 13 | IDENTIFIER PARSER 14 | CATEGORY_NAME "kdevelop.languages.ruby.parser" 15 | ) 16 | 17 | add_library(kdevrubyparser SHARED ${rubyparser_SRCS}) 18 | 19 | generate_export_header(kdevrubyparser EXPORT_MACRO_NAME KDEVRUBYPARSER_EXPORT 20 | EXPORT_FILE_NAME export.h) 21 | 22 | target_link_libraries(kdevrubyparser LINK_PRIVATE 23 | KDev::Language 24 | ) 25 | 26 | # Compile & install the tests if needed. 27 | if(BUILD_TESTING AND CMAKE_BUILD_TYPE STREQUAL "Debug") 28 | add_definitions(-DBUILD_TESTS) 29 | add_executable(ruby-parser main.c) 30 | set_target_properties(ruby-parser PROPERTIES WIN32_EXECUTABLE 0) 31 | install(DIRECTORY tools DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) 32 | target_link_libraries(ruby-parser kdevrubyparser) 33 | endif() 34 | 35 | install(TARGETS kdevrubyparser DESTINATION ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) 36 | 37 | -------------------------------------------------------------------------------- /parser/README.md: -------------------------------------------------------------------------------- 1 | # Parser 2 | 3 | ## Intro 4 | 5 | This is a bison-generated pure LALR parser. It's based on the MRI parser. 6 | This parser has been designed to be small, simple and yet powerful. Its code 7 | resides in four different files: parser.y, node.h, node.c and main.c. 8 | The main.c file is conceived only for testing purposes (see the section 9 | "Testing and Debugging the parser"). More important are the files node.h and 10 | node.c that, in short, define what is a node and what can we (and the parser) 11 | do with nodes. Finally, the parser.y file is the grammar of the parser. This 12 | is the parser in its very basic shape. To see what this parser really looks 13 | like, we have to generate three files: parser.h, parser.c and hash.c. 14 | The parser\_gen.{h, c} files are generated by bison taking the grammar file as 15 | its input. The last, (but not least) file to generate is hash.c and it's 16 | generated by gperf taking the file tools/gperf.txt as its input. It contains 17 | a hash table that is used by the parser to match keywords quickly. The 18 | parser\_gen.{h, c} files are generated by cmake. The hash.c file is generated 19 | with the tools/gperf.rb script. 20 | 21 | ## Testing and Debugging the Parser 22 | 23 | All the info on testing the parser can be found [here](http://techbase.kde.org/Projects/KDevelop4/Ruby#Testing). 24 | 25 | What represents all those integers from the output ? In short, 26 | it's the representation of an AST printed in pre-order. As you 27 | will see, the parser tries to beautify this output by telling you if the 28 | expression is a condition inside of, for example, a for statement, or it will 29 | output "Root" and "Next" if there is a list of inner statements. Moreover, the 30 | parser sometimes outputs names between parenthesis. Those names are variables, 31 | the name of a function, a class, etc. Sadly, sometimes the output is scary 32 | and a complete mess. In those cases, experience and patience 33 | will be our friends ;) 34 | 35 | ## Character encodings 36 | 37 | As stated before, this parser is meant to be simple and small. This means 38 | that by now we only support UTF-8 encoding. This doesn't mean that 39 | other encodings will never be supported by this parser, it's just that 40 | the developers haven't had enough time to write the code. 41 | 42 | -------------------------------------------------------------------------------- /parser/ast.cpp: -------------------------------------------------------------------------------- 1 | /* This file is part of KDevelop 2 | * 3 | * Copyright (C) 2011-2015 Miquel Sabaté Solà 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | #include 20 | 21 | using namespace ruby; 22 | 23 | Ast::Ast(Node *n, KDevelop::DUContext *ctx) 24 | : tree(n) 25 | , context(ctx) 26 | , foundProblems(false) 27 | { 28 | } 29 | 30 | NameAst::NameAst(const Ast *ast) : Ast(ast->tree, ast->context) 31 | { 32 | if (tree == nullptr) { 33 | value = "nil"; 34 | } else if (tree->kind == token_class || tree->kind == token_module) { 35 | value = QString(rb_name_node(tree)->name); 36 | } else if (tree->kind == token_function) { 37 | value = QString(rb_name_node(tree)->name); 38 | } else { 39 | value = QString(tree->name); 40 | } 41 | } 42 | 43 | -------------------------------------------------------------------------------- /parser/ast.h: -------------------------------------------------------------------------------- 1 | /* This file is part of KDevelop 2 | * 3 | * Copyright (C) 2011-2015 Miquel Sabaté Solà 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | #ifndef RUBY_AST_H 20 | #define RUBY_AST_H 21 | 22 | #include 23 | 24 | #include 25 | #include 26 | 27 | namespace ruby { 28 | 29 | /** 30 | * @class RubyAst 31 | * 32 | * This class represents a Ruby AST (Abstract Syntax Tree). It contains 33 | * the code (tree) and the associated KDevelop::DUContext. 34 | */ 35 | class KDEVRUBYPARSER_EXPORT Ast 36 | { 37 | public: 38 | /** 39 | * Constructor. 40 | * 41 | * @param n the code that this RubAst represents. 42 | * @param ctx the KDevelop::DUContext associated with it. 43 | */ 44 | explicit Ast(Node *n, KDevelop::DUContext *ctx = nullptr); 45 | 46 | public: 47 | /// The tree of this AST. 48 | Node *tree; 49 | 50 | /// The DUContext for this AST. 51 | KDevelop::DUContext *context; 52 | 53 | /// Used when we find a problem. 54 | bool foundProblems; 55 | }; 56 | 57 | /** 58 | * @class NameAst 59 | * 60 | * Extends the RubyAst class to easily obtain the identifier for 61 | * a RubyAst. 62 | */ 63 | class KDEVRUBYPARSER_EXPORT NameAst : public Ast 64 | { 65 | public: 66 | /** 67 | * Constructor. 68 | * 69 | * @param ast the RubyAst this class extends. 70 | */ 71 | explicit NameAst(const Ast *ast); 72 | 73 | public: 74 | /// The QString that represents this class. 75 | QString value; 76 | }; 77 | 78 | } 79 | 80 | #endif // RUBY_AST_H 81 | 82 | -------------------------------------------------------------------------------- /parser/main.c: -------------------------------------------------------------------------------- 1 | /* This file is part of KDevelop 2 | * 3 | * Copyright (C) 2010-2015 Miquel Sabaté Solà 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | 20 | #include 21 | #include 22 | #include "node.h" 23 | 24 | 25 | extern int rb_debug_file(struct options_t *opts); 26 | 27 | /* 28 | * This is a recursive function that steps over the AST to fetch 29 | * all the comments that the parser has stored. All the comments 30 | * are printed to the stdout. 31 | */ 32 | void fetch_comments(struct Node *tree) 33 | { 34 | if (!tree) 35 | return; 36 | if (tree->comment != NULL) 37 | printf("%s", tree->comment); 38 | 39 | fetch_comments(tree->l); 40 | fetch_comments(tree->r); 41 | fetch_comments(tree->next); 42 | } 43 | 44 | 45 | /** 46 | * This is the main function for the parser's debugging utility. It's 47 | * used to perform all the tests. Please, take a look at the README file 48 | * for more info. 49 | */ 50 | int main(int argc, char *argv[]) 51 | { 52 | struct ast_t *ast; 53 | struct options_t opts; 54 | 55 | switch (argc) { 56 | case 2: 57 | opts.path = argv[argc - 1]; 58 | opts.version = ruby21; 59 | return rb_debug_file(&opts); 60 | case 3: 61 | opts.path = argv[argc - 2]; 62 | opts.contents = NULL; 63 | opts.version = atoi(argv[argc - 1]); 64 | ast = rb_compile_file(&opts); 65 | if (ast->errors) { 66 | print_errors(ast->errors); 67 | exit(1); 68 | } 69 | fetch_comments(ast->tree); 70 | rb_free(ast); 71 | break; 72 | default: 73 | printf("Usage: ruby-parser file [ruby-version]\n\n"); 74 | printf("KDevelop Ruby parser debugging utility\n"); 75 | } 76 | return 0; 77 | } 78 | -------------------------------------------------------------------------------- /parser/parser.h: -------------------------------------------------------------------------------- 1 | /* This file is part of KDevelop 2 | * 3 | * Copyright (C) 2011-2015 Miquel Sabaté Solà 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | #ifndef RUBY_PARSER_H 20 | #define RUBY_PARSER_H 21 | 22 | #include 23 | 24 | #include 25 | #include 26 | 27 | namespace ruby { 28 | 29 | /** 30 | * @class Parser 31 | * 32 | * This class represents an interface to the "pure" parser and it may 33 | * be used across the plugin. 34 | */ 35 | class KDEVRUBYPARSER_EXPORT Parser 36 | { 37 | /// Convenient alias that packs a DUContextPointer and a RangeInRevision. 38 | using SimpleUse = QPair; 40 | 41 | public: 42 | Parser(); 43 | Parser(const KDevelop::IndexedString &fileName, const QByteArray &contents); 44 | virtual ~Parser(); 45 | 46 | /** 47 | * Set the contents of the document. 48 | * 49 | * @param contents the contents of the file to parse. 50 | */ 51 | void setContents(const QByteArray &contents); 52 | 53 | /** 54 | * Set the version of the Ruby interpreter. 55 | */ 56 | void setRubyVersion(enum ruby_version version); 57 | 58 | /** 59 | * This method parses the current document. 60 | * 61 | * @return the generated Ast. 62 | */ 63 | Ast * parse(); 64 | 65 | /** 66 | * Implemented to make the AbstractUseBuilder happy. 67 | */ 68 | void mapAstUse(Ast *node, const SimpleUse &use); 69 | 70 | /** 71 | * @return a QString that represents the value of the node 72 | * (not the node's name). 73 | */ 74 | const QString symbol(const Node *node) const; 75 | 76 | private: 77 | /** 78 | * @internal called when there are errors in the current document and we 79 | * want to append one of them in a list of ProblemPointer's. 80 | * 81 | * @param error the error provided to this method. 82 | */ 83 | void appendProblem(const struct error_t *error); 84 | 85 | public: 86 | QVector problems; 87 | KDevelop::IndexedString currentDocument; 88 | Ast *ast; 89 | 90 | private: 91 | QByteArray m_contents; 92 | enum ruby_version m_version; 93 | }; 94 | 95 | } 96 | 97 | #endif // RUBY_PARSER_H 98 | 99 | -------------------------------------------------------------------------------- /parser/tools/fancy.rb: -------------------------------------------------------------------------------- 1 | ## 2 | # This file is part of KDevelop 3 | # Copyright (C) 2011-2015 Miquel Sabaté Solà 4 | # 5 | # This program is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with this program. If not, see . 17 | 18 | 19 | #!/usr/bin/env ruby 20 | 21 | # 22 | # Prints the output of the parser in a "fancy" way, translating the numbers 23 | # shown at the expected output of the tests to words for mere mortals. This 24 | # script does the job by executing the parser on a given test and flushing 25 | # its output to a temporary file. Then it does the transalation in a simple way 26 | # and shows the output to the user. 27 | # NOTE: To use it, for example, just type "ruby fancy.rb test.rb" 28 | # to execute "tests/test.rb" ;) 29 | # 30 | 31 | # Only execute this script if the user provided a name 32 | exit if ARGV[0].nil? 33 | 34 | translate = [ 35 | 'whitespace', 'comment', 'plus', 'minus', 'mul', 'pow', 'div', 'mod', 'bit_and', 'bit_or', 'bit_xor', 36 | 'kw_and', 'kw_or', 'kw_not', 'or', 'and', 'lshift', 'rshift', 'neg', 'not', 'unary_plus', 37 | 'unay_minus', 'assign', 'op_assign', 'assoc', 'cmp', 'eq', 'neq', 'eqq', 'match', 'nmatch', 38 | 'greater', 'geq', 'lesser', 'leq', 'dot2', 'dot3', 'ternary', 'if', 'unless', 'while', 39 | 'until', 'case', 'when', 'BEGIN', 'END', 'for', 'begin', 'rescue_arg', 'rescue', 'ensure', 40 | 'object', 'numeric', 'symbol', 'body', 'function', 'module', 'class', 'singleton_class', 'super', 'string', 41 | 'regexp', 'key', 'array', 'hash', 'block', 'method_call', 'heredoc', 'break', 'redo', 'retry', 42 | 'next', 'return', 'yield', 'alias', 'defined', 'undef', 'array_value', '__END__', 'true', 'false', 43 | 'nil', 'self', '__ENCODING__', '__FILE__', '__LINE__' 44 | ] 45 | 46 | output = `../ruby-parser tests/#{ARGV.first}.rb` 47 | output.split("\n").each do |l| 48 | line = l.gsub(/[0-9]+(\[)/) { |m| "#{translate[m.to_i]}[" } 49 | puts line.gsub(/[0-9]+(\()/) { |m| "#{translate[m.to_i]}(" } 50 | end 51 | -------------------------------------------------------------------------------- /parser/tools/gperf.rb: -------------------------------------------------------------------------------- 1 | ## 2 | # This file is part of KDevelop 3 | # Copyright (C) 2011-2015 Miquel Sabaté Solà 4 | # 5 | # This program is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with this program. If not, see . 17 | 18 | 19 | #!/usr/bin/env ruby 20 | 21 | ## 22 | # This script just calls gperf with the correct arguments in order 23 | # to generate the hash.c file. 24 | 25 | 26 | # Check if the given program exists on your system. 27 | # 28 | # program - a String containing the name of the program. 29 | # 30 | # Returns true if the program exists on your system, false otherwise. 31 | def exists? program 32 | ENV['PATH'].split(File::PATH_SEPARATOR).any? do |directory| 33 | File.executable?(File.join(directory, program.to_s)) 34 | end 35 | end 36 | 37 | # Check if exists gperf on your system 38 | unless exists? 'gperf' 39 | puts 'You need gperf to run this script' 40 | exit 41 | end 42 | 43 | # Let's execute gperf with the appropiate arguments. 44 | 45 | GFLAGS = '-C -p -j1 -i 1 -g -o -t -N rb_reserved_word -k1,3,$ gperf.txt > ../hash.c' 46 | 47 | puts 'Using gperf to generate hash.c' 48 | `gperf #{GFLAGS}` 49 | text = File.read('../hash.c').gsub /{""}/, '{"", {0,0}, 0}' 50 | File.open('../hash.c', 'w') { |file| file.puts text } 51 | -------------------------------------------------------------------------------- /parser/tools/gperf.txt: -------------------------------------------------------------------------------- 1 | %{ 2 | struct kwtable {const char *name; int id[2]; enum lex_state_e state;}; 3 | const struct kwtable *rb_reserved_word(const char *, unsigned int); 4 | static const struct kwtable *reserved_word(const char *, unsigned int); 5 | #define rb_reserved_word(str, len) reserved_word(str, len) 6 | %} 7 | 8 | struct kwtable; 9 | %% 10 | __ENCODING__, {tENCODING, tENCODING}, EXPR_END 11 | __LINE__, {tLINE, tLINE}, EXPR_END 12 | __FILE__, {tFILE, tFILE}, EXPR_END 13 | BEGIN, {upBEGIN, upBEGIN}, EXPR_END 14 | END, {upEND, upEND}, EXPR_END 15 | alias, {tALIAS, tALIAS}, EXPR_FNAME 16 | and, {tKWAND, tKWAND}, EXPR_VALUE 17 | begin, {tBEGIN, tBEGIN}, EXPR_BEG 18 | break, {tBREAK, tBREAK}, EXPR_MID 19 | case, {tCASE, tCASE}, EXPR_VALUE 20 | class, {tCLASS, tCLASS}, EXPR_CLASS 21 | def, {tDEF, tDEF}, EXPR_FNAME 22 | defined?, {tDEFINED, tDEFINED}, EXPR_ARG 23 | do, {tDO, tDO}, EXPR_BEG 24 | else, {tELSE, tELSE}, EXPR_BEG 25 | elsif, {tELSIF, tELSIF}, EXPR_VALUE 26 | end, {tEND, tEND}, EXPR_END 27 | ensure, {tENSURE, tENSURE}, EXPR_BEG 28 | false, {tFALSE, tFALSE}, EXPR_END 29 | for, {tFOR, tFOR}, EXPR_VALUE 30 | if, {tIF, modifier_if}, EXPR_VALUE 31 | in, {tIN, tIN}, EXPR_VALUE 32 | module, {tMODULE, tMODULE}, EXPR_VALUE 33 | next, {tNEXT, tNEXT}, EXPR_MID 34 | nil, {tNIL, tNIL}, EXPR_END 35 | not, {tKWNOT, tKWNOT}, EXPR_ARG 36 | or, {tKWOR, tKWOR}, EXPR_VALUE 37 | redo, {tREDO, tREDO}, EXPR_END 38 | rescue, {tRESCUE, modifier_rescue}, EXPR_MID 39 | retry, {tRETRY, tRETRY}, EXPR_END 40 | return, {tRETURN, tRETURN}, EXPR_MID 41 | self, {tSELF, tSELF}, EXPR_END 42 | super, {tSUPER, tSUPER}, EXPR_ARG 43 | then, {tTHEN, tTHEN}, EXPR_BEG 44 | true, {tTRUE, tTRUE}, EXPR_END 45 | undef, {tUNDEF, tUNDEF}, EXPR_FNAME 46 | unless, {tUNLESS, modifier_unless}, EXPR_VALUE 47 | until, {tUNTIL, modifier_until}, EXPR_VALUE 48 | when, {tWHEN, tWHEN}, EXPR_VALUE 49 | while, {tWHILE, modifier_while}, EXPR_VALUE 50 | yield, {tYIELD, tYIELD}, EXPR_ARG 51 | %% 52 | -------------------------------------------------------------------------------- /parser/tools/parser_spec.rb: -------------------------------------------------------------------------------- 1 | ## 2 | # This file is part of KDevelop 3 | # Copyright (C) 2012-2015 Miquel Sabaté Solà 4 | # 5 | # This program is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with this program. If not, see . 17 | 18 | 19 | # Returns a String containing the absolute path to the ruby parser. 20 | def parser 21 | File.join(File.dirname(__FILE__), '../ruby-parser') 22 | end 23 | 24 | describe 'Parser' do 25 | base = File.dirname(__FILE__) 26 | 27 | # Regular tests 28 | files = Dir[File.join(base, 'tests/*.rb')] 29 | files.each do |file| 30 | name = file.match(/.*\/(.+)+\.rb$/)[1] 31 | 32 | it "test: `#{name}'" do 33 | expected = File.read "#{base}/tests/#{name}.txt" 34 | expect(`#{parser} #{base}/tests/#{name}.rb`).to eq(expected) 35 | end 36 | end 37 | 38 | # Testing that the comments are stored properly. 39 | it 'test: `comments\'' do 40 | expected = File.read "#{base}/tests/comments/expected.txt" 41 | expect(`#{parser} #{base}/tests/comments/test.rb 2`).to eq(expected) 42 | end 43 | 44 | # Testing the warnings on incompatible Ruby versions. 45 | context 'Ruby versions:' do 46 | it '1.8.x -> 1.9.x transition' do 47 | output = `#{parser} #{base}/tests/errors/from18to19.rb 0` 48 | expect(output).to eq(<<-HEREDOC.gsub(/^\s+/, '') 49 | Line: 1, Column: 16; This syntax is only available in Ruby 1.9.x or higher. 50 | Line: 2, Column: 4; "->" syntax is only available in Ruby 1.9.x or higher. 51 | Line: 3, Column: 15; Block local variables are only available in Ruby 1.9.x or higher. 52 | HEREDOC 53 | ) 54 | end 55 | 56 | it '1.9.x -> 2.0.x transition' do 57 | output = `#{parser} #{base}/tests/errors/from19to20.rb 0` 58 | expect(output).to eq(<<-HEREDOC.gsub(/^\s+/, '') 59 | Line: 1, Column: 22; Keyword arguments are only available in Ruby 2.0.x or higher. 60 | Line: 4, Column: 21; Keyword arguments are only available in Ruby 2.0.x or higher. 61 | Line: 9, Column: 9; This syntax is only available in Ruby 1.9.x or higher. 62 | Line: 9, Column: 15; This syntax is only available in Ruby 1.9.x or higher. 63 | Line: 11, Column: 25; Keyword arguments are only available in Ruby 2.0.x or higher. 64 | Line: 14, Column: 46; Keyword arguments are only available in Ruby 2.0.x or higher. 65 | Line: 17, Column: 2; This shortcut is only available in Ruby 2.0.x or higher. 66 | HEREDOC 67 | ) 68 | end 69 | 70 | it '2.0.x -> 2.1.x transition' do 71 | output = `#{parser} #{base}/tests/errors/from20to21.rb 0` 72 | expect(output).to eq(<<-HEREDOC.gsub(/^\s+/, '') 73 | Line: 2, Column: 8; Imaginary literals are only available in Ruby 2.1.x or higher. 74 | Line: 3, Column: 8; Rational literals are only available in Ruby 2.1.x or higher. 75 | HEREDOC 76 | ) 77 | end 78 | end 79 | end 80 | -------------------------------------------------------------------------------- /parser/tools/tests/array.rb: -------------------------------------------------------------------------------- 1 | def foo a, b 2 | a + b 3 | end 4 | 5 | def alone 6 | 3 7 | end 8 | 9 | a = [1, (b = foo 1, 2), 3] 10 | b = [foo(1, 2), 2] 11 | c = [alone, foo(1, 2), d = a] # Warning: 'alone' detected as object 12 | a = [1, (puts 1, 2), 2] 13 | e = [(f, g = 1, 2), 3] 14 | h = [(i, = 1, 2, 3), 4] 15 | j = [1 + 3, 'string''another''one'] 16 | k = [[1, 2, 3], [[1, 2], [1, 2]], {'asd' => 1 }] 17 | 18 | x = [1, 2, 4] 19 | y = [[1, 2], [[1, 2], [3, 4]]] 20 | x[0] = y[0][alone] + y[1][1][0] 21 | 22 | a = [ 23 | 1, 2 ] 24 | a = [ 25 | 1, 26 | 2] 27 | a = [ 28 | 1, 29 | 2 30 | ] 31 | 32 | %w{one two three} 33 | %w(one two three) 34 | %w 35 | %w[one two three] 36 | 37 | %w[ HTML HEAD BODY P PLAINTEXT DT DD LI OPTION tr 38 | th td ] 39 | %w[one two three] 40 | %w$Revision: 26193 $ 41 | -------------------------------------------------------------------------------- /parser/tools/tests/array.txt: -------------------------------------------------------------------------------- 1 | Resulting AST's: 2 | 51(a)[2,2:2,3] 2 51(b)[2,6:2,7] 54[2,0:3,0] 55 51(a)[1,8:1,9] 3 | Next statements: 51(b)[1,11:1,12] 4 | Root: 5 | Condition: 51(foo)[1,4:1,7] 6 | 52 54[6,0:7,0] 55 7 | Condition: 51(alone)[5,4:5,9] 8 | 51(a)[9,0:9,1] 22 52 9 | Next statements: 22 52 10 | Root: 63 11 | 51(b)[10,0:10,1] 22 51(foo)[10,5:10,8] 66 52 12 | Next statements: 52 13 | Root: 14 | Next statements: 52 15 | Root: 63 16 | 51(c)[11,0:11,1] 22 51(alone)[11,5:11,10] 17 | Next statements: 66 22 18 | Root: 63 19 | 51(a)[12,0:12,1] 22 52 20 | Next statements: 66 52 21 | Root: 63 22 | 51(e)[13,0:13,1] 22 51(f)[13,6:13,7] 23 | Next statements: 51(g)[13,9:13,10] 24 | Root: 22 52 25 | Next statements: 52 26 | Root: 27 | Next statements: 52 28 | Root: 63 29 | 51(h)[14,0:14,1] 22 51(i)[14,6:14,7] 22 52 30 | Next statements: 52 52 31 | Root: 32 | Next statements: 52 33 | Root: 63 34 | 51(j)[15,0:15,1] 22 52 2 52 35 | Next statements: 60 36 | Root: 63 37 | 51(k)[16,0:16,1] 22 52 38 | Next statements: 52 52 39 | Root: 63 40 | Next statements: 63 64 41 | Root: 63 42 | 51(x)[18,0:18,1] 22 52 43 | Next statements: 52 52 44 | Root: 63 45 | 51(y)[19,0:19,1] 22 52 46 | Next statements: 52 47 | Root: 63 48 | Next statements: 63 49 | Root: 63 50 | 51(x)[20,0:20,1] 77 52 22 51(y)[20,7:20,8] 77 52 77 51(alone)[20,12:20,17] 2 51(y)[20,21:20,22] 77 52 77 52 77 52 51 | 51(a)[22,0:22,1] 22 52 52 | Next statements: 52 53 | Root: 63 54 | 51(a)[24,0:24,1] 22 52 55 | Next statements: 52 56 | Root: 63 57 | 51(a)[27,0:27,1] 22 52 58 | Next statements: 52 59 | Root: 63 60 | 63 61 | 63 62 | 63 63 | 63 64 | 63 65 | 63 66 | 63 67 | 68 | 69 | -------------------------------------------------------------------------------- /parser/tools/tests/assign.rb: -------------------------------------------------------------------------------- 1 | a, *, b, c = 0, 1, 3, [1, 2] 2 | a, (b, c), d = 0, 1, 2 3 | a, 4 | b = 5 | 1, 6 | 2 7 | a, b = 1, 8 | 2 9 | a = 1, 2, 3 10 | a, = 1, 2, 3 11 | a[0] = 1 12 | a[foo 1, 2, 3] = 1 13 | a.b = 1 14 | a::b.c = 2 15 | 16 | a = if b < 1 17 | 3 18 | else 19 | 4 20 | end 21 | 22 | b = class Klass 23 | end 24 | 25 | a = begin 26 | 0 27 | end 28 | 29 | a.CONST += 1 30 | a::b += 1 31 | a.b += 1 32 | a[1] += 1 33 | a::year, b.month, c.DAY, d::LALA = year, month, day, lala 34 | h ^= a 35 | -------------------------------------------------------------------------------- /parser/tools/tests/assign.txt: -------------------------------------------------------------------------------- 1 | Resulting AST's: 2 | 51(a)[1,0:1,1] 3 | Next statements: 51 51(b)[1,6:1,7] 51(c)[1,9:1,10] 4 | Root: 22 52 5 | Next statements: 52 52 63 6 | Root: 7 | 51(a)[2,0:2,1] 8 | Next statements: 51 51(d)[2,11:2,12] 9 | Root: 22 52 10 | Next statements: 52 52 11 | Root: 12 | 51(a)[3,0:3,1] 13 | Next statements: 51(b)[4,4:4,5] 14 | Root: 22 52 15 | Next statements: 52 16 | Root: 17 | 51(a)[7,0:7,1] 18 | Next statements: 51(b)[7,3:7,4] 19 | Root: 22 52 20 | Next statements: 52 21 | Root: 22 | 51(a)[9,0:9,1] 22 52 23 | Next statements: 52 52 24 | Root: 25 | 51(a)[10,0:10,1] 22 52 26 | Next statements: 52 52 27 | Root: 28 | 51(a)[11,0:11,1] 77 52 22 52 29 | 51(a)[12,0:12,1] 77 51(foo)[12,2:12,5] 66 52 30 | Next statements: 52 52 31 | Root: 22 52 32 | 51(a)[13,0:13,1] 66 51(b)[13,2:13,3] 22 52 33 | 51(a)[14,0:14,1] 34 | Next statements: 51(b)[14,3:14,4] 35 | Root: 66 66 51(c)[14,5:14,6] 22 52 36 | 51(a)[16,0:16,1] 22 52 38 52 38 37 | 51(b)[22,0:22,1] 22 54[23,0:23,0] 57 51(Klass)[22,10:22,15] 38 | 51(a)[25,0:25,1] 22 52 54[25,9:27,0] 47 39 | 51(a)[29,0:29,1] 51 51(CONST)[29,2:29,7] 23 52 40 | 51(a)[30,0:30,1] 51 51(b)[30,3:30,4] 23 52 41 | 51(a)[31,0:31,1] 51 51(b)[31,2:31,3] 23 52 42 | 51(a)[32,0:32,1] 77 52 23 52 43 | 51(a)[33,0:33,1] 66 51(year)[33,3:33,7] 44 | Next statements: 66 66 66 45 | Root: 22 51(year)[33,35:33,39] 46 | Next statements: 51(month)[33,41:33,46] 51(day)[33,48:33,51] 51(lala)[33,53:33,57] 47 | Root: 48 | 51(h)[34,0:34,1] 23 51(a)[34,5:34,6] 49 | 50 | 51 | -------------------------------------------------------------------------------- /parser/tools/tests/begin_end.rb: -------------------------------------------------------------------------------- 1 | BEGIN { 2 | a = 0 3 | a += 1 4 | } 5 | 6 | END { b = 0 } 7 | END { b = 0 8 | } 9 | 10 | puts DATA.read 11 | 12 | __END__ 13 | Perl, Perl everywhere... 14 | -------------------------------------------------------------------------------- /parser/tools/tests/begin_end.txt: -------------------------------------------------------------------------------- 1 | Resulting AST's: 2 | 51(a)[2,2:2,3] 22 52 3 | Next statements: 23 4 | Root: 44 5 | 51(b)[6,6:6,7] 22 52 45 6 | 51(b)[7,6:7,7] 22 52 45 7 | 51(puts)[10,0:10,4] 66 51(DATA)[10,5:10,9] 8 | Next statements: 51(read)[10,10:10,14] 9 | Root: 66 10 | 78 11 | 12 | -------------------------------------------------------------------------------- /parser/tools/tests/block.rb: -------------------------------------------------------------------------------- 1 | a = lambda { |x| return x + 1 } 2 | a = lambda { |;y| return y + 1 } 3 | a = lambda { |x;y| return y + 1 } 4 | 5 | fun = ->(a, b) do 6 | puts a + b 7 | end 8 | fun.call(1, 2) 9 | 10 | variable = -> { puts 'lalala' } 11 | variable.call 12 | 13 | hash = { foo: ->(a, b) { puts a + b } } 14 | hash[:foo].call(1, 2) 15 | 16 | a = [1, 2, 3, 4] 17 | a.foo(1) do |x| 18 | puts(x) 19 | end 20 | 21 | a.foo(1) do 22 | |x| 23 | puts(x) 24 | end 25 | 26 | a.foo 1, 2 do |x| 27 | puts x 28 | end 29 | 30 | a.foo(1).c.d do 31 | |x| 32 | puts(x) 33 | end 34 | 35 | a.foo(1).c.d 1, 2 do 36 | |x| 37 | puts(x) 38 | end 39 | 40 | a.foo do |x, y, *z| 41 | end 42 | 43 | { a: 1, b: 2 }.each do |x, y| 44 | end 45 | 46 | 5.times { puts 'Spartans! What is your profession !?' } 47 | 48 | foo do |x = 1| 49 | end 50 | 51 | foo do |x = 1, *y| 52 | end 53 | 54 | foo do |*| # Expected: the star has pos = -1 55 | end 56 | 57 | foo do |x, &y| 58 | end 59 | 60 | foo do |x, y = 1; z| 61 | end 62 | 63 | a {[]} 64 | -------------------------------------------------------------------------------- /parser/tools/tests/block.txt: -------------------------------------------------------------------------------- 1 | Resulting AST's: 2 | 51(a)[1,0:1,1] 22 51(lambda)[1,4:1,10] 66 3 | 51(a)[2,0:2,1] 22 51(lambda)[2,4:2,10] 66 4 | 51(a)[3,0:3,1] 22 51(lambda)[3,4:3,10] 66 5 | 51(fun)[5,0:5,3] 22 66 6 | 51(fun)[8,0:8,3] 7 | Next statements: 51(call)[8,4:8,8] 8 | Root: 66 52 9 | Next statements: 52 10 | Root: 11 | 51(variable)[10,0:10,8] 22 66 12 | 51(variable)[11,0:11,8] 13 | Next statements: 51(call)[11,9:11,13] 14 | Root: 66 15 | 51(hash)[13,0:13,4] 22 53(foo)[13,9:13,12] 51 66 64 16 | 51(hash)[14,0:14,4] 77 53(foo)[14,5:14,9] 17 | Next statements: 51(call)[14,11:14,15] 18 | Root: 66 52 19 | Next statements: 52 20 | Root: 21 | 51(a)[16,0:16,1] 22 52 22 | Next statements: 52 52 52 23 | Root: 63 24 | 51(a)[17,0:17,1] 25 | Next statements: 51(foo)[17,2:17,5] 26 | Root: 66 52 27 | Condition: 51(puts)[18,2:18,6] 66 51(x)[18,7:18,8] 65[17,9:19,3] 51(x)[17,13:17,14] 28 | 51(a)[21,0:21,1] 29 | Next statements: 51(foo)[21,2:21,5] 30 | Root: 66 52 31 | Condition: 51(puts)[23,2:23,6] 66 51(x)[23,7:23,8] 65[21,9:24,3] 51(x)[22,3:22,4] 32 | 51(a)[26,0:26,1] 33 | Next statements: 51(foo)[26,2:26,5] 34 | Root: 66 52 35 | Next statements: 52 36 | Root: 37 | Condition: 51(puts)[27,2:27,6] 66 51(x)[27,7:27,8] 65[26,11:28,3] 51(x)[26,15:26,16] 38 | 51(a)[30,0:30,1] 39 | Next statements: 51(foo)[30,2:30,5] 40 | Root: 66 52 41 | Next statements: 51(c)[30,9:30,10] 42 | Root: 66 43 | Next statements: 51(d)[30,11:30,12] 44 | Root: 66 45 | Condition: 51(puts)[32,2:32,6] 66 51(x)[32,7:32,8] 65[30,13:33,3] 51(x)[31,3:31,4] 46 | 51(a)[35,0:35,1] 47 | Next statements: 51(foo)[35,2:35,5] 48 | Root: 66 52 49 | Next statements: 51(c)[35,9:35,10] 50 | Root: 66 51 | Next statements: 51(d)[35,11:35,12] 52 | Root: 66 52 53 | Next statements: 52 54 | Root: 55 | Condition: 51(puts)[37,2:37,6] 66 51(x)[37,7:37,8] 65[35,18:38,3] 51(x)[36,3:36,4] 56 | 51(a)[40,0:40,1] 57 | Next statements: 51(foo)[40,2:40,5] 58 | Root: 66 59 | Condition: 65[40,6:41,3] 51(x)[40,10:40,11] 60 | Next statements: 51(y)[40,13:40,14] 51(z)[40,17:40,18] 61 | Root: 62 | 53(a)[43,2:43,3] 51 52 63 | Next statements: 51 64 | Root: 64 65 | Next statements: 51(each)[43,15:43,19] 66 | Root: 66 67 | Condition: 65[43,20:44,3] 51(x)[43,24:43,25] 68 | Next statements: 51(y)[43,27:43,28] 69 | Root: 70 | 52 71 | Next statements: 51(times)[46,2:46,7] 72 | Root: 66 73 | Condition: 51(puts)[46,10:46,14] 66 60 65[46,8:46,55] 74 | 51(foo)[48,0:48,3] 66 75 | Condition: 65[48,4:49,3] 51(x)[48,8:48,9] 22 52 76 | 51(foo)[51,0:51,3] 66 77 | Condition: 65[51,4:52,3] 51(x)[51,8:51,9] 22 52 78 | Next statements: 51(y)[51,16:51,17] 79 | Root: 80 | 51(foo)[54,0:54,3] 66 81 | Condition: 65[54,4:55,3] 51 82 | 51(foo)[57,0:57,3] 66 83 | Condition: 65[57,4:58,3] 51(x)[57,8:57,9] 84 | Next statements: 51(y)[57,12:57,13] 85 | Root: 86 | 51(foo)[60,0:60,3] 66 87 | Condition: 65[60,4:61,3] 51(x)[60,8:60,9] 88 | Next statements: 22 51(z)[60,18:60,19] 89 | Root: 90 | 51(a)[63,0:63,1] 66 91 | Condition: 63 65[63,2:63,6] 92 | 93 | 94 | -------------------------------------------------------------------------------- /parser/tools/tests/case.rb: -------------------------------------------------------------------------------- 1 | num = 5 2 | case 3 | when num % 2 == 0 then :a 4 | when num % 3 == 0 then :b 5 | else :c 6 | end 7 | 8 | n = case 9 | when num % 2 == 0 then :a 10 | when num % 3 == 0 then :b 11 | else :c 12 | end 13 | 14 | case num 15 | when 2 then :a 16 | when 3 then :b 17 | end 18 | 19 | case a 20 | when :text 21 | return 1 22 | =begin 23 | 24 | =end 25 | end 26 | -------------------------------------------------------------------------------- /parser/tools/tests/case.txt: -------------------------------------------------------------------------------- 1 | Resulting AST's: 2 | 51(num)[1,0:1,3] 22 52 3 | 53(a)[3,25:3,27] 43 53(b)[4,25:4,27] 43 53(c)[5,7:5,9] 38 42 4 | 51(n)[8,0:8,1] 22 53(a)[9,25:9,27] 43 53(b)[10,25:10,27] 43 53(c)[11,7:11,9] 38 42 5 | 53(a)[15,14:15,16] 43 53(b)[16,14:16,16] 43 42 6 | Condition: 51(num)[14,5:14,8] 7 | 52 72 43 42 8 | Condition: 51(a)[19,5:19,6] 9 | 10 | 11 | -------------------------------------------------------------------------------- /parser/tools/tests/class.rb: -------------------------------------------------------------------------------- 1 | class FooClass 2 | def foo 3 | end 4 | end 5 | 6 | class FooFooClass < FooClass 7 | def foofoo 8 | end 9 | end 10 | 11 | f = FooClass.new 12 | puts f.foo 13 | 14 | class << (a = 0) 15 | def foo 16 | 'Modified' 17 | end 18 | end 19 | 20 | puts f.foo 21 | 22 | class << { a: 3 } 23 | def foo 24 | 'Modified2' 25 | end 26 | end 27 | 28 | puts f.foo 29 | 30 | class 31 | << f 32 | def foo 33 | 'Modified3' 34 | end 35 | end 36 | 37 | puts f.foo 38 | 39 | class Lalala < ::FooClass 40 | end 41 | 42 | class Klass 43 | def self.foo(str) 44 | { 'result' => str } 45 | end 46 | end 47 | 48 | class Gem::Package 49 | end 50 | 51 | class Gem::Package::TarReader 52 | end 53 | -------------------------------------------------------------------------------- /parser/tools/tests/class.txt: -------------------------------------------------------------------------------- 1 | Resulting AST's: 2 | 54[3,0:3,2] 55 54[2,0:4,0] 57 51(FooClass)[1,6:1,14] 3 | 54[8,0:8,2] 55 54[7,0:9,0] 57 51(FooFooClass)[6,6:6,17] 4 | Condition: 51(FooClass)[6,20:6,28] 5 | 51(f)[11,0:11,1] 22 51(FooClass)[11,4:11,12] 6 | Next statements: 51(new)[11,13:11,16] 7 | Root: 66 8 | 51(puts)[12,0:12,4] 66 51(f)[12,5:12,6] 9 | Next statements: 51(foo)[12,7:12,10] 10 | Root: 66 11 | 60 54[16,0:17,2] 55 54[15,0:18,0] 58 51(a)[14,10:14,11] 22 52 12 | 51(puts)[20,0:20,4] 66 51(f)[20,5:20,6] 13 | Next statements: 51(foo)[20,7:20,10] 14 | Root: 66 15 | 60 54[24,0:25,2] 55 54[23,0:26,0] 58 53(a)[22,11:22,12] 51 52 64 16 | 51(puts)[28,0:28,4] 66 51(f)[28,5:28,6] 17 | Next statements: 51(foo)[28,7:28,10] 18 | Root: 66 19 | 60 54[33,0:34,2] 55 54[32,0:35,0] 58 51(f)[31,5:31,6] 20 | 51(puts)[37,0:37,4] 66 51(f)[37,5:37,6] 21 | Next statements: 51(foo)[37,7:37,10] 22 | Root: 66 23 | 54[40,0:40,0] 57 51(Lalala)[39,6:39,12] 24 | Condition: 51(FooClass)[39,17:39,25] 25 | 60 51 51(str)[44,18:44,21] 64 54[43,19:45,2] 55 51(str)[43,15:43,18] 54[43,0:46,0] 57 51(Klass)[42,6:42,11] 26 | 54[49,0:49,0] 57 51(Gem)[48,6:48,9] 27 | Next statements: 51(Package)[48,11:48,18] 28 | Root: 29 | 54[52,0:52,0] 57 51(Gem)[51,6:51,9] 30 | Next statements: 51(Package)[51,11:51,18] 31 | Root: 66 32 | Next statements: 51(TarReader)[51,20:51,29] 33 | Root: 34 | 35 | 36 | -------------------------------------------------------------------------------- /parser/tools/tests/comment.rb: -------------------------------------------------------------------------------- 1 | # This is a single line comment 2 | a = 0 3 | # It can be followed 4 | # by more single-line comments though 5 | b = 0 6 | =begin 7 | However, If you want to do so, it's 8 | better to use multi-line comments. 9 | =end 10 | c = 0 11 | # Just a comment at the end -------------------------------------------------------------------------------- /parser/tools/tests/comment.txt: -------------------------------------------------------------------------------- 1 | Resulting AST's: 2 | 51(a)[2,0:2,1] 22 52 3 | 51(b)[5,0:5,1] 22 52 4 | 51(c)[10,0:10,1] 22 52 5 | 6 | 7 | -------------------------------------------------------------------------------- /parser/tools/tests/comments/expected.txt: -------------------------------------------------------------------------------- 1 | 2 | However, now we're talking about a documentation comment. 3 | We want to store this comment 4 | 5 | This is also a documentation comment, store it! 6 | 7 | I'm a useful comment 8 | But this one is not 9 | Store this comment 10 | and this one too. 11 | This is more documentation 12 | and more, and more 13 | testing a regression 14 | no blank 15 | -------------------------------------------------------------------------------- /parser/tools/tests/comments/test.rb: -------------------------------------------------------------------------------- 1 | # 2 | # This comment will be ignored by the parser. 3 | # 4 | # This program is free software: you can redistribute it and/or modify 5 | # it under the terms of the GNU General Public License as published by 6 | # the Free Software Foundation, either version 3 of the License, or 7 | # (at your option) any later version. 8 | # 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | # GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License 15 | # along with this program. If not, see . 16 | 17 | 18 | # This comment is not useful. 19 | if ARGV[0].nil 20 | exit 21 | end 22 | 23 | ## 24 | # However, now we're talking about a documentation comment. 25 | # We want to store this comment 26 | class Klass 27 | # There's nothing to do here, therefore this comment will 28 | # not be stored. 29 | end 30 | 31 | # 32 | # This is also a documentation comment, store it! 33 | # 34 | class Clas < Klass 35 | # I'm a useful comment 36 | def foo; end 37 | 38 | # this is useless 39 | 40 | # But this one is not 41 | def foo1; end 42 | end 43 | 44 | # Store this comment 45 | module Aa 46 | # and this one too. 47 | module Bb 48 | end 49 | 50 | # This is more documentation 51 | # and more, and more 52 | # testing a regression 53 | #no blank 54 | def foo 55 | end 56 | 57 | # but not this one. 58 | end 59 | -------------------------------------------------------------------------------- /parser/tools/tests/errors/from18to19.rb: -------------------------------------------------------------------------------- 1 | a = { b: 'asd' } 2 | -> { puts 'Hello World!' } 3 | 3.times do|y;x| 4 | puts "Looping #{y}" 5 | x = y 6 | end 7 | -------------------------------------------------------------------------------- /parser/tools/tests/errors/from19to20.rb: -------------------------------------------------------------------------------- 1 | def function(a, b: {}) 2 | end 3 | 4 | def foo(a: '', b: '') 5 | puts "#{a}, #{b}" 6 | puts args 7 | end 8 | 9 | foo(a: 1, b: 2, 'asd' => 1) 10 | 11 | def another(a, *b, c: '') 12 | end 13 | 14 | def yet_another(a, b = 1, *c, d: '', **e, &blk) 15 | end 16 | 17 | %i{ sym a_sym } 18 | -------------------------------------------------------------------------------- /parser/tools/tests/errors/from20to21.rb: -------------------------------------------------------------------------------- 1 | 2 | a = 123i 3 | b = 123r 4 | 5 | -------------------------------------------------------------------------------- /parser/tools/tests/except.rb: -------------------------------------------------------------------------------- 1 | begin 2 | a = 0 3 | end 4 | 5 | begin 6 | a = 0 7 | rescue NameError 8 | c = 0 9 | end 10 | 11 | begin 12 | a = 0 13 | rescue NameError 14 | c = 0 15 | rescue ZeroDivisionError 16 | d = 0 17 | end 18 | 19 | begin 20 | a = 0 21 | else 22 | d = 0 23 | end 24 | 25 | begin 26 | a = 0 27 | ensure 28 | d = 1 29 | end 30 | 31 | begin 32 | a = 0 33 | else 34 | c = 0 35 | ensure 36 | d = 0 37 | end 38 | 39 | begin 40 | a = 0 41 | rescue ZeroDivisionError 42 | b = 0 43 | else 44 | a = 0 45 | ensure 46 | c = 0 47 | end 48 | 49 | begin 50 | a = 1 51 | c = 0 52 | a /= c 53 | rescue ZeroDivisionError => e 54 | b = 1 55 | rescue NameError then 56 | c += 1 57 | rescue RuntimeError 58 | puts 'lalala' 59 | else 60 | d = 0 61 | ensure 62 | a = 0 63 | end 64 | 65 | begin 66 | 1/0 67 | rescue ZeroDivisionError, NameError => m 68 | puts e.message 69 | end 70 | 71 | begin 72 | rescue => ex 73 | 1 74 | end 75 | 76 | begin 77 | return 78 | rescue FTPPermError => e 79 | end 80 | 81 | begin 82 | rescue *EXCEPTIONS 83 | end 84 | -------------------------------------------------------------------------------- /parser/tools/tests/except.txt: -------------------------------------------------------------------------------- 1 | Resulting AST's: 2 | 51(a)[2,2:2,3] 22 52 54[1,5:3,0] 47 3 | 51(a)[6,2:6,3] 22 52 54[5,5:9,0] 51(NameError)[7,7:7,16] 48 49 51(c)[8,2:8,3] 22 52 47 4 | 51(a)[12,2:12,3] 22 52 54[11,5:17,0] 51(NameError)[13,7:13,16] 48 49 51(c)[14,2:14,3] 22 52 47 5 | 51(a)[20,2:20,3] 22 52 54[19,5:23,0] 47 6 | 51(a)[26,2:26,3] 22 52 54[25,5:29,0] 47 7 | Ensure: 51(d)[28,2:28,3] 22 52 50 8 | 51(a)[32,2:32,3] 22 52 54[31,5:37,0] 47 9 | Condition: 51(c)[34,2:34,3] 22 52 38 10 | Ensure: 51(d)[36,2:36,3] 22 52 50 11 | 51(a)[40,2:40,3] 22 52 54[39,5:47,0] 51(ZeroDivisionError)[41,7:41,24] 48 49 51(b)[42,2:42,3] 22 52 47 12 | Condition: 51(a)[44,2:44,3] 22 52 38 13 | Ensure: 51(c)[46,2:46,3] 22 52 50 14 | 51(a)[50,2:50,3] 22 52 15 | Next statements: 22 23 16 | Root: 54[49,5:63,0] 51(ZeroDivisionError)[53,7:53,24] 48 51(e)[53,28:53,29] 49 51(b)[54,2:54,3] 22 52 47 17 | Condition: 51(d)[60,2:60,3] 22 52 38 18 | Ensure: 51(a)[62,2:62,3] 22 52 50 19 | 52 6 52 54[65,5:69,0] 51(ZeroDivisionError)[67,7:67,24] 20 | Next statements: 51(NameError)[67,26:67,35] 21 | Root: 48 51(m)[67,39:67,40] 49 51(puts)[68,2:68,6] 66 51(e)[68,7:68,8] 22 | Next statements: 51(message)[68,9:68,16] 23 | Root: 66 47 24 | 54[71,5:74,0] 48 51(ex)[72,10:72,12] 49 52 47 25 | 72 54[76,5:79,0] 51(FTPPermError)[78,7:78,19] 48 51(e)[78,23:78,24] 49 47 26 | 54[81,5:83,0] 51(EXCEPTIONS)[82,8:82,18] 48 49 47 27 | 28 | 29 | -------------------------------------------------------------------------------- /parser/tools/tests/for.rb: -------------------------------------------------------------------------------- 1 | a = 0 2 | for i in (1..10) do 3 | a += 1 4 | end 5 | 6 | for i in (1...10) 7 | a += 1 8 | end 9 | 10 | for i, j in {a: 'hola', b: 'adeu'} 11 | puts "Primer: #{i}, Segon: #{j}" 12 | end 13 | 14 | for i, j in (1..10) do 15 | puts i 16 | end 17 | -------------------------------------------------------------------------------- /parser/tools/tests/for.txt: -------------------------------------------------------------------------------- 1 | Resulting AST's: 2 | 51(a)[1,0:1,1] 22 52 3 | 51(a)[3,2:3,3] 23 52 46 51(i)[2,4:2,5] 4 | Condition: 52 35 52 5 | 51(a)[7,2:7,3] 23 52 46 51(i)[6,4:6,5] 6 | Condition: 52 36 52 7 | 51(puts)[11,2:11,6] 66 51(i)[11,18:11,19] 8 | Next statements: 51(j)[11,31:11,32] 9 | Root: 60 46 51(i)[10,4:10,5] 10 | Next statements: 51(j)[10,7:10,8] 11 | Root: 12 | Condition: 53(a)[10,13:10,14] 51 60 13 | Next statements: 51 14 | Root: 64 15 | 51(puts)[15,2:15,6] 66 51(i)[15,7:15,8] 46 51(i)[14,4:14,5] 16 | Next statements: 51(j)[14,7:14,8] 17 | Root: 18 | Condition: 52 35 52 19 | 20 | 21 | -------------------------------------------------------------------------------- /parser/tools/tests/function.rb: -------------------------------------------------------------------------------- 1 | 2 | def foo? a 3 | a = 0 4 | while a < 5 5 | a += 1 6 | end 7 | rescue 8 | b = 5 9 | else 10 | c = 3 11 | ensure 12 | d = 9 13 | end 14 | 15 | def foo a, 16 | b 17 | end 18 | 19 | def foo(a, b) 20 | end 21 | 22 | def a.append_features(klass) 23 | super 24 | 25 | klass.install_must_call_validator('', ::RSS::URI) 26 | end 27 | 28 | # Singleton 29 | 30 | class Single 31 | def foo a = 2, b 32 | 25 33 | end 34 | end 35 | 36 | s = Single.new 37 | puts s.foo 38 | 39 | def s.foo a = 2 40 | 20 41 | end 42 | 43 | puts s.foo 44 | 45 | # Defining functions with a weird argument list 46 | 47 | def aa a, b, c 48 | end 49 | 50 | def bb a = 1, b = 2, c = 3 51 | end 52 | 53 | def funny *a, c, b, &d 54 | end 55 | 56 | def jolly a = 0, b = 1, c, d, &e 57 | end 58 | 59 | def fuck! a = 0, b = 1, *c, d, e, &f 60 | end 61 | 62 | def nice a = 0, b = 1, *c, &d 63 | end 64 | 65 | def yeah! a, b, c = 1, d = 2, e, f, &g 66 | end 67 | 68 | def head_shot! a, b, c = 1, d = 2, *e, f, g, &h 69 | end 70 | 71 | def final a, b, c = 1, d = 2, *e, &h 72 | end 73 | 74 | def == other 75 | end 76 | 77 | def another(a=1) 78 | end 79 | 80 | def a.b=(val) 81 | end 82 | 83 | def initialize parent=nil 84 | end 85 | 86 | def `(p1) 87 | end 88 | 89 | def self.[]; end 90 | 91 | class A 92 | end 93 | 94 | def <<(obj) 95 | log(INFO, obj.to_s) 96 | end 97 | 98 | def %(x) 99 | end 100 | 101 | def foo a, *; end 102 | -------------------------------------------------------------------------------- /parser/tools/tests/function.txt: -------------------------------------------------------------------------------- 1 | Resulting AST's: 2 | 51(a)[3,2:3,3] 22 52 3 | Next statements: 40 4 | Root: 54[3,0:13,0] 49 51(b)[8,2:8,3] 22 52 55 51(a)[2,9:2,10] 5 | Condition: 51(foo?)[2,4:2,8] 6 | Condition: 51(c)[10,2:10,3] 22 52 38 7 | Ensure: 51(d)[12,2:12,3] 22 52 50 8 | 54[17,0:17,0] 55 51(a)[15,8:15,9] 9 | Next statements: 51(b)[16,4:16,5] 10 | Root: 11 | Condition: 51(foo)[15,4:15,7] 12 | 54[19,13:20,0] 55 51(a)[19,8:19,9] 13 | Next statements: 51(b)[19,11:19,12] 14 | Root: 15 | Condition: 51(foo)[19,4:19,7] 16 | 59 17 | Next statements: 66 18 | Root: 54[22,28:26,0] 55 51(klass)[22,22:22,27] 19 | Condition: 51(a)[22,4:22,5] 51 51(append_features)[22,6:22,21] 20 | 52 54[32,0:33,2] 55 51(a)[31,10:31,11] 22 52 21 | Next statements: 51(b)[31,17:31,18] 22 | Root: 54[31,0:34,0] 57 51(Single)[30,6:30,12] 23 | 51(s)[36,0:36,1] 22 51(Single)[36,4:36,10] 24 | Next statements: 51(new)[36,11:36,14] 25 | Root: 66 26 | 51(puts)[37,0:37,4] 66 51(s)[37,5:37,6] 27 | Next statements: 51(foo)[37,7:37,10] 28 | Root: 66 29 | 52 54[40,0:41,0] 55 51(a)[39,10:39,11] 22 52 30 | Condition: 51(s)[39,4:39,5] 51 51(foo)[39,6:39,9] 31 | 51(puts)[43,0:43,4] 66 51(s)[43,5:43,6] 32 | Next statements: 51(foo)[43,7:43,10] 33 | Root: 66 34 | 54[48,0:48,0] 55 51(a)[47,7:47,8] 35 | Next statements: 51(b)[47,10:47,11] 51(c)[47,13:47,14] 36 | Root: 37 | Condition: 51(aa)[47,4:47,6] 38 | 54[51,0:51,0] 55 51(a)[50,7:50,8] 22 52 39 | Next statements: 22 22 40 | Root: 41 | Condition: 51(bb)[50,4:50,6] 42 | 54[54,0:54,0] 55 51(a)[53,11:53,12] 43 | Next statements: 51(c)[53,14:53,15] 51(b)[53,17:53,18] 51(d)[53,21:53,22] 44 | Root: 45 | Condition: 51(funny)[53,4:53,9] 46 | 54[57,0:57,0] 55 51(a)[56,10:56,11] 22 52 47 | Next statements: 22 51(c)[56,24:56,25] 51(d)[56,27:56,28] 51(e)[56,31:56,32] 48 | Root: 49 | Condition: 51(jolly)[56,4:56,9] 50 | 54[60,0:60,0] 55 51(a)[59,10:59,11] 22 52 51 | Next statements: 22 51(c)[59,25:59,26] 51(d)[59,28:59,29] 51(e)[59,31:59,32] 51(f)[59,35:59,36] 52 | Root: 53 | Condition: 51(fuck!)[59,4:59,9] 54 | 54[63,0:63,0] 55 51(a)[62,9:62,10] 22 52 55 | Next statements: 22 51(c)[62,24:62,25] 51(d)[62,28:62,29] 56 | Root: 57 | Condition: 51(nice)[62,4:62,8] 58 | 54[66,0:66,0] 55 51(a)[65,10:65,11] 59 | Next statements: 51(b)[65,13:65,14] 22 22 51(e)[65,30:65,31] 51(f)[65,33:65,34] 51(g)[65,37:65,38] 60 | Root: 61 | Condition: 51(yeah!)[65,4:65,9] 62 | 54[69,0:69,0] 55 51(a)[68,15:68,16] 63 | Next statements: 51(b)[68,18:68,19] 22 22 51(e)[68,36:68,37] 51(f)[68,39:68,40] 51(g)[68,42:68,43] 51(h)[68,46:68,47] 64 | Root: 65 | Condition: 51(head_shot!)[68,4:68,14] 66 | 54[72,0:72,0] 55 51(a)[71,10:71,11] 67 | Next statements: 51(b)[71,13:71,14] 22 22 51(e)[71,31:71,32] 51(h)[71,35:71,36] 68 | Root: 69 | Condition: 51(final)[71,4:71,9] 70 | 54[75,0:75,0] 55 51(other)[74,7:74,12] 71 | Condition: 51(==)[74,4:74,6] 72 | 54[77,16:78,0] 55 51(a)[77,12:77,13] 22 52 73 | Condition: 51(another)[77,4:77,11] 74 | 54[80,13:81,0] 55 51(val)[80,9:80,12] 75 | Condition: 51(a)[80,4:80,5] 51 51(b=)[80,6:80,8] 76 | 54[84,0:84,0] 55 51(parent)[83,15:83,21] 22 81 77 | Condition: 51(initialize)[83,4:83,14] 78 | 54[86,9:87,0] 55 51(p1)[86,6:86,8] 79 | Condition: 51(`)[86,4:86,5] 80 | 54[89,12:89,13] 55 81 | Condition: 82 51 51([])[89,9:89,11] 82 | 54[92,0:92,0] 57 51(A)[91,6:91,7] 83 | 51(log)[95,2:95,5] 66 51(INFO)[95,6:95,10] 84 | Next statements: 66 85 | Root: 54[94,11:96,0] 55 51(obj)[94,7:94,10] 86 | Condition: 51(<<)[94,4:94,6] 87 | 54[98,8:99,0] 55 51(x)[98,6:98,7] 88 | Condition: 51(%)[98,4:98,5] 89 | 54[101,13:101,14] 55 51(a)[101,8:101,9] 90 | Next statements: 51 91 | Root: 92 | Condition: 51(foo)[101,4:101,7] 93 | 94 | 95 | -------------------------------------------------------------------------------- /parser/tools/tests/global.rb: -------------------------------------------------------------------------------- 1 | $: << File.expand_path(File.dirname(__FILE__) + 'lib') 2 | 3 | $global = 0 4 | if $-a 5 | puts '-a option is set' 6 | end 7 | 8 | begin 9 | 1/0 10 | rescue 11 | puts $! 12 | end 13 | 14 | # (global) vars starting with $ 15 | $! 16 | $@ 17 | $; 18 | $, 19 | $/ 20 | $\ 21 | $. 22 | $_ 23 | $> 24 | $< 25 | $$ 26 | $? 27 | $~ 28 | $= # deprecated 29 | $* 30 | $& 31 | $` 32 | $' 33 | $+ 34 | 35 | a = $120 36 | -------------------------------------------------------------------------------- /parser/tools/tests/global.txt: -------------------------------------------------------------------------------- 1 | Resulting AST's: 2 | 51($:)[1,0:1,2] 16 51(File)[1,6:1,10] 3 | Next statements: 51(expand_path)[1,11:1,22] 4 | Root: 66 51(File)[1,23:1,27] 5 | Next statements: 51(dirname)[1,28:1,35] 6 | Root: 66 84 2 60 7 | 51($global)[3,0:3,7] 22 52 8 | 51(puts)[5,2:5,6] 66 60 38 9 | Condition: 51($-a)[4,3:4,6] 10 | 52 6 52 54[8,5:12,0] 49 51(puts)[11,2:11,6] 66 51($!)[11,7:11,9] 47 11 | 51($!)[15,0:15,2] 12 | 51($@)[16,0:16,2] 13 | 51($;)[17,0:17,2] 14 | 51($,)[18,0:18,2] 15 | 51($/)[19,0:19,2] 16 | 51($\)[20,0:20,2] 17 | 51($.)[21,0:21,2] 18 | 51($_)[22,0:22,2] 19 | 51($>)[23,0:23,2] 20 | 51($<)[24,0:24,2] 21 | 51($$)[25,0:25,2] 22 | 51($?)[26,0:26,2] 23 | 51($~)[27,0:27,2] 24 | 51($=)[28,0:28,2] 25 | 51($*)[29,0:29,2] 26 | 51($&)[30,0:30,2] 27 | 51($`)[31,0:31,2] 28 | 51($')[32,0:32,2] 29 | 51($+)[33,0:33,2] 30 | 51(a)[35,0:35,1] 22 51($120)[35,4:35,8] 31 | 32 | 33 | -------------------------------------------------------------------------------- /parser/tools/tests/hash.rb: -------------------------------------------------------------------------------- 1 | a = {:a => 'hola', :b => 'adeu'} 2 | b = {c: 'hola', d: 'adios'} 3 | c = {:e => 'hello', f: 'bye'} 4 | 5 | a = { :a => 6 | 1, 7 | :b => 2} 8 | a = { :a => 9 | 1, 10 | :b => 2 11 | } 12 | a = { 13 | :a => 14 | 1, 15 | :b => 2 16 | } 17 | a = { 18 | a: 19 | 1, 20 | :b => 2 21 | } 22 | d = {:a => 'aa'} 23 | { 'UNIX' => '/', 'WINDOWS' => "\\", 'MACINTOSH' => ':' } 24 | @options={:accept_charset=>@@accept_charset} 25 | -------------------------------------------------------------------------------- /parser/tools/tests/hash.txt: -------------------------------------------------------------------------------- 1 | Resulting AST's: 2 | 51(a)[1,0:1,1] 22 53(a)[1,5:1,7] 51 60 3 | Next statements: 51 4 | Root: 64 5 | 51(b)[2,0:2,1] 22 53(c)[2,5:2,6] 51 60 6 | Next statements: 51 7 | Root: 64 8 | 51(c)[3,0:3,1] 22 53(e)[3,5:3,7] 51 60 9 | Next statements: 51 10 | Root: 64 11 | 51(a)[5,0:5,1] 22 53(a)[5,6:5,8] 51 52 12 | Next statements: 51 13 | Root: 64 14 | 51(a)[8,0:8,1] 22 53(a)[8,6:8,8] 51 52 15 | Next statements: 51 16 | Root: 64 17 | 51(a)[12,0:12,1] 22 53(a)[13,2:13,4] 51 52 18 | Next statements: 51 19 | Root: 64 20 | 51(a)[17,0:17,1] 22 53(a)[18,2:18,3] 51 52 21 | Next statements: 51 22 | Root: 64 23 | 51(d)[22,0:22,1] 22 53(a)[22,5:22,7] 51 60 64 24 | 60 51 60 25 | Next statements: 51 51 26 | Root: 64 27 | 51(@options)[24,0:24,8] 22 53(accept_charset)[24,10:24,25] 51 51(@@accept_charset)[24,27:24,43] 64 28 | 29 | 30 | -------------------------------------------------------------------------------- /parser/tools/tests/heredoc.rb: -------------------------------------------------------------------------------- 1 | a = < 17 | 18 | #{HTMLUtils::escape(@reason_phrase)} 19 | 20 |

#{HTMLUtils::escape(@reason_phrase)}

21 | #{HTMLUtils::escape(ex.message)} 22 |
23 | _end_of_html_ 24 | 25 | msg = <<"MSGEND" 26 | 27 | 28 | #{err} 29 | 30 | 31 |

#{err}

32 |

Unexpected error occured while processing XML-RPC request!

33 | 34 | 35 | MSGEND 36 | 37 | msg = <<-"MSGEND" 38 | 39 | 40 | #{err} 41 | 42 | 43 |

#{err}

44 |

Unexpected error occured while processing XML-RPC request!

45 | 46 | 47 | MSGEND 48 | 49 | modul_eval(<<-asd, __FILE__, __LINE__ + 1) 50 | def #{name} 51 | #{val} 52 | end 53 | asd 54 | 55 | < a 16 | c = 1 17 | else 18 | b = 5 19 | end 20 | 21 | if b == c 22 | a += 1 23 | elsif b > a 24 | then c = 1 25 | else 26 | b = 5 27 | end 28 | 29 | if b == c 30 | then 31 | a += 1 32 | elsif b > a then 33 | c = 1 34 | else 35 | b = 5 36 | end 37 | 38 | if b == c then a += 1 39 | elsif (b > a) then c = 1 40 | else b = 5 41 | end 42 | 43 | if name !~ /[a-zA-Z0-9_.:\/]+/ 44 | raise ArgumentError, "Wrong XML-RPC method-name" 45 | end 46 | 47 | if param >= -(2**31) and param <= (2**31-1) 48 | end 49 | 50 | if a and 51 | n 52 | end 53 | 54 | if /^(\d+)\.(\d+)$/ =~ version 55 | @major, @minor = $1.to_i, $2.to_i 56 | end 57 | 58 | if (ret = @major <=> other.major) == 0 59 | return @minor <=> other.minor 60 | end 61 | 62 | if(@req) 63 | a = 0 64 | end 65 | -------------------------------------------------------------------------------- /parser/tools/tests/ifelse.txt: -------------------------------------------------------------------------------- 1 | Resulting AST's: 2 | 51(a)[1,0:1,1] 22 52 3 | 51(b)[2,0:2,1] 22 51(a)[2,4:2,5] 4 | 51(c)[3,0:3,1] 22 52 5 | 51(b)[6,2:6,3] 22 52 6 | Next statements: 23 38 7 | Root: 39 8 | Condition: 51(a)[5,7:5,8] 26 52 9 | 51(a)[14,2:14,3] 23 52 38 51(c)[16,2:16,3] 22 52 38 51(b)[18,2:18,3] 22 52 38 10 | Condition: 51(b)[13,3:13,4] 26 51(c)[13,8:13,9] 11 | 51(a)[22,2:22,3] 23 52 38 51(c)[24,7:24,8] 22 52 38 51(b)[26,2:26,3] 22 52 38 12 | Condition: 51(b)[21,3:21,4] 26 51(c)[21,8:21,9] 13 | 51(a)[31,2:31,3] 23 52 38 51(c)[33,2:33,3] 22 52 38 51(b)[35,2:35,3] 22 52 38 14 | Condition: 51(b)[29,3:29,4] 26 51(c)[29,8:29,9] 15 | 51(a)[38,15:38,16] 23 52 38 51(c)[39,19:39,20] 22 52 38 51(b)[40,5:40,6] 22 52 38 16 | Condition: 51(b)[38,3:38,4] 26 51(c)[38,8:38,9] 17 | 51(raise)[44,2:44,7] 66 51(ArgumentError)[44,8:44,21] 18 | Next statements: 60 19 | Root: 38 20 | Condition: 51(name)[43,3:43,7] 30 61 21 | 38 22 | Condition: 51(param)[47,3:47,8] 32 52 5 52 21 11 51(param)[47,25:47,30] 34 52 5 52 3 52 23 | 38 24 | Condition: 51(a)[50,3:50,4] 11 51(n)[51,4:51,5] 25 | 51(@major)[55,2:55,8] 26 | Next statements: 51(@minor)[55,10:55,16] 27 | Root: 22 51($1)[55,19:55,21] 28 | Next statements: 51(to_i)[55,22:55,26] 29 | Root: 66 30 | Next statements: 66 31 | Root: 38 32 | Condition: 61 29 51(version)[54,23:54,30] 33 | 51(@minor)[59,9:59,15] 25 51(other)[59,20:59,25] 34 | Next statements: 51(minor)[59,26:59,31] 35 | Root: 66 72 38 36 | Condition: 51(ret)[58,4:58,7] 22 51(@major)[58,10:58,16] 25 51(other)[58,21:58,26] 37 | Next statements: 51(major)[58,27:58,32] 38 | Root: 66 26 52 39 | 51(a)[63,2:63,3] 22 52 38 40 | Condition: 51(@req)[62,3:62,7] 41 | 42 | 43 | -------------------------------------------------------------------------------- /parser/tools/tests/method_call.rb: -------------------------------------------------------------------------------- 1 | $:.unshift('this_freakingly_awesome_path') 2 | 3 | module Dummy 4 | module BA 5 | def inject(n) 6 | each { |value| n = yield(n, value) } 7 | n 8 | end 9 | 10 | def BA.greeting str 11 | "Hello #{str}!" 12 | end 13 | 14 | def BA.want_a_block(&mblock) 15 | yield mblock 16 | end 17 | 18 | CONST = 0 19 | end 20 | end 21 | 22 | module AA 23 | include ::Dummy::BA 24 | 25 | def sum(initial = 0) 26 | inject(initial) { |n, value| n + value } 27 | end 28 | 29 | ACONST = 1 30 | end 31 | 32 | class Range 33 | include AA 34 | end 35 | 36 | puts (1..5).sum 37 | puts Dummy::BA::CONST, ::AA::ACONST 38 | puts(Dummy::BA::CONST, ::AA::ACONST) 39 | puts 'lalala', Dummy::BA.greeting('Miquel') 40 | puts('lalala', Dummy::BA.greeting('Miquel')) 41 | puts "Where is thumbkin?", Dummy::BA.want_a_block { 'Here I am!' } 42 | puts("Where is thumbkin?", Dummy::BA.want_a_block { 'Here I am!' }) 43 | puts %Q{ lalala }.length 44 | 45 | __inspect__.sub("Chameleon", method.to_s.sub('to_','').capitalize) 46 | method.to_s.sub('to_','').capitalize 47 | b.a(1).c 48 | a.b.c 1, 2 49 | puts 1+1 50 | 51 | a.class 52 | foo 1, 53 | 2 54 | 55 | foo a, :a => 'string', b: 'another' 56 | where_is_thumbkin? && here_i_am! 57 | 58 | class Klass 59 | def self.foo(str) 60 | { 'result' => str } 61 | end 62 | end 63 | 64 | puts Klass.foo('lala')['result'] 65 | 66 | def moo(a, b) 67 | yield if block_given? 68 | end 69 | 70 | require 'rubygems' 71 | 72 | Gem::Specification::new do |spec| 73 | end 74 | 75 | open a do |os| 76 | loop do 77 | a 78 | end 79 | end 80 | 81 | remove_method(:alternate=) 82 | -------------------------------------------------------------------------------- /parser/tools/tests/method_call.txt: -------------------------------------------------------------------------------- 1 | Resulting AST's: 2 | 51($:)[1,0:1,2] 3 | Next statements: 51(unshift)[1,3:1,10] 4 | Root: 66 60 5 | 51(each)[6,6:6,10] 66 6 | Next statements: 51(n)[7,6:7,7] 7 | Root: 54[5,17:8,4] 55 51(n)[5,15:5,16] 8 | Next statements: 55 55 22 9 | Root: 54[5,0:19,2] 56 51(BA)[4,9:4,11] 54[4,0:20,0] 56 51(Dummy)[3,7:3,12] 10 | 51(include)[23,2:23,9] 66 51(Dummy)[23,12:23,17] 11 | Next statements: 51(BA)[23,19:23,21] 12 | Root: 66 13 | Next statements: 55 22 14 | Root: 54[23,0:30,0] 56 51(AA)[22,7:22,9] 15 | 51(include)[33,2:33,9] 66 51(AA)[33,10:33,12] 54[33,0:34,0] 57 51(Range)[32,6:32,11] 16 | 51(puts)[36,0:36,4] 66 52 35 52 17 | Next statements: 51(sum)[36,12:36,15] 18 | Root: 66 19 | 51(puts)[37,0:37,4] 66 51(Dummy)[37,5:37,10] 20 | Next statements: 51(BA)[37,12:37,14] 21 | Root: 66 22 | Next statements: 51(CONST)[37,16:37,21] 23 | Root: 66 24 | Next statements: 66 25 | Root: 26 | 51(puts)[38,0:38,4] 66 51(Dummy)[38,5:38,10] 27 | Next statements: 51(BA)[38,12:38,14] 28 | Root: 66 29 | Next statements: 51(CONST)[38,16:38,21] 30 | Root: 66 31 | Next statements: 66 32 | Root: 33 | 51(puts)[39,0:39,4] 66 60 34 | Next statements: 66 35 | Root: 36 | 51(puts)[40,0:40,4] 66 60 37 | Next statements: 66 38 | Root: 39 | 51(puts)[41,0:41,4] 66 60 40 | Next statements: 66 41 | Root: 42 | 51(puts)[42,0:42,4] 66 60 43 | Next statements: 66 44 | Root: 45 | 51(puts)[43,0:43,4] 66 60 46 | Next statements: 51(length)[43,18:43,24] 47 | Root: 66 48 | 51(__inspect__)[45,0:45,11] 49 | Next statements: 51(sub)[45,12:45,15] 50 | Root: 66 60 51 | Next statements: 66 52 | Root: 53 | 51(method)[46,0:46,6] 54 | Next statements: 51(to_s)[46,7:46,11] 55 | Root: 66 56 | Next statements: 51(sub)[46,12:46,15] 57 | Root: 66 60 58 | Next statements: 60 59 | Root: 60 | Next statements: 51(capitalize)[46,26:46,36] 61 | Root: 66 62 | 51(b)[47,0:47,1] 63 | Next statements: 51(a)[47,2:47,3] 64 | Root: 66 52 65 | Next statements: 51(c)[47,7:47,8] 66 | Root: 66 67 | 51(a)[48,0:48,1] 68 | Next statements: 51(b)[48,2:48,3] 69 | Root: 66 70 | Next statements: 51(c)[48,4:48,5] 71 | Root: 66 52 72 | Next statements: 52 73 | Root: 74 | 51(puts)[49,0:49,4] 66 52 2 52 75 | 51(a)[51,0:51,1] 76 | Next statements: 51(class)[51,2:51,7] 77 | Root: 66 78 | 51(foo)[52,0:52,3] 66 52 79 | Next statements: 52 80 | Root: 81 | 51(foo)[55,0:55,3] 66 51(a)[55,4:55,5] 82 | Next statements: 64 83 | Root: 84 | 51(where_is_thumbkin?)[56,0:56,18] 15 51(here_i_am!)[56,22:56,32] 85 | 60 51 51(str)[60,18:60,21] 64 54[59,19:61,2] 55 51(str)[59,15:59,18] 54[59,0:62,0] 57 51(Klass)[58,6:58,11] 86 | 51(puts)[64,0:64,4] 66 51(Klass)[64,5:64,10] 87 | Next statements: 51(foo)[64,11:64,14] 88 | Root: 66 60 77 60 89 | 73 38 54[66,13:68,0] 55 51(a)[66,8:66,9] 90 | Next statements: 51(b)[66,11:66,12] 91 | Root: 92 | Condition: 51(moo)[66,4:66,7] 93 | 51(require)[70,0:70,7] 66 60 94 | 51(Gem)[72,0:72,3] 95 | Next statements: 51(Specification)[72,5:72,18] 96 | Root: 66 97 | Next statements: 51(new)[72,20:72,23] 98 | Root: 66 99 | Condition: 65[72,24:73,3] 51(spec)[72,28:72,32] 100 | 51(open)[75,0:75,4] 66 51(a)[75,5:75,6] 101 | Condition: 51(loop)[76,2:76,6] 66 65[75,7:79,3] 51(os)[75,11:75,13] 102 | 51(remove_method)[81,0:81,13] 66 53(alternate=)[81,14:81,25] 103 | 104 | 105 | -------------------------------------------------------------------------------- /parser/tools/tests/modifiers.rb: -------------------------------------------------------------------------------- 1 | a = 0 2 | a = 1 if a == 0 3 | a += 1 unless a != 1 4 | a += 1 while a < 5 5 | a -= 1 until a == 0 6 | 7 | begin 8 | self[column] = SecureRandom.urlsafe_base64 9 | end while User.exists?(column => self[column]) 10 | 11 | a unless (1..31).include? 12 | -------------------------------------------------------------------------------- /parser/tools/tests/modifiers.txt: -------------------------------------------------------------------------------- 1 | Resulting AST's: 2 | 51(a)[1,0:1,1] 22 52 3 | 51(a)[2,0:2,1] 22 52 38 4 | Condition: 51(a)[2,9:2,10] 26 52 5 | 51(a)[3,0:3,1] 23 52 39 6 | Condition: 51(a)[3,14:3,15] 27 52 7 | 51(a)[4,0:4,1] 23 52 40 8 | Condition: 51(a)[4,13:4,14] 33 52 9 | 51(a)[5,0:5,1] 23 52 41 10 | Condition: 51(a)[5,13:5,14] 26 52 11 | 82 77 51(column)[8,7:8,13] 22 51(SecureRandom)[8,17:8,29] 12 | Next statements: 51(urlsafe_base64)[8,30:8,44] 13 | Root: 66 54[7,5:9,0] 47 40 14 | Condition: 51(User)[9,10:9,14] 15 | Next statements: 51(exists?)[9,15:9,22] 16 | Root: 66 51(column)[9,23:9,29] 51 82 77 51(column)[9,38:9,44] 64 17 | 51(a)[11,0:11,1] 39 18 | Condition: 52 35 52 19 | Next statements: 51(include?)[11,17:11,25] 20 | Root: 66 21 | 22 | 23 | -------------------------------------------------------------------------------- /parser/tools/tests/module.rb: -------------------------------------------------------------------------------- 1 | module A a = 0 2 | end 3 | 4 | module B 5 | a = 1 6 | b = 0 7 | end 8 | 9 | module C 10 | def foo 11 | a = 0 12 | end 13 | end 14 | 15 | module Foo 16 | module A 17 | def b 18 | 2 19 | end 20 | module_function :b 21 | end 22 | def a 23 | A::b 24 | end 25 | 26 | module_function :a 27 | end 28 | 29 | a = Foo::a 30 | puts a 31 | 32 | module Mod1 33 | module Mod2 34 | class A 35 | def to_s 36 | "Aigua clara de l'Anoia!" 37 | end 38 | end 39 | end 40 | end 41 | 42 | class B < Mod1::Mod2::A 43 | end 44 | 45 | puts B.new 46 | -------------------------------------------------------------------------------- /parser/tools/tests/module.txt: -------------------------------------------------------------------------------- 1 | Resulting AST's: 2 | 51(a)[1,9:1,10] 22 52 54[1,10:2,0] 56 51(A)[1,7:1,8] 3 | 51(a)[5,2:5,3] 22 52 4 | Next statements: 22 5 | Root: 54[5,0:7,0] 56 51(B)[4,7:4,8] 6 | 51(a)[11,4:11,5] 22 52 54[11,0:12,2] 55 54[10,0:13,0] 56 51(C)[9,7:9,8] 7 | 52 54[18,0:19,4] 55 8 | Next statements: 66 9 | Root: 54[17,0:21,2] 56 51(A)[16,9:16,10] 10 | Next statements: 55 66 11 | Root: 54[16,0:27,0] 56 51(Foo)[15,7:15,10] 12 | 51(a)[29,0:29,1] 22 51(Foo)[29,4:29,7] 13 | Next statements: 51(a)[29,9:29,10] 14 | Root: 66 15 | 51(puts)[30,0:30,4] 66 51(a)[30,5:30,6] 16 | 60 54[36,0:37,6] 55 54[35,0:38,4] 57 51(A)[34,10:34,11] 54[34,0:39,2] 56 51(Mod2)[33,9:33,13] 54[33,0:40,0] 56 51(Mod1)[32,7:32,11] 17 | 54[43,0:43,0] 57 51(B)[42,6:42,7] 18 | Condition: 51(Mod1)[42,10:42,14] 19 | Next statements: 51(Mod2)[42,16:42,20] 20 | Root: 66 21 | Next statements: 51(A)[42,22:42,23] 22 | Root: 66 23 | 51(puts)[45,0:45,4] 66 51(B)[45,5:45,6] 24 | Next statements: 51(new)[45,7:45,10] 25 | Root: 66 26 | 27 | 28 | -------------------------------------------------------------------------------- /parser/tools/tests/numeric.rb: -------------------------------------------------------------------------------- 1 | a = 0x1A 2 | b = 0x1a 3 | c = 0X12123 4 | d = 0b10101 5 | e = 0B101010 6 | f = 1e+1 7 | g = 1E-2 8 | h = 1_000_000 9 | i = 1_0_0_0_0 10 | j = 12i 11 | k = 123r 12 | -------------------------------------------------------------------------------- /parser/tools/tests/numeric.txt: -------------------------------------------------------------------------------- 1 | Resulting AST's: 2 | 51(a)[1,0:1,1] 22 52 3 | 51(b)[2,0:2,1] 22 52 4 | 51(c)[3,0:3,1] 22 52 5 | 51(d)[4,0:4,1] 22 52 6 | 51(e)[5,0:5,1] 22 52 7 | 51(f)[6,0:6,1] 22 52 8 | 51(g)[7,0:7,1] 22 52 9 | 51(h)[8,0:8,1] 22 52 10 | 51(i)[9,0:9,1] 22 52 11 | 51(j)[10,0:10,1] 22 52 12 | 51(k)[11,0:11,1] 22 52 13 | 14 | 15 | -------------------------------------------------------------------------------- /parser/tools/tests/operators.rb: -------------------------------------------------------------------------------- 1 | 2 | super( @source.eof? ? str : str+@source.readline( @line_break ) ) 3 | 4 | overflow = "This text should flow gracefully onto the next page, like a stream" + 5 | " flows elegantly from a mountain lake down into the village below." 6 | 7 | b = 1 8 | a = b 9 | - 1 # assign and unary 10 | a = b - 11 | 1 # just an assign 12 | 13 | a = a * 14 | b 15 | 16 | a = a % 17 | b 18 | 19 | a = b ^ 20 | 2 21 | 22 | a = b & 23 | 2 24 | 25 | a = b | 26 | 2 27 | 28 | a = b / 29 | 2.0 30 | 31 | a = b + sx ** 2 32 | 33 | ?- ? -1 : 1 34 | q = @pubid.include?('"')?"'":'"' 35 | 36 | +1.2 37 | -1.2 38 | -------------------------------------------------------------------------------- /parser/tools/tests/operators.txt: -------------------------------------------------------------------------------- 1 | Resulting AST's: 2 | 59 51(str)[2,22:2,25] 37 51(str)[2,28:2,31] 2 51(@source)[2,32:2,39] 3 | Next statements: 51(readline)[2,40:2,48] 4 | Root: 66 51(@line_break)[2,50:2,61] 5 | 51(overflow)[4,0:4,8] 22 60 2 60 6 | 51(b)[7,0:7,1] 22 52 7 | 51(a)[8,0:8,1] 22 51(b)[8,4:8,5] 8 | 52 21 9 | 51(a)[10,0:10,1] 22 51(b)[10,4:10,5] 3 52 10 | 51(a)[13,0:13,1] 22 51(a)[13,4:13,5] 4 51(b)[14,4:14,5] 11 | 51(a)[16,0:16,1] 22 51(a)[16,4:16,5] 7 51(b)[17,4:17,5] 12 | 51(a)[19,0:19,1] 22 51(b)[19,4:19,5] 10 52 13 | 51(a)[22,0:22,1] 22 51(b)[22,4:22,5] 8 52 14 | 51(a)[25,0:25,1] 22 51(b)[25,4:25,5] 9 52 15 | 51(a)[28,0:28,1] 22 51(b)[28,4:28,5] 6 52 16 | 51(a)[31,0:31,1] 22 51(b)[31,4:31,5] 2 51(sx)[31,8:31,10] 5 52 17 | 52 21 37 52 18 | Condition: 60 19 | 51(q)[34,0:34,1] 22 60 37 60 20 | 52 20 21 | 52 21 22 | 23 | 24 | -------------------------------------------------------------------------------- /parser/tools/tests/regexp.rb: -------------------------------------------------------------------------------- 1 | a / 1 2 | a = a / 1 3 | /asd/ 4 | a = / 1 / 5 | a = / \/ / 6 | a = %r[ Mon "adasdadas" /asdasda/ @a ] 7 | variable = 'variable' 8 | a = /#{variable}/ 9 | a = /#{variable}#{a}/ 10 | %r/ #{asd} asda/ 11 | path.gsub(/..\/tests\/?/, '') 12 | 13 | if ajax_method =~ /^find_user_(.+)$/ 14 | validate_user_uniqueness $1 15 | else 16 | raise NoMethodError, "Linx: '#{ajax_method}' is not a valid Ajax method!" 17 | end 18 | 19 | /asd/mo 20 | %r\asd\ 21 | %r-asd- 22 | 23 | return /IIS\/(\d+)/ 24 | 25 | a = /asd/iu 26 | a = /\A#\#$/ 27 | %r{[*?\[\{]} 28 | puts /asd/ 29 | -------------------------------------------------------------------------------- /parser/tools/tests/regexp.txt: -------------------------------------------------------------------------------- 1 | Resulting AST's: 2 | 51(a)[1,0:1,1] 6 52 3 | 51(a)[2,0:2,1] 22 51(a)[2,4:2,5] 6 52 4 | 61 5 | 51(a)[4,0:4,1] 22 61 6 | 51(a)[5,0:5,1] 22 61 7 | 51(a)[6,0:6,1] 22 61 8 | 51(variable)[7,0:7,8] 22 60 9 | 51(a)[8,0:8,1] 22 51(variable)[8,7:8,15] 61 10 | 51(a)[9,0:9,1] 22 51(variable)[9,7:9,15] 11 | Next statements: 51(a)[9,18:9,19] 12 | Root: 61 13 | 51(asd)[10,6:10,9] 61 14 | 51(path)[11,0:11,4] 15 | Next statements: 51(gsub)[11,5:11,9] 16 | Root: 66 61 17 | Next statements: 60 18 | Root: 19 | 51(validate_user_uniqueness)[14,2:14,26] 66 51($1)[14,27:14,29] 38 51(raise)[16,2:16,7] 66 51(NoMethodError)[16,8:16,21] 20 | Next statements: 60 21 | Root: 38 22 | Condition: 51(ajax_method)[13,3:13,14] 29 61 23 | 61 24 | 61 25 | 61 26 | 61 72 27 | 51(a)[25,0:25,1] 22 61 28 | 51(a)[26,0:26,1] 22 61 29 | 61 30 | 51(puts)[28,0:28,4] 66 61 31 | Line: 28, Column: 6; ambiguous first argument; put parentheses or even spaces 32 | 33 | 34 | -------------------------------------------------------------------------------- /parser/tools/tests/rocket.rb: -------------------------------------------------------------------------------- 1 | 2 | # BEGIN: TestRocket code 3 | module TestRocket 4 | extend Module.new { attr_accessor :out } 5 | 6 | def _test(a, b); send((call rescue()) ? a : b); end 7 | 8 | def +@; _show _test :_pass, :_fail end 9 | def -@; _show _test :_fail, :_pass end 10 | def ~@; _show _pend; end 11 | def !@; _show _desc; end 12 | 13 | def _show(r); (TestRocket.out || $>) << r; r end 14 | def _pass; " OK\n"; end 15 | def _fail; " FAIL @ #{source_location * ':'}\n"; end 16 | def _pend; "PENDING '#{call}' @ #{source_location * ':'}\n"; end 17 | def _desc; " FIRE '#{call}'!\n"; end 18 | end 19 | 20 | Proc.send :include, TestRocket 21 | 22 | +-> { Die.new(2) } 23 | --> { raise } 24 | +-> { 2 + 2 == 4 } 25 | +-> { raise } 26 | --> { true } 27 | ~-> { "this is a pending test" } 28 | !-> { "use this for descriptive output and to separate your test parts" } 29 | # END: TestRocket code 30 | 31 | class MagicString < String 32 | def +@ 33 | upcase 34 | end 35 | 36 | def ! 37 | swapcase 38 | end 39 | end 40 | 41 | str = MagicString.new("This is my string!") 42 | p +str # => "THIS IS MY STRING!" 43 | p !str # => "tHIS IS MY STRING!" 44 | p -str 45 | -------------------------------------------------------------------------------- /parser/tools/tests/rocket.txt: -------------------------------------------------------------------------------- 1 | Resulting AST's: 2 | 51(extend)[4,2:4,8] 66 51(Module)[4,9:4,15] 3 | Next statements: 51(new)[4,16:4,19] 4 | Root: 66 5 | Next statements: 55 55 55 55 55 55 55 55 55 55 6 | Root: 54[4,0:18,0] 56 51(TestRocket)[3,7:3,17] 7 | 51(Proc)[20,0:20,4] 8 | Next statements: 51(send)[20,5:20,9] 9 | Root: 66 53(include)[20,10:20,18] 10 | Next statements: 51(TestRocket)[20,20:20,30] 11 | Root: 12 | 66 20 13 | 66 21 14 | 66 20 15 | 66 20 16 | 66 21 17 | 66 18 18 | 66 19 19 | 51(upcase)[33,4:33,10] 54[33,0:34,2] 55 20 | Next statements: 55 21 | Root: 54[32,0:39,0] 57 51(MagicString)[31,6:31,17] 22 | Condition: 51(String)[31,20:31,26] 23 | 51(str)[41,0:41,3] 22 51(MagicString)[41,6:41,17] 24 | Next statements: 51(new)[41,18:41,21] 25 | Root: 66 60 26 | 51(p)[42,0:42,1] 66 51(str)[42,3:42,6] 20 27 | 51(p)[43,0:43,1] 66 51(str)[43,3:43,6] 19 28 | 51(p)[44,0:44,1] 66 51(str)[44,3:44,6] 21 29 | Line: 42, Column: 4; ambiguous first argument; put parentheses or even spaces 30 | Line: 44, Column: 4; ambiguous first argument; put parentheses or even spaces 31 | 32 | 33 | -------------------------------------------------------------------------------- /parser/tools/tests/ruby20.rb: -------------------------------------------------------------------------------- 1 | def function(a, b: {}) 2 | end 3 | 4 | def foo(a: '', b: '') 5 | puts "#{a}, #{b}" 6 | puts args 7 | end 8 | 9 | foo(a: 1, b: 2, 'asd' => 1) 10 | 11 | def another(a, *b, c: '') 12 | end 13 | 14 | def yet_another(a, b = 1, *c, d: '', **e, &blk) 15 | end 16 | 17 | def yay a: 1, **; end 18 | -------------------------------------------------------------------------------- /parser/tools/tests/ruby20.txt: -------------------------------------------------------------------------------- 1 | Resulting AST's: 2 | 54[1,22:2,0] 55 51(a)[1,13:1,14] 3 | Next statements: 51 4 | Root: 5 | Condition: 51(function)[1,4:1,12] 6 | 51(puts)[5,2:5,6] 66 51(a)[5,10:5,11] 7 | Next statements: 51(b)[5,16:5,17] 8 | Root: 60 9 | Next statements: 66 10 | Root: 54[4,21:7,0] 55 53(a)[4,8:4,9] 51 60 11 | Next statements: 51 12 | Root: 13 | Condition: 51(foo)[4,4:4,7] 14 | 51(foo)[9,0:9,3] 66 53(a)[9,4:9,5] 51 52 15 | Next statements: 51 51 16 | Root: 64 17 | 54[11,25:12,0] 55 51(a)[11,12:11,13] 18 | Next statements: 51(b)[11,16:11,17] 51 19 | Root: 20 | Condition: 51(another)[11,4:11,11] 21 | 54[14,47:15,0] 55 51(a)[14,16:14,17] 22 | Next statements: 22 51(c)[14,27:14,28] 51 51(e)[14,39:14,40] 51(blk)[14,43:14,46] 23 | Root: 24 | Condition: 51(yet_another)[14,4:14,15] 25 | 54[17,17:17,18] 55 53(a)[17,8:17,9] 51 52 26 | Next statements: 51 27 | Root: 28 | Condition: 51(yay)[17,4:17,7] 29 | 30 | 31 | -------------------------------------------------------------------------------- /parser/tools/tests/semicolon.rb: -------------------------------------------------------------------------------- 1 | class A; 15; end; 2 | class A; 15; end 3 | class A; def foo; 15; end; end; a = A.new; puts a.foo 4 | puts 1; puts 2 5 | while true; puts 1; end 6 | class A; def foo; end; def asd; end; end 7 | class A; def foo; 15; end; def asd; end; end 8 | module A; def foo; end; end 9 | case a; when 0; puts 1; when 1; puts 2; end 10 | -------------------------------------------------------------------------------- /parser/tools/tests/semicolon.txt: -------------------------------------------------------------------------------- 1 | Resulting AST's: 2 | 52 54[1,8:1,13] 57 51(A)[1,6:1,7] 3 | 52 54[2,8:2,13] 57 51(A)[2,6:2,7] 4 | 52 54[3,17:3,22] 55 54[3,8:3,27] 57 51(A)[3,6:3,7] 5 | 51(a)[3,32:3,33] 22 51(A)[3,36:3,37] 6 | Next statements: 51(new)[3,38:3,41] 7 | Root: 66 8 | 51(puts)[3,43:3,47] 66 51(a)[3,48:3,49] 9 | Next statements: 51(foo)[3,50:3,53] 10 | Root: 66 11 | 51(puts)[4,0:4,4] 66 52 12 | 51(puts)[4,8:4,12] 66 52 13 | 51(puts)[5,12:5,16] 66 52 40 14 | Condition: 79 15 | 54[6,17:6,18] 55 16 | Next statements: 55 17 | Root: 54[6,8:6,37] 57 51(A)[6,6:6,7] 18 | 52 54[7,17:7,22] 55 19 | Next statements: 55 20 | Root: 54[7,8:7,41] 57 51(A)[7,6:7,7] 21 | 54[8,18:8,19] 55 54[8,9:8,24] 56 51(A)[8,7:8,8] 22 | 51(puts)[9,16:9,20] 66 52 43 51(puts)[9,32:9,36] 66 52 43 42 23 | Condition: 51(a)[9,5:9,6] 24 | 25 | 26 | -------------------------------------------------------------------------------- /parser/tools/tests/simple.rb: -------------------------------------------------------------------------------- 1 | def foo 2 | return 1+1 3 | end 4 | 5 | def foo1 6 | return 1 7 | end 8 | 9 | def a 10 | puts 'el riu anoia fa pudor' 11 | end 12 | 13 | a = 0 14 | b = 0 15 | while a < 10 16 | if a == 5 && b == 0 17 | b = 1 18 | redo 19 | end 20 | next 21 | a += 1 22 | end 23 | 24 | alias foo foo1 25 | alias foo1 :a 26 | alias $ERROR_INFO $! 27 | alias mon= month= 28 | alias [] test 29 | 30 | undef :a, foo 31 | if defined? anoia 32 | puts 'a' 33 | end 34 | 35 | quoted_string =~ /^[\'\"].*[\'\"]$/ ? 36 | quoted_string[1, quoted_string.length-2] : 37 | quoted_string 38 | 39 | a = b ? \ 40 | c : 41 | d 42 | -------------------------------------------------------------------------------- /parser/tools/tests/simple.txt: -------------------------------------------------------------------------------- 1 | Resulting AST's: 2 | 52 2 52 72 54[2,0:3,0] 55 3 | Condition: 51(foo)[1,4:1,7] 4 | 52 72 54[6,0:7,0] 55 5 | Condition: 51(foo1)[5,4:5,8] 6 | 51(puts)[10,2:10,6] 66 60 54[10,0:11,0] 55 7 | Condition: 51(a)[9,4:9,5] 8 | 51(a)[13,0:13,1] 22 52 9 | 51(b)[14,0:14,1] 22 52 10 | 51(b)[17,4:17,5] 22 52 11 | Next statements: 69 12 | Root: 38 13 | Next statements: 71 23 14 | Root: 40 15 | Condition: 51(a)[15,6:15,7] 33 52 16 | 51(foo)[24,6:24,9] 74 51(foo1)[24,10:24,14] 17 | 51(foo1)[25,6:25,10] 74 53(a)[25,11:25,13] 18 | 51($ERROR_INFO)[26,6:26,17] 74 51($!)[26,18:26,20] 19 | 51(mon=)[27,6:27,10] 74 51(month=)[27,11:27,17] 20 | 51([])[28,6:28,8] 74 51(test)[28,9:28,13] 21 | 76 53(a)[30,6:30,8] 22 | Next statements: 51(foo)[30,10:30,13] 23 | Root: 24 | 51(puts)[32,2:32,6] 66 60 38 25 | Condition: 51(anoia)[31,12:31,17] 75 26 | 51(quoted_string)[36,8:36,21] 77 52 27 | Next statements: 3 28 | Root: 37 51(quoted_string)[37,8:37,21] 29 | Condition: 51(quoted_string)[35,0:35,13] 29 61 30 | 51(a)[39,0:39,1] 22 51(c)[40,8:40,9] 37 51(d)[41,8:41,9] 31 | 32 | 33 | -------------------------------------------------------------------------------- /parser/tools/tests/string.rb: -------------------------------------------------------------------------------- 1 | a = 'Hello' 2 | b = 'I\'m a string' 3 | c = 'Let\'s' + ' concatenate!' 4 | d = "I'm a double-quoted string" 5 | e = 0 6 | f = "The value of e variable: #{e}" 7 | g = 'Don\'t forget' ' this way to' ' concatenate strings' 8 | 9 | this_is = %q( This is ) 10 | persian = %Q( #{this_is} blasphemy! #{this_is} madness! ) 11 | leonidas = %{ Madness? #{this_is} Sparta! } 12 | 13 | k = `ls \`asdas` 14 | l = `ls` 15 | dir = "." 16 | m = `ls #{dir}` 17 | 18 | # test cases for general delimited input 19 | # quoted strings 20 | %Q|this is a string| 21 | %Q{this is a string} 22 | %Q(this is a string) 23 | %Q 24 | %Q[this is a string] 25 | 26 | %|also a string| 27 | %{also a string} 28 | %(also a string) 29 | % 30 | %[also a string] 31 | 32 | # apostrophed strings 33 | %q|apostrophed| 34 | %q{apostrophed} 35 | %q(apostrophed) 36 | %q 37 | %q[apostrophed] 38 | 39 | %x[ ls ] 40 | 41 | # Weird way to declare a char :D 42 | c = ?a 43 | c = ?\n 44 | c = ?- 45 | a = b ?1 : c 46 | a = (b) ?1 : c 47 | 48 | a = 'asdas 49 | asd' 50 | 51 | a = 'asd 52 | asdasd 53 | asdasdasdasd' 54 | 55 | b = "asd #{c.foo}" "aaa #{a} " 56 | 57 | "asd #$a sdàs #@a" 58 | 59 | %{ {} } 60 | %[ [ asdsad ] ] 61 | -------------------------------------------------------------------------------- /parser/tools/tests/string.txt: -------------------------------------------------------------------------------- 1 | Resulting AST's: 2 | 51(a)[1,0:1,1] 22 60 3 | 51(b)[2,0:2,1] 22 60 4 | 51(c)[3,0:3,1] 22 60 2 60 5 | 51(d)[4,0:4,1] 22 60 6 | 51(e)[5,0:5,1] 22 52 7 | 51(f)[6,0:6,1] 22 51(e)[6,32:6,33] 60 8 | 51(g)[7,0:7,1] 22 60 9 | Next statements: 60 60 10 | Root: 11 | 51(this_is)[9,0:9,7] 22 60 12 | 51(persian)[10,0:10,7] 22 51(this_is)[10,16:10,23] 13 | Next statements: 51(this_is)[10,38:10,45] 14 | Root: 60 15 | 51(leonidas)[11,0:11,8] 22 51(this_is)[11,25:11,32] 60 16 | 51(k)[13,0:13,1] 22 60 17 | 51(l)[14,0:14,1] 22 60 18 | 51(dir)[15,0:15,3] 22 60 19 | 51(m)[16,0:16,1] 22 51(dir)[16,10:16,13] 60 20 | 60 21 | 60 22 | 60 23 | 60 24 | 60 25 | 60 26 | 60 27 | 60 28 | 60 29 | 60 30 | 60 31 | 60 32 | 60 33 | 60 34 | 60 35 | 60 36 | 51(c)[42,0:42,1] 22 60 37 | 51(c)[43,0:43,1] 22 60 38 | 51(c)[44,0:44,1] 22 60 39 | 51(a)[45,0:45,1] 22 52 37 51(c)[45,11:45,12] 40 | 51(a)[46,0:46,1] 22 52 37 51(c)[46,13:46,14] 41 | 51(a)[48,0:48,1] 22 60 42 | 51(a)[51,0:51,1] 22 60 43 | 51(b)[55,0:55,1] 22 51(c)[55,11:55,12] 44 | Next statements: 51(foo)[55,13:55,16] 45 | Root: 66 60 46 | Next statements: 60 47 | Root: 48 | 51($a)[57,6:57,8] 49 | Next statements: 51(@a)[57,15:57,17] 50 | Root: 60 51 | 60 52 | 60 53 | 54 | 55 | -------------------------------------------------------------------------------- /parser/tools/tests/symbol.rb: -------------------------------------------------------------------------------- 1 | 2 | # The following are not strings, but symbols 3 | :"asdasd" 4 | :'symbol' 5 | 6 | a = :[] 7 | a = :[]= 8 | -------------------------------------------------------------------------------- /parser/tools/tests/symbol.txt: -------------------------------------------------------------------------------- 1 | Resulting AST's: 2 | 53 3 | 53 4 | 51(a)[6,0:6,1] 22 53([])[6,4:6,7] 5 | 51(a)[7,0:7,1] 22 53([]=)[7,4:7,8] 6 | 7 | 8 | -------------------------------------------------------------------------------- /parser/tools/tests/utf8.rb: -------------------------------------------------------------------------------- 1 | #encoding: utf-8 2 | € = 0 3 | à = 0 4 | sóc = € 5 | д = 0 6 | 7 | def funció 8 | puts 'Sí' 9 | end 10 | 11 | funció 12 | 13 | mss = %{ Miquel Sabaté #{Solà} } 14 | o = "Més accents en #{català}" 15 | l = `i més i #{més} i #{més}...` 16 | a = %Q{ más vale maña que #{fuerza} } 17 | -------------------------------------------------------------------------------- /parser/tools/tests/utf8.txt: -------------------------------------------------------------------------------- 1 | Resulting AST's: 2 | 51(€)[2,0:2,1] 22 52 3 | 51(à)[3,0:3,1] 22 52 4 | 51(sóc)[4,0:4,3] 22 51(€)[4,6:4,7] 5 | 51(д)[5,0:5,1] 22 52 6 | 51(puts)[8,2:8,6] 66 60 54[8,0:9,0] 55 7 | Condition: 51(funció)[7,4:7,10] 8 | 51(funció)[11,0:11,6] 9 | 51(mss)[13,0:13,3] 22 51(Solà)[13,25:13,29] 60 10 | 51(o)[14,0:14,1] 22 51(català)[14,22:14,28] 60 11 | 51(l)[15,0:15,1] 22 51(més)[15,15:15,18] 12 | Next statements: 51(més)[15,24:15,27] 13 | Root: 60 14 | 51(a)[16,0:16,1] 22 51(fuerza)[16,28:16,34] 60 15 | 16 | 17 | -------------------------------------------------------------------------------- /parser/tools/tests/while.rb: -------------------------------------------------------------------------------- 1 | a = 0 2 | b = 0 3 | 4 | while a < 5 5 | a += 1 6 | end 7 | 8 | until a == 0 9 | a -= 1 10 | end 11 | 12 | while a < 5 do 13 | a += 2 14 | if b == 0 15 | b += 1 16 | else 17 | b += 2 18 | end 19 | a -= 1 20 | end 21 | 22 | 23 | until a < 5 do 24 | a += 1 25 | end 26 | 27 | until a == 0 && b == 1 do 28 | while a < 5 do 29 | puts 'lalala' 30 | end 31 | a -= 1 32 | end 33 | 34 | while a and b do 35 | end 36 | 37 | while MUTEX.synchronize { a } 38 | end 39 | 40 | while MUTEX.synchronize { 41 | a 42 | } 43 | end 44 | -------------------------------------------------------------------------------- /parser/tools/tests/while.txt: -------------------------------------------------------------------------------- 1 | Resulting AST's: 2 | 51(a)[1,0:1,1] 22 52 3 | 51(b)[2,0:2,1] 22 52 4 | 51(a)[5,2:5,3] 23 52 40 5 | Condition: 51(a)[4,6:4,7] 33 52 6 | 51(a)[9,2:9,3] 23 52 40 7 | Condition: 51(a)[8,6:8,7] 26 52 8 | 51(a)[13,2:13,3] 23 52 9 | Next statements: 38 23 10 | Root: 40 11 | Condition: 51(a)[12,6:12,7] 33 52 12 | 51(a)[24,2:24,3] 23 52 40 13 | Condition: 51(a)[23,6:23,7] 33 52 14 | 51(puts)[29,4:29,8] 66 60 40 15 | Next statements: 23 16 | Root: 40 17 | Condition: 51(a)[27,6:27,7] 26 52 15 51(b)[27,16:27,17] 26 52 18 | 40 19 | Condition: 51(a)[34,6:34,7] 11 51(b)[34,12:34,13] 20 | 40 21 | Condition: 51(MUTEX)[37,6:37,11] 22 | Next statements: 51(synchronize)[37,12:37,23] 23 | Root: 66 24 | 40 25 | Condition: 51(MUTEX)[40,6:40,11] 26 | Next statements: 51(synchronize)[40,12:40,23] 27 | Root: 66 28 | 29 | 30 | -------------------------------------------------------------------------------- /rails/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | set(rubyrails_SRCS 3 | support.cpp 4 | switchers.cpp 5 | dataprovider.cpp 6 | helpers.cpp 7 | quickopendata.cpp 8 | ) 9 | 10 | add_library(kdevrubyrails SHARED ${rubyrails_SRCS}) 11 | 12 | generate_export_header(kdevrubyrails EXPORT_MACRO_NAME KDEVRUBYRAILS_EXPORT 13 | EXPORT_FILE_NAME export.h) 14 | 15 | target_link_libraries(kdevrubyrails LINK_PRIVATE 16 | KDev::Language 17 | KDev::Project 18 | 19 | kdevrubyparser 20 | ) 21 | 22 | install(TARGETS kdevrubyrails DESTINATION ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) 23 | 24 | if(BUILD_TESTING) 25 | add_subdirectory(tests) 26 | endif() 27 | -------------------------------------------------------------------------------- /rails/dataprovider.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of KDevelop 3 | * 4 | * Copyright 2010 Alexander Dymo 5 | * Copyright (C) 2014-2015 Miquel Sabaté Solà 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU Library General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public 18 | * License along with this program; if not, write to the 19 | * Free Software Foundation, Inc., 20 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 21 | */ 22 | 23 | #include 24 | 25 | #include 26 | 27 | #include 28 | #include 29 | 30 | #include 31 | 32 | #include 33 | #include 34 | 35 | #include 36 | #include 37 | 38 | using namespace KDevelop; 39 | using namespace ruby::rails; 40 | 41 | DataProvider::DataProvider(Kind kind) : m_kind(kind) 42 | { 43 | reset(); 44 | } 45 | 46 | QStringList DataProvider::scopes() 47 | { 48 | return QStringList{ QStringLiteral("Project") }; 49 | } 50 | 51 | void DataProvider::setFilterText(const QString &text) 52 | { 53 | setFilter(text.split('/')); 54 | } 55 | 56 | void DataProvider::reset() 57 | { 58 | updateItems([this](QVector &items) { 59 | const auto * const doc = ICore::self()->documentController()->activeDocument(); 60 | 61 | QVector urlsToSwitch; 62 | if (m_kind == Kind::Views) { 63 | urlsToSwitch = Switchers::viewsToSwitch(); 64 | } else if (m_kind == Kind::Tests) { 65 | urlsToSwitch = Switchers::testsToSwitch(); 66 | } 67 | 68 | items.resize(urlsToSwitch.size()); 69 | std::transform(urlsToSwitch.cbegin(), urlsToSwitch.cend(), items.begin(), 70 | [doc](const Path &url) { 71 | QuickOpenItem item; 72 | item.url = url.toUrl(); 73 | if (doc) { 74 | item.originUrl = Path(doc->url()).toUrl(); 75 | } 76 | return item; 77 | }); 78 | }); 79 | } 80 | 81 | 82 | uint DataProvider::itemCount() const 83 | { 84 | return filteredItems().count(); 85 | } 86 | 87 | uint DataProvider::unfilteredItemCount() const 88 | { 89 | return items().count(); 90 | } 91 | 92 | KDevelop::QuickOpenDataPointer DataProvider::data(uint row) const 93 | { 94 | QString s; 95 | QuickOpenItem item(filteredItems()[row]); 96 | 97 | if (m_kind == Kind::Views) { 98 | s = i18n("View for:"); 99 | } else { 100 | s = i18n("Test for:"); 101 | } 102 | return QuickOpenDataPointer(new QuickOpenData(item, s)); 103 | } 104 | 105 | void DataProvider::enableData(const QStringList &items, 106 | const QStringList &scopes) 107 | { 108 | QuickOpenDataProviderBase::enableData(items, scopes); 109 | } 110 | 111 | -------------------------------------------------------------------------------- /rails/dataprovider.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of KDevelop 3 | * 4 | * Copyright 2010 Alexander Dymo 5 | * Copyright (C) 2014-2015 Miquel Sabaté Solà 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU Library General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public 18 | * License along with this program; if not, write to the 19 | * Free Software Foundation, Inc., 20 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 21 | */ 22 | 23 | #ifndef RAILS_DATA_PROVIDER_H 24 | #define RAILS_DATA_PROVIDER_H 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | namespace ruby { 31 | namespace rails { 32 | 33 | /** 34 | * The kind of providers available. 35 | */ 36 | enum class Kind { Views, Tests }; 37 | 38 | /** 39 | * @class DataProvider. 40 | * 41 | * This class takes the rails::QuickOpenData class to provide all the 42 | * data that we need to feed the QuickOpen. 43 | */ 44 | class KDEVRUBYRAILS_EXPORT DataProvider 45 | : public KDevelop::QuickOpenDataProviderBase 46 | , public KDevelop::PathFilter 47 | { 48 | public: 49 | explicit DataProvider(const Kind kind); 50 | 51 | /// @returns the item as a KDevelop::Path. 52 | /// NOTE: currently we use QUrl internally because KDevPlatform hasn't 53 | /// moved away from KUrl yet. 54 | inline KDevelop::Path itemPath(const QuickOpenItem &data) const 55 | { 56 | return KDevelop::Path(data.url); 57 | } 58 | inline KDevelop::Path itemPrefixPath(const QuickOpenItem& data) const 59 | { 60 | #ifdef __GNUC__ 61 | #warning DataProvider::itemPrefixPath(QuickOpenItem) needs a sane implementation! 62 | #endif 63 | // FIXME: what should/could be returned here? 64 | return KDevelop::Path(); 65 | } 66 | 67 | /// @returns all scopes supported by this data-provider. 68 | static QStringList scopes(); 69 | 70 | protected: 71 | void setFilterText(const QString &text) override; 72 | void reset() override; 73 | uint itemCount() const override; 74 | uint unfilteredItemCount() const override; 75 | KDevelop::QuickOpenDataPointer data(uint row) const override; 76 | void enableData(const QStringList &items, 77 | const QStringList &scopes) override; 78 | 79 | private: 80 | Kind m_kind; 81 | }; 82 | 83 | } 84 | } 85 | 86 | #endif // RAILS_DATA_PROVIDER_H 87 | 88 | -------------------------------------------------------------------------------- /rails/helpers.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of KDevelop 3 | * 4 | * Copyright 2007-2010 Alexander Dymo 5 | * Copyright (C) 2014-2015 Miquel Sabaté Solà 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU Library General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public 18 | * License along with this program; if not, write to the 19 | * Free Software Foundation, Inc., 20 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 21 | */ 22 | 23 | #include 24 | 25 | using namespace KDevelop; 26 | using namespace ruby::rails; 27 | 28 | Path Helpers::findRailsRoot(const QUrl &url) 29 | { 30 | Path current(url.toString()); 31 | Path upUrl(current.parent()); 32 | 33 | while (upUrl != current) { 34 | Path aux = upUrl.parent(); 35 | if (aux.lastPathSegment() == QStringLiteral("app")) { 36 | const QString &dir = upUrl.lastPathSegment(); 37 | if (dir == QStringLiteral("controllers") || 38 | dir == QStringLiteral("models") || 39 | dir == QStringLiteral("views")) { 40 | return aux.parent(); 41 | } 42 | } else if (upUrl.lastPathSegment() == QStringLiteral("test")) { 43 | return aux; 44 | } 45 | current = upUrl; 46 | upUrl = aux; 47 | } 48 | return Path(); 49 | } 50 | 51 | -------------------------------------------------------------------------------- /rails/helpers.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of KDevelop 3 | * 4 | * Copyright 2007-2010 Alexander Dymo 5 | * Copyright (C) 2014-2015 Miquel Sabaté Solà 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU Library General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public 18 | * License along with this program; if not, write to the 19 | * Free Software Foundation, Inc., 20 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 21 | */ 22 | 23 | #ifndef RAILS_HELPERS_H 24 | #define RAILS_HELPERS_H 25 | 26 | #include 27 | #include 28 | 29 | namespace ruby { 30 | namespace rails { 31 | 32 | /** 33 | * @class Helpers 34 | * 35 | * This class contains common utilities for all the code across the 36 | * Rails namespace. 37 | */ 38 | class KDEVRUBYRAILS_EXPORT Helpers 39 | { 40 | public: 41 | /** 42 | * Finds the root directory of the Rails application. Not all the paths are 43 | * being looked up by this method, only the ones that the different 44 | * switchers might use: controllers, models, views and tests. 45 | * 46 | * @param url The current file or directory that is included inside a 47 | * Rails application. 48 | * @returns an invalid Path if an error has been found. Otherwise this 49 | * method returns a valid Path that points to the root of the Rails 50 | * application. 51 | */ 52 | static KDevelop::Path findRailsRoot(const QUrl &url); 53 | }; 54 | 55 | } 56 | } 57 | 58 | #endif // RAILS_HELPERS_H 59 | 60 | -------------------------------------------------------------------------------- /rails/quickopendata.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of KDevelop 3 | * 4 | * Copyright (C) 2014-2015 Miquel Sabaté Solà 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #include 21 | 22 | #include 23 | #include 24 | 25 | #include 26 | #include 27 | 28 | #include 29 | 30 | using namespace ruby::rails; 31 | 32 | QuickOpenData::QuickOpenData(const QuickOpenItem &item, 33 | const QString &explanation) 34 | : QuickOpenDataBase() 35 | , m_item(item), m_explanation(explanation) 36 | { 37 | } 38 | 39 | QString QuickOpenData::text() const 40 | { 41 | const QString &item = m_item.url.toString(); 42 | return KDevelop::Path(Helpers::findRailsRoot(m_item.url), item).path(); 43 | } 44 | 45 | QString QuickOpenData::htmlDescription() const 46 | { 47 | return "" + m_explanation + ' ' 48 | + m_item.originUrl.fileName() + ""; 49 | } 50 | 51 | bool QuickOpenData::execute(QString &filterText) 52 | { 53 | Q_UNUSED(filterText); 54 | 55 | KDevelop::ICore::self()->documentController()->openDocument(m_item.url); 56 | return true; 57 | } 58 | 59 | bool QuickOpenData::isExpandable() const 60 | { 61 | return false; 62 | } 63 | 64 | QWidget * QuickOpenData::expandingWidget() const 65 | { 66 | return KDevelop::QuickOpenDataBase::expandingWidget(); 67 | } 68 | 69 | QIcon QuickOpenData::icon() const 70 | { 71 | return KDevelop::QuickOpenDataBase::icon(); 72 | } 73 | 74 | QList QuickOpenData::highlighting() const 75 | { 76 | QTextCharFormat boldFormat; 77 | boldFormat.setFontWeight(QFont::Bold); 78 | 79 | const QString &txt = text(); 80 | int fileNameLength = m_item.url.fileName().length(); 81 | 82 | return QList{ 83 | 0, 84 | txt.length() - fileNameLength, 85 | QVariant(QTextCharFormat()), 86 | txt.length() - fileNameLength, 87 | fileNameLength, 88 | QVariant(boldFormat) 89 | }; 90 | } 91 | 92 | -------------------------------------------------------------------------------- /rails/quickopendata.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of KDevelop 3 | * 4 | * Copyright (C) 2014-2015 Miquel Sabaté Solà 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #ifndef RAILS_QUICKOPEN_DATA_H 21 | #define RAILS_QUICKOPEN_DATA_H 22 | 23 | #include 24 | #include 25 | 26 | #include 27 | 28 | namespace ruby { 29 | namespace rails { 30 | 31 | /* 32 | * TODO: maybe KDevPlatform will pick KDevelop::Path when moving away 33 | * from KUrl. If this is the case, these two attributes will be of type 34 | * KDevelop::Path too. 35 | */ 36 | struct KDEVRUBYRAILS_EXPORT QuickOpenItem { 37 | // The path of the view or test 38 | QUrl url; 39 | 40 | // The path of the file for which we show views/tests 41 | QUrl originUrl; 42 | }; 43 | 44 | /** 45 | * @class QuickOpenData 46 | * 47 | * The class being used to feed data to QuickOpen regarding Rails stuff. 48 | */ 49 | class KDEVRUBYRAILS_EXPORT QuickOpenData : public KDevelop::QuickOpenDataBase 50 | { 51 | public: 52 | QuickOpenData(const QuickOpenItem &item, const QString &explanation); 53 | 54 | protected: 55 | QString text() const override; 56 | QString htmlDescription() const override; 57 | 58 | bool execute(QString &filterText) override; 59 | 60 | bool isExpandable() const override; 61 | QWidget * expandingWidget() const override; 62 | 63 | QIcon icon() const override; 64 | 65 | QList highlighting() const override; 66 | 67 | private: 68 | QuickOpenItem m_item; 69 | QString m_explanation; 70 | }; 71 | 72 | } 73 | } 74 | 75 | #endif // RAILS_QUICKOPEN_DATA_H 76 | 77 | -------------------------------------------------------------------------------- /rails/support.cpp: -------------------------------------------------------------------------------- 1 | /* This file is part of KDevelop 2 | * 3 | * Copyright (C) 2014-2015 Miquel Sabaté Solà 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | #include 20 | 21 | #include 22 | 23 | #include 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | #include 30 | #include 31 | #include 32 | 33 | using namespace ruby::rails; 34 | 35 | Support::Support(ruby::LanguageSupport *support) 36 | : QObject(nullptr) 37 | , m_support(support) 38 | , m_views(nullptr) 39 | , m_tests(nullptr) 40 | { 41 | m_switchers = new Switchers(support); 42 | setupQuickOpen(); 43 | } 44 | 45 | Support::~Support() 46 | { 47 | delete m_switchers; 48 | delete m_views; 49 | delete m_tests; 50 | } 51 | 52 | void Support::setupQuickOpen() 53 | { 54 | auto qo = m_support->core()->pluginController()-> 55 | extensionForPlugin("org.kdevelop.IQuickOpen"); 56 | if (qo) { 57 | m_views = new DataProvider(Kind::Views); 58 | auto name = QStringList(i18n("Rails Views")); 59 | qo->registerProvider(DataProvider::scopes(), name, m_views); 60 | 61 | m_tests = new DataProvider(Kind::Tests); 62 | name = QStringList(i18n("Rails Tests")); 63 | qo->registerProvider(DataProvider::scopes(), name, m_tests); 64 | } 65 | } 66 | 67 | void Support::setupActions(KActionCollection &actions) 68 | { 69 | QAction *action = actions.addAction("ruby_switch_to_controller"); 70 | action->setText(i18n("Switch To Controller")); 71 | action->setShortcut(Qt::CTRL | Qt::ALT | Qt::Key_1); 72 | connect(action, &QAction::triggered, 73 | m_switchers, &Switchers::switchToController); 74 | 75 | action = actions.addAction("ruby_switch_to_model"); 76 | action->setText(i18n("Switch To Model")); 77 | action->setShortcut(Qt::CTRL | Qt::ALT | Qt::Key_2); 78 | connect(action, &QAction::triggered, 79 | m_switchers, &Switchers::switchToModel); 80 | 81 | action = actions.addAction("ruby_switch_to_view"); 82 | action->setText(i18n("Switch To View")); 83 | action->setShortcut(Qt::CTRL | Qt::ALT | Qt::Key_3); 84 | connect(action, &QAction::triggered, 85 | m_switchers, &Switchers::switchToView); 86 | 87 | action = actions.addAction("ruby_switch_to_test"); 88 | action->setText(i18n("Switch To Test")); 89 | action->setShortcut(Qt::CTRL | Qt::ALT | Qt::Key_4); 90 | connect(action, &QAction::triggered, 91 | m_switchers, &Switchers::switchToTest); 92 | } 93 | 94 | -------------------------------------------------------------------------------- /rails/support.h: -------------------------------------------------------------------------------- 1 | /* This file is part of KDevelop 2 | * 3 | * Copyright (C) 2014-2015 Miquel Sabaté Solà 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | #ifndef RUBY_RAILS_H 20 | #define RUBY_RAILS_H 21 | 22 | #include 23 | #include 24 | 25 | namespace ruby { 26 | 27 | class LanguageSupport; 28 | 29 | namespace rails { 30 | 31 | class Switchers; 32 | class DataProvider; 33 | 34 | /** 35 | * @class Support 36 | * 37 | * This class gathers together anything that has to do with Rails support. This 38 | * includes setting up Quick open, the main window actions, etc. 39 | */ 40 | class KDEVRUBYRAILS_EXPORT Support : public QObject 41 | { 42 | Q_OBJECT 43 | 44 | public: 45 | explicit Support(ruby::LanguageSupport *language); 46 | ~Support() override; 47 | 48 | /** 49 | * Setup the Main Window actions. 50 | * 51 | * @param actions The main window actions to be modified. 52 | */ 53 | void setupActions(KActionCollection &actions); 54 | 55 | private: 56 | void setupQuickOpen(); 57 | 58 | private: 59 | ruby::LanguageSupport *m_support; 60 | Switchers *m_switchers; 61 | DataProvider *m_views; 62 | DataProvider *m_tests; 63 | }; 64 | 65 | } 66 | } 67 | 68 | #endif // RUBY_RAILS_H 69 | 70 | -------------------------------------------------------------------------------- /rails/switchers.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of KDevelop 3 | * 4 | * Copyright 2007-2010 Alexander Dymo 5 | * Copyright (C) 2014-2015 Miquel Sabaté Solà 6 | * 7 | * This program is free software; you can redistribute it and/or modify 8 | * it under the terms of the GNU Library General Public License as 9 | * published by the Free Software Foundation; either version 2 of the 10 | * License, or (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public 18 | * License along with this program; if not, write to the 19 | * Free Software Foundation, Inc., 20 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 21 | */ 22 | 23 | #ifndef RAILS_SWITCHERS_H 24 | #define RAILS_SWITCHERS_H 25 | 26 | #include 27 | #include 28 | 29 | namespace ruby { 30 | 31 | class LanguageSupport; 32 | 33 | namespace rails { 34 | 35 | /** 36 | * @class Switchers 37 | * 38 | * This class has all the logic to switch between controllers, models, views 39 | * and tests, in a Rails application. 40 | */ 41 | class KDEVRUBYRAILS_EXPORT Switchers : public QObject 42 | { 43 | Q_OBJECT 44 | 45 | public: 46 | explicit Switchers(ruby::LanguageSupport *language); 47 | 48 | /// @returns all the views that we can switch to. 49 | static QVector viewsToSwitch(); 50 | 51 | /// @returns all the tests that we can switch to. 52 | static QVector testsToSwitch(); 53 | 54 | public slots: 55 | void switchToController(); 56 | void switchToModel(); 57 | void switchToView(); 58 | void switchToTest(); 59 | }; 60 | 61 | } 62 | } 63 | 64 | #endif // RAILS_SWITCHERS_H 65 | 66 | -------------------------------------------------------------------------------- /rails/tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}) 3 | 4 | include(ECMAddTests) 5 | 6 | macro(ruby_unit_test testname) 7 | ecm_add_test( 8 | ${testname}.cpp TEST_NAME ${testname} 9 | 10 | LINK_LIBRARIES 11 | 12 | Qt5::Test 13 | 14 | KDev::Interfaces 15 | KDev::Tests 16 | 17 | kdevrubyparser 18 | kdevrubyrails 19 | ) 20 | endmacro() 21 | 22 | ruby_unit_test(rails) 23 | -------------------------------------------------------------------------------- /rails/tests/rails.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of KDevelop 3 | * Copyright (C) 2014-2015 Miquel Sabaté Solà 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | 27 | QTEST_MAIN(ruby::rails::Test) 28 | 29 | using namespace ruby::rails; 30 | 31 | Test::Test() 32 | { 33 | /* There's nothing to do here. */ 34 | } 35 | 36 | void Test::TestFindRailsRoot() 37 | { 38 | KDevelop::Path path; 39 | 40 | // Empty URL. 41 | path = Helpers::findRailsRoot(QUrl("")); 42 | Q_ASSERT(!path.isValid()); 43 | 44 | // App. 45 | path = Helpers::findRailsRoot(QUrl("/rails/app/controllers/file.rb")); 46 | Q_ASSERT(path.isValid()); 47 | QCOMPARE(path.toLocalFile(), QString("/rails")); 48 | path = Helpers::findRailsRoot(QUrl("/rails/app/models/file.rb")); 49 | Q_ASSERT(path.isValid()); 50 | QCOMPARE(path.toLocalFile(), QString("/rails")); 51 | path = Helpers::findRailsRoot(QUrl("/rails/app/views/file.rb")); 52 | Q_ASSERT(path.isValid()); 53 | QCOMPARE(path.toLocalFile(), QString("/rails")); 54 | 55 | // Tests. 56 | path = Helpers::findRailsRoot(QUrl("/rails/test/file.rb")); 57 | Q_ASSERT(path.isValid()); 58 | QCOMPARE(path.toLocalFile(), QString("/rails")); 59 | path = Helpers::findRailsRoot(QUrl("/rails/dir/test/file.rb")); 60 | Q_ASSERT(path.isValid()); 61 | QCOMPARE(path.toLocalFile(), QString("/rails/dir")); 62 | 63 | // Invalids 64 | path = Helpers::findRailsRoot(QUrl("/rails/app/test/file.rb")); 65 | Q_ASSERT(!path.isValid()); 66 | path = Helpers::findRailsRoot(QUrl("/rails/app/controllers")); 67 | Q_ASSERT(!path.isValid()); 68 | } 69 | 70 | -------------------------------------------------------------------------------- /rails/tests/rails.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of KDevelop 3 | * Copyright (C) 2014-2015 Miquel Sabaté Solà 4 | * 5 | * This program is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program. If not, see . 17 | */ 18 | 19 | #ifndef RAILS_TEST_H 20 | #define RAILS_TEST_H 21 | 22 | #include 23 | 24 | namespace ruby { 25 | namespace rails { 26 | 27 | class Test : public QObject 28 | { 29 | Q_OBJECT 30 | 31 | public: 32 | Test(); 33 | 34 | private slots: 35 | void TestFindRailsRoot(); 36 | }; 37 | 38 | } 39 | } 40 | 41 | #endif /* RAILS_TEST */ 42 | --------------------------------------------------------------------------------