rsense-server 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +23 -0
  3. data/Gemfile +14 -0
  4. data/Guardfile +5 -0
  5. data/LICENSE.txt +1 -0
  6. data/README.md +51 -0
  7. data/Rakefile +9 -0
  8. data/bin/_rsense.rb +115 -0
  9. data/config/puma.rb +2 -0
  10. data/lib/rsense/server/code.rb +38 -0
  11. data/lib/rsense/server/command/completion_result.rb +11 -0
  12. data/lib/rsense/server/command/special_meth.rb +18 -0
  13. data/lib/rsense/server/command/type_inference_method.rb +24 -0
  14. data/lib/rsense/server/command.rb +239 -0
  15. data/lib/rsense/server/config.rb +70 -0
  16. data/lib/rsense/server/gem_path.rb +18 -0
  17. data/lib/rsense/server/listeners/find_definition_event_listener.rb +91 -0
  18. data/lib/rsense/server/listeners/where_event_listener.rb +39 -0
  19. data/lib/rsense/server/load_path.rb +62 -0
  20. data/lib/rsense/server/options.rb +85 -0
  21. data/lib/rsense/server/parser.rb +17 -0
  22. data/lib/rsense/server/path_info.rb +17 -0
  23. data/lib/rsense/server/project.rb +24 -0
  24. data/lib/rsense/server/version.rb +5 -0
  25. data/lib/rsense/server.rb +18 -0
  26. data/rsense-server.gemspec +35 -0
  27. data/spec/fixtures/config_fixture/.rsense +4 -0
  28. data/spec/fixtures/deeply/nested/thing.rb +0 -0
  29. data/spec/fixtures/find_def_sample.json +10 -0
  30. data/spec/fixtures/sample.json +10 -0
  31. data/spec/fixtures/test_gem/.gitignore +22 -0
  32. data/spec/fixtures/test_gem/Gemfile +4 -0
  33. data/spec/fixtures/test_gem/LICENSE.txt +22 -0
  34. data/spec/fixtures/test_gem/README.md +29 -0
  35. data/spec/fixtures/test_gem/Rakefile +2 -0
  36. data/spec/fixtures/test_gem/lib/sample/version.rb +3 -0
  37. data/spec/fixtures/test_gem/lib/sample.rb +16 -0
  38. data/spec/fixtures/test_gem/sample.gemspec +23 -0
  39. data/spec/fixtures/test_gem/test.json +10 -0
  40. data/spec/rsense/server/code_spec.rb +44 -0
  41. data/spec/rsense/server/command/special_meth_spec.rb +23 -0
  42. data/spec/rsense/server/command_spec.rb +108 -0
  43. data/spec/rsense/server/config_spec.rb +27 -0
  44. data/spec/rsense/server/gem_path_spec.rb +16 -0
  45. data/spec/rsense/server/load_path_spec.rb +63 -0
  46. data/spec/rsense/server/options_spec.rb +33 -0
  47. data/spec/rsense/server/path_info_spec.rb +11 -0
  48. data/spec/rsense/server/project_spec.rb +18 -0
  49. data/spec/rsense/server_spec.rb +7 -0
  50. data/spec/spec_helper.rb +16 -0
  51. data/vendor/gems/puma-2.8.2-java/COPYING +55 -0
  52. data/vendor/gems/puma-2.8.2-java/DEPLOYMENT.md +92 -0
  53. data/vendor/gems/puma-2.8.2-java/Gemfile +17 -0
  54. data/vendor/gems/puma-2.8.2-java/History.txt +532 -0
  55. data/vendor/gems/puma-2.8.2-java/LICENSE +26 -0
  56. data/vendor/gems/puma-2.8.2-java/Manifest.txt +68 -0
  57. data/vendor/gems/puma-2.8.2-java/README.md +251 -0
  58. data/vendor/gems/puma-2.8.2-java/Rakefile +158 -0
  59. data/vendor/gems/puma-2.8.2-java/bin/puma +10 -0
  60. data/vendor/gems/puma-2.8.2-java/bin/puma-wild +17 -0
  61. data/vendor/gems/puma-2.8.2-java/bin/pumactl +12 -0
  62. data/vendor/gems/puma-2.8.2-java/docs/config.md +0 -0
  63. data/vendor/gems/puma-2.8.2-java/docs/nginx.md +80 -0
  64. data/vendor/gems/puma-2.8.2-java/docs/signals.md +42 -0
  65. data/vendor/gems/puma-2.8.2-java/ext/puma_http11/PumaHttp11Service.java +17 -0
  66. data/vendor/gems/puma-2.8.2-java/ext/puma_http11/ext_help.h +15 -0
  67. data/vendor/gems/puma-2.8.2-java/ext/puma_http11/extconf.rb +8 -0
  68. data/vendor/gems/puma-2.8.2-java/ext/puma_http11/http11_parser.c +1225 -0
  69. data/vendor/gems/puma-2.8.2-java/ext/puma_http11/http11_parser.h +64 -0
  70. data/vendor/gems/puma-2.8.2-java/ext/puma_http11/http11_parser.java.rl +161 -0
  71. data/vendor/gems/puma-2.8.2-java/ext/puma_http11/http11_parser.rl +146 -0
  72. data/vendor/gems/puma-2.8.2-java/ext/puma_http11/http11_parser_common.rl +54 -0
  73. data/vendor/gems/puma-2.8.2-java/ext/puma_http11/io_buffer.c +155 -0
  74. data/vendor/gems/puma-2.8.2-java/ext/puma_http11/mini_ssl.c +195 -0
  75. data/vendor/gems/puma-2.8.2-java/ext/puma_http11/org/jruby/puma/Http11.java +225 -0
  76. data/vendor/gems/puma-2.8.2-java/ext/puma_http11/org/jruby/puma/Http11Parser.java +488 -0
  77. data/vendor/gems/puma-2.8.2-java/ext/puma_http11/org/jruby/puma/MiniSSL.java +289 -0
  78. data/vendor/gems/puma-2.8.2-java/ext/puma_http11/puma_http11.c +491 -0
  79. data/vendor/gems/puma-2.8.2-java/lib/puma/accept_nonblock.rb +23 -0
  80. data/vendor/gems/puma-2.8.2-java/lib/puma/app/status.rb +59 -0
  81. data/vendor/gems/puma-2.8.2-java/lib/puma/binder.rb +298 -0
  82. data/vendor/gems/puma-2.8.2-java/lib/puma/capistrano.rb +86 -0
  83. data/vendor/gems/puma-2.8.2-java/lib/puma/cli.rb +587 -0
  84. data/vendor/gems/puma-2.8.2-java/lib/puma/client.rb +289 -0
  85. data/vendor/gems/puma-2.8.2-java/lib/puma/cluster.rb +389 -0
  86. data/vendor/gems/puma-2.8.2-java/lib/puma/compat.rb +18 -0
  87. data/vendor/gems/puma-2.8.2-java/lib/puma/configuration.rb +377 -0
  88. data/vendor/gems/puma-2.8.2-java/lib/puma/const.rb +165 -0
  89. data/vendor/gems/puma-2.8.2-java/lib/puma/control_cli.rb +251 -0
  90. data/vendor/gems/puma-2.8.2-java/lib/puma/daemon_ext.rb +25 -0
  91. data/vendor/gems/puma-2.8.2-java/lib/puma/delegation.rb +11 -0
  92. data/vendor/gems/puma-2.8.2-java/lib/puma/detect.rb +4 -0
  93. data/vendor/gems/puma-2.8.2-java/lib/puma/events.rb +130 -0
  94. data/vendor/gems/puma-2.8.2-java/lib/puma/io_buffer.rb +7 -0
  95. data/vendor/gems/puma-2.8.2-java/lib/puma/java_io_buffer.rb +45 -0
  96. data/vendor/gems/puma-2.8.2-java/lib/puma/jruby_restart.rb +83 -0
  97. data/vendor/gems/puma-2.8.2-java/lib/puma/minissl.rb +148 -0
  98. data/vendor/gems/puma-2.8.2-java/lib/puma/null_io.rb +34 -0
  99. data/vendor/gems/puma-2.8.2-java/lib/puma/puma_http11.jar +0 -0
  100. data/vendor/gems/puma-2.8.2-java/lib/puma/rack_default.rb +7 -0
  101. data/vendor/gems/puma-2.8.2-java/lib/puma/rack_patch.rb +45 -0
  102. data/vendor/gems/puma-2.8.2-java/lib/puma/reactor.rb +183 -0
  103. data/vendor/gems/puma-2.8.2-java/lib/puma/runner.rb +146 -0
  104. data/vendor/gems/puma-2.8.2-java/lib/puma/server.rb +801 -0
  105. data/vendor/gems/puma-2.8.2-java/lib/puma/single.rb +102 -0
  106. data/vendor/gems/puma-2.8.2-java/lib/puma/tcp_logger.rb +32 -0
  107. data/vendor/gems/puma-2.8.2-java/lib/puma/thread_pool.rb +185 -0
  108. data/vendor/gems/puma-2.8.2-java/lib/puma/util.rb +9 -0
  109. data/vendor/gems/puma-2.8.2-java/lib/puma.rb +14 -0
  110. data/vendor/gems/puma-2.8.2-java/lib/rack/handler/puma.rb +66 -0
  111. data/vendor/gems/puma-2.8.2-java/puma.gemspec +55 -0
  112. data/vendor/gems/puma-2.8.2-java/test/test_app_status.rb +92 -0
  113. data/vendor/gems/puma-2.8.2-java/test/test_cli.rb +173 -0
  114. data/vendor/gems/puma-2.8.2-java/test/test_config.rb +26 -0
  115. data/vendor/gems/puma-2.8.2-java/test/test_http10.rb +27 -0
  116. data/vendor/gems/puma-2.8.2-java/test/test_http11.rb +144 -0
  117. data/vendor/gems/puma-2.8.2-java/test/test_integration.rb +165 -0
  118. data/vendor/gems/puma-2.8.2-java/test/test_iobuffer.rb +38 -0
  119. data/vendor/gems/puma-2.8.2-java/test/test_minissl.rb +25 -0
  120. data/vendor/gems/puma-2.8.2-java/test/test_null_io.rb +31 -0
  121. data/vendor/gems/puma-2.8.2-java/test/test_persistent.rb +238 -0
  122. data/vendor/gems/puma-2.8.2-java/test/test_puma_server.rb +323 -0
  123. data/vendor/gems/puma-2.8.2-java/test/test_rack_handler.rb +10 -0
  124. data/vendor/gems/puma-2.8.2-java/test/test_rack_server.rb +141 -0
  125. data/vendor/gems/puma-2.8.2-java/test/test_tcp_rack.rb +42 -0
  126. data/vendor/gems/puma-2.8.2-java/test/test_thread_pool.rb +156 -0
  127. data/vendor/gems/puma-2.8.2-java/test/test_unix_socket.rb +39 -0
  128. data/vendor/gems/puma-2.8.2-java/test/test_ws.rb +89 -0
  129. data/vendor/gems/puma-2.8.2-java/tools/jungle/README.md +9 -0
  130. data/vendor/gems/puma-2.8.2-java/tools/jungle/init.d/README.md +54 -0
  131. data/vendor/gems/puma-2.8.2-java/tools/jungle/init.d/puma +332 -0
  132. data/vendor/gems/puma-2.8.2-java/tools/jungle/init.d/run-puma +3 -0
  133. data/vendor/gems/puma-2.8.2-java/tools/jungle/upstart/README.md +61 -0
  134. data/vendor/gems/puma-2.8.2-java/tools/jungle/upstart/puma-manager.conf +31 -0
  135. data/vendor/gems/puma-2.8.2-java/tools/jungle/upstart/puma.conf +63 -0
  136. data/vendor/gems/puma-2.8.2-java/tools/trickletest.rb +45 -0
  137. metadata +389 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 8d67d9c7640d8e06647ff1f5e708b5a73a1aa28b
