qdocs 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: dc6b3ccc77bc958c324f4cdc463febbcd6337e7c6b39a51e55f215c187167d80
4
+ data.tar.gz: 503a6012c888d1626a834f1ab95d2fbc194ca9193943ea1595d4e9c732bfd038
5
+ SHA512:
6
+ metadata.gz: 3066dea2b451986c417f12ed8e437c0d6131068a546d30969a305be55cc63ec0044f3ec09add1d650356e321810546a49a84c23ecc9a0219fb408d27deddf9b2
7
+ data.tar.gz: 679cd7f630fd15b4026646cfb60bbb1692fc8ddcbceb8febecf3585a75e86c705fd08c4399fa3556bcdb379829240dc0254f949e242501988c4760530c8d52e6
data/.gitignore ADDED
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ # rspec failure tracking
11
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ # Specify your gem's dependencies in qdocs.gemspec
6
+ gemspec
7
+
8
+ gem "rake", "~> 13.0"
9
+
10
+ gem "rspec", "~> 3.0"
data/Gemfile.lock ADDED
@@ -0,0 +1,38 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ qdocs (0.1.0)
5
+ method_source (~> 1)
6
+ rack (> 1)
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ diff-lcs (1.4.4)
12
+ method_source (1.0.0)
13
+ rack (2.2.3)
14
+ rake (13.0.3)
15
+ rspec (3.10.0)
16
+ rspec-core (~> 3.10.0)
17
+ rspec-expectations (~> 3.10.0)
18
+ rspec-mocks (~> 3.10.0)
19
+ rspec-core (3.10.1)
20
+ rspec-support (~> 3.10.0)
21
+ rspec-expectations (3.10.1)
22
+ diff-lcs (>= 1.2.0, < 2.0)
23
+ rspec-support (~> 3.10.0)
24
+ rspec-mocks (3.10.2)
25
+ diff-lcs (>= 1.2.0, < 2.0)
26
+ rspec-support (~> 3.10.0)
27
+ rspec-support (3.10.2)
28
+
29
+ PLATFORMS
30
+ ruby
31
+
32
+ DEPENDENCIES
33
+ qdocs!
34
+ rake (~> 13.0)
35
+ rspec (~> 3.0)
36
+
37
+ BUNDLED WITH
38
+ 2.1.4
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2021 Joseph Johansen
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,39 @@
1
+ # Qdocs
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/qdocs`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'qdocs'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle install
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install qdocs
22
+
23
+ ## Usage
24
+
25
+ TODO: Write usage instructions here
26
+
27
+ ## Development
28
+
29
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
+
31
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
+
33
+ ## Contributing
34
+
35
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/qdocs.
36
+
37
+ ## License
38
+
39
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task default: :spec
data/bin/console ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require "qdocs"
6
+
7
+ # You can add fixtures and/or initialization code here to make experimenting
8
+ # with your gem easier. You can also use a different console, if you like.
9
+
10
+ # (If you use this, don't forget to add pry to your Gemfile!)
11
+ # require "pry"
12
+ # Pry.start
13
+
14
+ require "irb"
15
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/exe/qdocs ADDED
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'qdocs'
5
+ require 'json'
6
+
7
+ input = ARGV[0]
8
+
9
+ output = nil
10
+
11
+ case input
12
+ when "--version", "-v", "-version"
13
+ puts Qdocs::VERSION
14
+ when "-s", "--server"
15
+ require "qdocs/server"
16
+ when "help", "--help", "-h", "", nil
17
+ puts <<~STR
18
+ Usage:
19
+ qdocs 'String#split' # => info about String's "split" instance method
20
+ qdocs 'String.try_convert' # => info about String's "try_convert" singleton method
21
+ qdocs puts # => info about Object/Kernel method
22
+ qdocs String # => info about String class
23
+ qdocs String/tr/ # => grep for methods matching /tr/ within String
24
+ STR
25
+ else
26
+ begin
27
+ output = Qdocs.lookup(input)
28
+ rescue => e
29
+ abort e.message
30
+ end
31
+ end
32
+
33
+ puts JSON.pretty_generate(output) if output
data/lib/qdocs.rb ADDED
@@ -0,0 +1,144 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'method_source'
4
+ require_relative "qdocs/version"
5
+
6
+ module Qdocs
7
+ class UnknownClassError < StandardError; end
8
+
9
+ class UnknownMethodTypeError < StandardError; end
10
+
11
+ class UnknownMethodError < StandardError; end
12
+
13
+ class UnknownPatternError < StandardError; end
14
+
15
+ module Helpers
16
+ def source_location_to_str(source_location)
17
+ if source_location && source_location.length == 2
18
+ "#{source_location[0]}:#{source_location[1]}"
19
+ end
20
+ end
21
+
22
+ def own_methods(methods)
23
+ methods - Object.methods
24
+ end
25
+
26
+ def params_to_hash(params)
27
+ hsh = {}
28
+ params.each_with_index do |prm, i|
29
+ hsh[prm[1] || "unnamed_arg_#{i}"] = prm[0]
30
+ end
31
+ hsh
32
+ end
33
+
34
+ def find_constant(const)
35
+ case const
36
+ when Symbol, String
37
+ Object.const_get const
38
+ else
39
+ const
40
+ end
41
+ rescue NameError
42
+ raise UnknownClassError, "Unknown constant #{const}"
43
+ end
44
+ end
45
+
46
+ class Const
47
+ include Helpers
48
+
49
+ def show(const)
50
+ const = const.to_s
51
+ constant = find_constant const
52
+
53
+ const_sl = Object.const_source_location const
54
+
55
+ {
56
+ source_location: source_location_to_str(const_sl),
57
+ instance_methods: own_methods(constant.instance_methods).sort,
58
+ singleton_methods: own_methods(constant.methods).sort,
59
+ }
60
+ end
61
+ end
62
+
63
+ class Method
64
+ include Helpers
65
+
66
+ def index(const, pattern)
67
+ constant = find_constant const
68
+ {
69
+ constant: constant,
70
+ singleton_methods: own_methods(constant.methods.grep(pattern)).sort,
71
+ instance_methods: own_methods(constant.instance_methods.grep(pattern)).sort,
72
+ }
73
+ end
74
+
75
+ def show(const, meth, type)
76
+ constant = begin
77
+ find_constant(const)
78
+ rescue UnknownClassError
79
+ abort "Unknown class #{const.inspect}"
80
+ end
81
+ method = case meth
82
+ when Symbol, String
83
+ method_method = case type
84
+ when :instance
85
+ :instance_method
86
+ when :singleton, :class
87
+ :method
88
+ else
89
+ raise UnknownMethodTypeError, "Unknown method type #{type}"
90
+ end
91
+
92
+ begin
93
+ constant.send method_method, meth
94
+ rescue NameError
95
+ raise UnknownMethodError, "No method #{meth.inspect} for #{constant.inspect}. Did you mean #{constant.inspect}/#{meth}/ ?"
96
+ end
97
+ when Method
98
+ meth
99
+ else
100
+ raise InvalidArgumentError, "#{meth.inspect} must be of type Symbol, String, or Method"
101
+ end
102
+
103
+ parameters = params_to_hash(method.parameters)
104
+ src = method.source rescue nil
105
+ source = if src
106
+ lines = src.lines
107
+ first_line = lines.first
108
+ indent_amount = first_line.length - first_line.sub(/^\s*/, '').length
109
+ lines.map { |l| l[indent_amount..-1] }.join
110
+ end
111
+
112
+ {
113
+ defined_at: source_location_to_str(method.source_location),
114
+ source: source,
115
+ arity: method.arity,
116
+ parameters: parameters,
117
+ comment: (method.comment.strip rescue nil),
118
+ name: method.name,
119
+ belongs_to: method.owner,
120
+ super_method: method.super_method,
121
+ }
122
+ end
123
+ end
124
+
125
+ METHOD_REGEXP = /(?:[a-zA-Z_]+|\[\])[?!=]?/.freeze
126
+ CONST_REGEXP = /[[:upper:]]\w*(?:::[[:upper:]]\w*)*/.freeze
127
+
128
+ def self.lookup(input)
129
+ case input
130
+ when /\A([[:lower:]](?:#{METHOD_REGEXP})?)\z/
131
+ Qdocs::Method.new.show(Object, $1, :instance)
132
+ when /\A(#{CONST_REGEXP})\.(#{METHOD_REGEXP})\z/
133
+ Qdocs::Method.new.show($1, $2, :singleton)
134
+ when /\A(#{CONST_REGEXP})#(#{METHOD_REGEXP})\z/
135
+ Qdocs::Method.new.show($1, $2, :instance)
136
+ when /\A(#{CONST_REGEXP})\z/
137
+ Qdocs::Const.new.show($1)
138
+ when %r{\A(#{CONST_REGEXP})/([^/]+)/\z}
139
+ Qdocs::Method.new.index($1, Regexp.new($2))
140
+ else
141
+ raise UnknownPatternError, "Unrecognised pattern #{input}"
142
+ end
143
+ end
144
+ end
@@ -0,0 +1,23 @@
1
+ require "rack"
2
+
3
+ module Qdocs
4
+ class Server
5
+ def call(env)
6
+ req = Rack::Request.new(env)
7
+ params = req.params
8
+ case env["REQUEST_PATH"]
9
+ when "/"
10
+ body = JSON.pretty_generate(Qdocs.lookup(params["input"]))
11
+ [200, { "Content-Type" => "application/json; charset=utf-8" }, [body]]
12
+ else
13
+ [404, { "Content-Type" => "text/html; charset=utf-8" }, ["Not Found"]]
14
+ end
15
+ rescue => e
16
+ [500, { "Content-Type" => "text/html; charset=utf-8" }, ["Error: #{e.message}"]]
17
+ end
18
+ end
19
+ end
20
+
21
+ handler = Rack::Handler::WEBrick
22
+
23
+ handler.run Qdocs::Server.new
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Qdocs
4
+ VERSION = "0.1.0"
5
+ end
data/qdocs.gemspec ADDED
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/qdocs/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "qdocs"
7
+ spec.version = Qdocs::VERSION
8
+ spec.authors = ["Joseph Johansen"]
9
+ spec.email = ["joe@stotles.com"]
10
+
11
+ spec.summary = "A rudimentary ruby language intelligence server"
12
+ spec.description = "A server providing runtime information about constants and methods"
13
+ spec.license = "MIT"
14
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.4.0")
15
+
16
+ spec.metadata["allowed_push_host"] = "https://rubygems.org"
17
+
18
+ spec.metadata["source_code_uri"] = "https://github.com/johansenja/qdocs"
19
+
20
+ # Specify which files should be added to the gem when it is released.
21
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
22
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
23
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{\A(?:test|spec|features)/}) }
24
+ end
25
+ spec.bindir = "exe"
26
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
27
+ spec.require_paths = ["lib"]
28
+
29
+ spec.add_dependency "method_source", "~> 1"
30
+ spec.add_dependency "rack", "> 1"
31
+ end
metadata ADDED
@@ -0,0 +1,88 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: qdocs
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Joseph Johansen
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2021-05-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: method_source
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rack
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">"
32
+ - !ruby/object:Gem::Version
33
+ version: '1'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">"
39
+ - !ruby/object:Gem::Version
40
+ version: '1'
41
+ description: A server providing runtime information about constants and methods
42
+ email:
43
+ - joe@stotles.com
44
+ executables:
45
+ - qdocs
46
+ extensions: []
47
+ extra_rdoc_files: []
48
+ files:
49
+ - ".gitignore"
50
+ - ".rspec"
51
+ - Gemfile
52
+ - Gemfile.lock
53
+ - LICENSE.txt
54
+ - README.md
55
+ - Rakefile
56
+ - bin/console
57
+ - bin/setup
58
+ - exe/qdocs
59
+ - lib/qdocs.rb
60
+ - lib/qdocs/server.rb
61
+ - lib/qdocs/version.rb
62
+ - qdocs.gemspec
63
+ homepage:
64
+ licenses:
65
+ - MIT
66
+ metadata:
67
+ allowed_push_host: https://rubygems.org
68
+ source_code_uri: https://github.com/johansenja/qdocs
69
+ post_install_message:
70
+ rdoc_options: []
71
+ require_paths:
72
+ - lib
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: 2.4.0
78
+ required_rubygems_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ requirements: []
84
+ rubygems_version: 3.1.2
85
+ signing_key:
86
+ specification_version: 4
87
+ summary: A rudimentary ruby language intelligence server
88
+ test_files: []