4
+ data.tar.gz: 186fd888eefebaad271af5b2254ffd1e44dcf790
5
+ SHA512:
6
+ metadata.gz: d06bfae8ea880c507de82e9baeb0d15251bed35c65e0e46709bf1775aea2a3258d670e109ac437bbb010cc5b7768081c0375be57022b5380f7b6145767b9021f
7
+ data.tar.gz: 11a44d3575f2eb25907bdb76817434f2676fed08996c14d5dd61ceb790ed87e590d0ef638b3e72ff09ee96b596764e6280ee29a9095ad03d175ee5d2bf9178e5
data/.gitignore ADDED
@@ -0,0 +1,23 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
23
+ .ruby-version
data/Gemfile ADDED
@@ -0,0 +1,14 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in rsense.gemspec
4
+ gemspec
5
+
6
+ gem 'puma', :path => File.join(File.dirname(__FILE__), './vendor/gems/puma-2.8.2-java')
7
+
8
+ group :linux do
9
+ gem 'libnotify'
10
+ end
11
+
12
+ group :darwin do
13
+ gem 'terminal-notifier-guard'
14
+ end
data/Guardfile ADDED
@@ -0,0 +1,5 @@
1
+ guard :minitest do
2
+ watch(%r{^spec/(.*)_spec\.rb})
3
+ watch(%r{^lib/(.+)\.rb}) { |m| "spec/#{m[1]}_spec.rb" }
4
+ watch(%r{^spec/spec_helper\.rb}) { 'spec' }
5
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1 @@
1
+ RSense is distributed under the term of GPLv3+(http://gplv3.fsf.org/).
data/README.md ADDED
@@ -0,0 +1,51 @@
1
+ ![rsense](https://cloud.githubusercontent.com/assets/1395968/2978144/51565ee2-dbb5-11e3-9b94-e97a37739d03.png)
2
+
3
+ # Rsense Can See All
4
+
5
+ [![Gitter chat](https://badges.gitter.im/rsense/rsense.png)](https://gitter.im/rsense/rsense)
6
+
7
+ RSense is a tool for doing static analysis of Ruby source code. Rsense is used in conjunction with an editor plugin.
8
+
9
+ RSense is currently under heavy development and not ready to use yet. It would be awesome if you helped get things done.
10
+
11
+ [![Stories in Ready](https://badge.waffle.io/rsense/rsense.png?label=ready&title=Ready)](https://waffle.io/rsense/rsense)
12
+
13
+
14
+ ## Installation
15
+
16
+ Add this line to your application's Gemfile:
17
+
18
+ gem 'rsense'
19
+
20
+ And then execute:
21
+
22
+ $ bundle
23
+
24
+ Or install it yourself as:
25
+
26
+ $ gem install rsense
27
+
28
+ ## Usage
29
+
30
+ TODO: Write usage instructions here
31
+
32
+ ## Contributing
33
+
34
+ 1. Fork it ( https://github.com/[my-github-username]/rsense/fork )
35
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
36
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
37
+ 4. Push to the branch (`git push origin my-new-feature`)
38
+ 5. Create a new Pull Request
39
+
40
+ ## License
41
+
42
+ RSense is distributed under the term of
43
+ [GPLv3+](http://gplv3.fsf.org/).
44
+
45
+ ## Credits
46
+
47
+ Rsense was originally designed and implemented by [Matsuyama Tomohiro(@m2ym)](https://github.com/m2ym/), and his hard work is still at the core of rsense today. All of the algorithms for type-detection were implemented by him, with inspiration from multiple places. You can read about his original version at [Rsense: A Ruby Development tools for Emacs, Vim and Others](http://cx4a.org/software/rsense/)
48
+
49
+ In 2013, a major undertaking by @edubkendo to bring it current and improve its usefullness to rubyists was sponsored by the @jruby organization as a Google Summer of Code project.
50
+
51
+ Special thanks belongs to [Tom Enebo (@enebo)](https://github.com/enebo) who provided excellent mentorship, code, architectural suggestions and more throughout the course of the update.
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new do |t|
5
+ t.libs.push "lib"
6
+ t.test_files = FileList['spec/**/*_spec.rb']
7
+ t.verbose = true
8
+ end
9
+
data/bin/_rsense.rb ADDED
@@ -0,0 +1,115 @@
1
+ require "rsense/server"
2
+ require "rsense/server/config"
3
+ require "optparse"
4
+
5
+ SOCKET_PATH = '127.0.0.1:'
6
+ DEFAULT_PORT = 47367
7
+
8
+ options = {}
9
+ OptionParser.new do |opts|
10
+ opts.banner = "Usage: rsense start [options]"
11
+
12
+ opts.on("-pp", "--path PATH", "project path") do |path|
13
+ options[:path] = path
14
+ end
15
+
16
+ opts.on("-p", "--port PORT", "Port") do |port|
17
+ options[:port] = port
18
+ end
19
+ end.parse!
20
+
21
+ def config(options)
22
+ if options[:path]
23
+ path = Pathname.new(options[:path]).expand_path
24
+ end
25
+ conf = Rsense::Server::Config.new
26
+
27
+ if path && path.exist?
28
+ conf.set_up(path)
29
+ else
30
+ conf.set_up(Pathname.new("~").expand_path)
31
+ end
32
+ conf
33
+ end
34
+
35
+ def port(options)
36
+ config = config(options)
37
+ if options[:port] && options[:port].match(/^\d*$/)
38
+ options[:port].to_i
39
+ elsif config.port
40
+ config.port
41
+ else
42
+ DEFAULT_PORT
43
+ end
44
+ end
45
+
46
+ PORT = port(options)
47
+
48
+ require "puma"
49
+ require "sinatra"
50
+ require "json"
51
+
52
+ class RsenseApp < Sinatra::Base
53
+ attr_accessor :roptions, :rcommand, :rproject
54
+
55
+ configure { set :server, :puma }
56
+ set :port, PORT
57
+
58
+ def setup(jsondata)
59
+ if @roptions && @roptions.project_path =~ /#{jsondata["project"]}/
60
+ changed = check_options(jsondata)
61
+ @rcommand.options = @roptions
62
+ else
63
+ @roptions = Rsense::Server::Options.new(jsondata)
64
+ @rcommand = Rsense::Server::Command::Command.new(@roptions)
65
+ end
66
+ end
67
+
68
+ def check_options(data)
69
+ changed = []
70
+ data.each do |k, v|
71
+ unless @roptions.send k.to_sym == v
72
+ @roptions.__send__("#{k}=", v)
73
+ changed << k
74
+ end
75
+ end
76
+ changed
77
+ end
78
+
79
+ def code_completion
80
+ if @roptions.code
81
+ candidates = @rcommand.code_completion(@roptions.file, @roptions.location, @roptions.code)
82
+ else
83
+ candidates = @rcommand.code_completion(@roptions.file, @roptions.location)
84
+ end
85
+ completions = candidates.map do |c|
86
+ {c.completion => {
87
+ qualified_name: c.qualified_name,
88
+ base_name: c.base_name,
89
+ kind: c.kind.to_string
90
+ }}
91
+ end
92
+ { :completions => completions }
93
+ end
94
+
95
+ post '/' do
96
+ content_type :json
97
+ jsontext = request.body.read
98
+ if jsontext
99
+ data = JSON.parse(jsontext)
100
+ setup(data)
101
+ __send__(data["command"]).to_json
102
+ else
103
+ "No JSON was sent"
104
+ end
105
+ end
106
+
107
+ end
108
+
109
+ # termination signal
110
+ Signal.trap("TERM") do
111
+ puts "TERM signal received."
112
+ RsenseApp.stop!
113
+ end
114
+
115
+ RsenseApp.run!
data/config/puma.rb ADDED
@@ -0,0 +1,2 @@
1
+ OUT_PATH = '/tmp/rsense.log'
2
+ stdout_redirect(OUT_PATH, OUT_PATH, true)
@@ -0,0 +1,38 @@
1
+ module Rsense
2
+ module Server
3
+ class Code
4
+ attr_accessor :lines
5
+ TYPE_INFERENCE_METHOD_NAME = Rsense::Server::Command::TYPE_INFERENCE_METHOD_NAME
6
+ FIND_DEFINITION_METHOD_NAME_PREFIX = Rsense::Server::Command::FIND_DEFINITION_METHOD_NAME_PREFIX
7
+
8
+ def initialize(code_str)
9
+ @lines = code_str.split("\n")
10
+ end
11
+
12
+ def inject_inference_marker(location)
13
+ row = location["row"] - 1
14
+ column = location["column"] - 1
15
+ lines = @lines.clone
16
+ line = lines[row]
17
+ if line.slice(column - 1).end_with?(".")
18
+ line.insert(column, TYPE_INFERENCE_METHOD_NAME)
19
+ else
20
+ line.insert(column, ".#{TYPE_INFERENCE_METHOD_NAME}")
21
+ end
22
+ lines.join("\n")
23
+ end
24
+
25
+ def inject_definition_marker(injection, location)
26
+ row = location["row"] - 1
27
+ column = location["column"] - 1
28
+ lines = @lines.clone
29
+ line = lines[row]
30
+ match = line.slice(0, column).match(/.*(?:\.|::|\s)(\w+?[!?]?)/)
31
+ start = match.end(0)
32
+ line.insert(start - 1, injection)
33
+ lines.join("\n")
34
+ end
35
+
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,11 @@
1
+ module Rsense
2
+ module Server
3
+ module Command
4
+
5
+ end
6
+ end
7
+ end
8
+
9
+ class Rsense::Server::Command::CompletionResult
10
+
11
+ end
@@ -0,0 +1,18 @@
1
+ module Rsense
2
+ module Server
3
+ module Command
4
+ class SpecialMeth < Java::org.cx4a.rsense.typing.runtime::SpecialMethod
5
+ attr_accessor :call_block
6
+
7
+ def initialize(&code)
8
+ @call_block = code
9
+ end
10
+
11
+ def call(*args)
12
+ @call_block.call(*args)
13
+ end
14
+
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,24 @@
1
+ module Rsense
2
+ module Server
3
+ module Command
4
+
5
+ end
6
+ end
7
+ end
8
+
9
+ class Rsense::Server::Command::TypeInferenceMethod < Java::org.cx4a.rsense.typing.runtime::SpecialMethod
10
+ attr_accessor :context
11
+
12
+ def initialize
13
+ super
14
+ end
15
+
16
+ def call(runtime, receivers, args, blcck, result)
17
+ receivers.each do |receiver|
18
+ @context.typeSet.add(receiver)
19
+ end
20
+ result.setResultTypeSet(receivers)
21
+ result.setNeverCallAgain(true)
22
+ end
23
+
24
+ end
@@ -0,0 +1,239 @@
1
+ require "pathname"
2
+ require "rsense-core"
3
+ require_relative "./listeners/find_definition_event_listener"
4
+ require_relative "./listeners/where_event_listener"
5
+ require_relative "./command/special_meth"
6
+ require_relative "./command/type_inference_method"
7
+
8
+ module Rsense
9
+ module Server
10
+ Context = Struct.new(:project, :typeSet, :main, :feature, :loadPathLevel) {
11
+ def clear
12
+ @project = nil
13
+ @typeSet = nil
14
+ @main = false
15
+ @feature = nil
16
+ @loadPathLevel = 0
17
+ end
18
+ }
19
+ module Command
20
+ TYPE_INFERENCE_METHOD_NAME = Rsense::CodeAssist::TYPE_INFERENCE_METHOD_NAME
21
+ FIND_DEFINITION_METHOD_NAME_PREFIX = Rsense::CodeAssist::FIND_DEFINITION_METHOD_NAME_PREFIX
22
+ PROJECT_CONFIG_NAME = ".rsense"
23
+ end
24
+ end
25
+ end
26
+
27
+ class Rsense::Server::Command::Command
28
+ LoadResult = Java::org.cx4a.rsense::LoadResult
29
+ CompletionCandidate = Struct.new(
30
+ :completion,
31
+ :qualified_name,
32
+ :base_name,
33
+ :kind
34
+ )
35
+
36
+ attr_accessor :context, :options, :parser, :projects, :sandbox, :definitionFinder, :whereListener, :type_inference_method, :require_method, :require_next_method, :result, :graph
37
+
38
+ def initialize(options)
39
+ @context = Rsense::Server::Context.new
40
+ @options = options
41
+
42
+ @type_inference_method = Rsense::Server::Command::TypeInferenceMethod.new()
43
+ @type_inference_method.context = @context
44
+
45
+ @require_method = Rsense::Server::Command::SpecialMeth.new() do |runtime, receivers, args, blcck, result|
46
+ if args
47
+ feature = Java::org.cx4a.rsense.typing.vertex::Vertex.getString(args[0])
48
+ if feature
49
+ rrequire(@context.project, feature, "UTF-8")
50
+ end
51
+ end
52
+ end
53
+
54
+ @require_next_method = Rsense::Server::Command::SpecialMeth.new() do |runtime, receivers, args, blcck, result|
55
+ if @context.feature
56
+ rrequire(@context.project, @context.feature, "UTF-8", @context.loadPathLevel + 1)
57
+ end
58
+ end
59
+
60
+ clear()
61
+ end
62
+
63
+ def rload(project, file, encoding, prep)
64
+ return LoadResult.alreadyLoaded() if project.loaded?(file)
65
+ return if file.extname =~ /(\.so|\.dylib|\.dll|\.java|\.class|\.c$|\.h$|\.m$|\.js|\.html|\.css)/
66
+ project.loaded << file
67
+ oldmain = @context.main
68
+
69
+ if prep
70
+ prepare(project)
71
+ else
72
+ @context.main = false
73
+ end
74
+
75
+ ast = @parser.parse_string(file.read, file.to_s)
76
+ project.graph.load(ast)
77
+ result = LoadResult.new
78
+ result.setAST(ast)
79
+ result
80
+ end
81
+
82
+ def rrequire(project, feature, encoding, loadPathLevel=0)
83
+ return LoadResult.alreadyLoaded() unless project.loaded?(feature)
84
+ project.loaded << feature
85
+
86
+ stubs = stubs_matches(project, feature)
87
+ stubs.each do |stub|
88
+ rload(project, Pathname.new(stub), encoding, false)
89
+ end
90
+
91
+ lpmatches = load_path_matches(project, feature)
92
+ lpmatches.each do |lp|
93
+ rload(project, lp, encoding, false)
94
+ end
95
+
96
+ dependencies = project.dependencies
97
+ dpmatches = dependency_matches(dependencies, feature)
98
+ dpmatches.each do |dp|
99
+ rload(project, dp, encoding, false)
100
+ end
101
+
102
+ unless lpmatches || dpmatches
103
+ dep_paths = dependency_paths(dependencies)
104
+ gem_path = project.gem_path.map {|gp| Pathname.new(gp) }
105
+
106
+ checked = deep_check(gem_path, dep_paths, feature)
107
+ checked.each do |cp|
108
+ rload(project, cp, encoding, false)
109
+ end
110
+ end
111
+ end
112
+
113
+ def load_builtin(project)
114
+ builtin = builtin_path(project)
115
+ rload(project, builtin, "UTF-8", false)
116
+ end
117
+
118
+ def builtin_path(project)
119
+ Pathname.new(project.stubs.select { |stub| stub.match(/builtin/)}.first)
120
+ end
121
+
122
+ def stub_matches(project, feature)
123
+ project.stubs.select { |stub| stub.to_s =~ /#{feature}/ }
124
+ end
125
+
126
+ def dependency_paths(dependencies)
127
+ dependencies.map { |d| Pathname.new(d.path.first).parent }.flatten
128
+ end
129
+
130
+ def dependency_matches(dependencies, feature)
131
+ dmatch = dependencies.select { |d| d.name =~ /#{feature}/ }
132
+ if dmatch
133
+ dmatch.map { |dm| Pathname.new(dm.path.first) }
134
+ end
135
+ end
136
+
137
+ def load_path_matches(project, feature)
138
+ load_path = project.load_path
139
+ load_path.map do |lp|
140
+ Dir.glob(Pathname.new(lp).join("**/*#{feature}*"))
141
+ end.flatten.compact
142
+ end
143
+
144
+ def deep_check(gem_path, dep_paths, feature)
145
+ checkpaths = gem_path + dep_paths
146
+ checkpaths.map do |p|
147
+ Dir.glob(Pathname.new(p).join("**/*#{feature}*"))
148
+ end.flatten.compact
149
+ end
150
+
151
+ def open_project(project)
152
+ @projects[project.name] = project
153
+ end
154
+
155
+ def code_completion(file, location, code_str="")
156
+ if code_str.empty?
157
+ code = Rsense::Server::Code.new(Pathname.new(file).read)
158
+ else
159
+ code = Rsense::Server::Code.new(code_str)
160
+ puts code
161
+ end
162
+ source = code.inject_inference_marker(location)
163
+ ast = @parser.parse_string(source, file.to_s)
164
+ @project.graph.load(ast)
165
+ result = Java::org.cx4a.rsense::CodeCompletionResult.new
166
+ result.setAST(ast)
167
+ candidates = []
168
+ @receivers = []
169
+ @context.typeSet.each do |receiver|
170
+ @receivers << receiver
171
+ ruby_class = receiver.getMetaClass
172
+ ruby_class.getMethods(true).each do |name|
173
+ rmethod = ruby_class.searchMethod(name)
174
+ candidates << CompletionCandidate.new(name, rmethod.toString(), rmethod.getModule().getMethodPath(nil), method_kind)
175
+ end
176
+ if receiver.to_java_object.java_kind_of?(Java::org.cx4a.rsense.ruby::RubyModule)
177
+ rmodule = receiver
178
+ rmodule.getConstants(true).each do |name|
179
+ direct_module = rmodule.getConstantModule(name)
180
+ constant = direct_module.getConstant(name)
181
+ base_name = direct_module.toString()
182
+ qname = "#{base_name}::#{name}"
183
+ kind = kind_check(constant)
184
+ candidates << CompletionCandidate.new(name, qname, base_name, kind)
185
+ end
186
+ end
187
+ end
188
+ candidates
189
+ end
190
+
191
+ def method_kind
192
+ Java::org.cx4a.rsense::CodeCompletionResult::CompletionCandidate::Kind::METHOD
193
+ end
194
+
195
+ def kind_check(constant)
196
+ if constant.class == Java::org.cx4a.rsense.ruby::RubyClass
197
+ Java::org.cx4a.rsense::CodeCompletionResult::CompletionCandidate::Kind::CLASS
198
+ elsif constant.class == Java::org.cx4a.rsense.ruby::RubyModule
199
+ Java::org.cx4a.rsense::CodeCompletionResult::CompletionCandidate::Kind::MODULE
200
+ else
201
+ Java::org.cx4a.rsense::CodeCompletionResult::CompletionCandidate::Kind::CONSTANT
202
+ end
203
+ end
204
+
205
+ def prepare(project)
206
+ @context.project = project
207
+ @context.typeSet = Java::org.cx4a.rsense.typing::TypeSet.new
208
+ @context.main = true
209
+ @type_inference_method.context = @context
210
+ @graph = project.graph
211
+ @graph.addSpecialMethod(Rsense::Server::Command::TYPE_INFERENCE_METHOD_NAME, @type_inference_method)
212
+ @graph.addSpecialMethod("require", @require_method)
213
+ @graph.addSpecialMethod("require_next", @require_next_method)
214
+ load_builtin(project)
215
+ end
216
+
217
+ def clear
218
+ @parser = Rsense::Server::Parser.new
219
+ @context.clear()
220
+ @projects = {}
221
+ @sandbox = Rsense::Server::Project.new("(sandbox)", Pathname.new("."))
222
+ @definitionFinder = Rsense::Server::Listeners::FindDefinitionEventListener.new(@context)
223
+ @whereListener = Rsense::Server::Listeners::WhereEventListener.new(@context)
224
+ open_project(@sandbox)
225
+ prepare_project()
226
+ end
227
+
228
+ def prepare_project()
229
+ if @options.name
230
+ name = @roptions.name
231
+ else
232
+ name = "(sandbox)"
233
+ end
234
+ file = @options.project_path
235
+ @project = Rsense::Server::Project.new(name, file)
236
+ prepare(@project)
237
+ end
238
+
239
+ end
@@ -0,0 +1,70 @@
1
+ require "filetree"
2
+ require "json"
3
+
4
+ module Rsense
5
+ module Server
6
+
7
+ end
8
+ end
9
+
10
+ class Rsense::Server::Config
11
+ attr_accessor :searched, :options, :errors, :port, :ignores
12
+
13
+ def initialize
14
+ @searched = []
15
+ @ignores = []
16
+ @errors = []
17
+ end
18
+
19
+ def search(path_str="~")
20
+ path = FileTree.new(path_str)
21
+ return if @searched.include?(path)
22
+ @searched << path
23
+ conf = path.join(".rsense").expand_path
24
+ unless conf.exist?
25
+ unless path.parent == path
26
+ conf = search(path.parent)
27
+ end
28
+ end
29
+ conf
30
+ end
31
+
32
+ def options(config_path)
33
+ begin
34
+ json_str = JSON.parse(config_path.read)
35
+ rescue JSON::ParserError => e
36
+ @errors << e
37
+ end
38
+ if json_str
39
+ @options ||= Rsense::Server::Options.new(json_str)
40
+ else
41
+ @options ||= Rsense::Server::Options.new({})
42
+ end
43
+ @options
44
+ end
45
+
46
+ def port
47
+ @port ||= check_options("port")
48
+ end
49
+
50
+ def ignores
51
+ if @ignores.empty?
52
+ @ignores << check_options("ignores")
53
+ @ignores.flatten!
54
+ end
55
+ @ignores
56
+ end
57
+
58
+ def check_options(name)
59
+ @options.rest[name] if @options.rest.key?(name)
60
+ end
61
+
62
+ def set_up(path)
63
+ conf = search(path)
64
+ if conf
65
+ options(conf)
66
+ end
67
+ end
68
+
69
+
70
+ end
@@ -0,0 +1,18 @@
1
+ module Rsense
2
+ module Server
3
+ module GemPath
4
+
5
+ module_function
6
+ def paths
7
+ fetch.map do |p|
8
+ p unless p =~ /^file:/
9
+ end
10
+ end
11
+
12
+ def fetch
13
+ Gem.path
14
+ end
15
+
16
+ end
17
+ end
18
+ end