parlour 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/ISSUE_TEMPLATE/bug-report.md +23 -0
- data/.github/ISSUE_TEMPLATE/feature-request.md +20 -0
- data/.travis.yml +5 -0
- data/README.md +66 -7
- data/Rakefile +6 -0
- data/exe/parlour +75 -0
- data/lib/parlour.rb +3 -0
- data/lib/parlour/conflict_resolver.rb +45 -18
- data/lib/parlour/plugin.rb +53 -0
- data/lib/parlour/rbi_generator.rb +28 -2
- data/lib/parlour/rbi_generator/attribute.rb +68 -0
- data/lib/parlour/rbi_generator/class_namespace.rb +49 -13
- data/lib/parlour/rbi_generator/method.rb +123 -31
- data/lib/parlour/rbi_generator/module_namespace.rb +43 -14
- data/lib/parlour/rbi_generator/namespace.rb +264 -32
- data/lib/parlour/rbi_generator/options.rb +37 -1
- data/lib/parlour/rbi_generator/parameter.rb +52 -1
- data/lib/parlour/rbi_generator/rbi_object.rb +116 -3
- data/lib/parlour/version.rb +2 -1
- data/parlour.gemspec +1 -0
- data/plugin_examples/foobar_plugin.rb +13 -0
- metadata +26 -3
@@ -1,6 +1,7 @@
|
|
1
1
|
# typed: true
|
2
2
|
module Parlour
|
3
3
|
class RbiGenerator
|
4
|
+
# Represents a method parameter with a Sorbet type signature.
|
4
5
|
class Parameter
|
5
6
|
extend T::Sig
|
6
7
|
|
@@ -11,6 +12,27 @@ module Parlour
|
|
11
12
|
default: T.nilable(String)
|
12
13
|
).void
|
13
14
|
end
|
15
|
+
# Create a new method parameter.
|
16
|
+
#
|
17
|
+
# @example Create a simple Integer parameter named +num+.
|
18
|
+
# Parlour::RbiGenerator::Parameter.new('num', type: 'Integer')
|
19
|
+
# @example Create a nilable array parameter.
|
20
|
+
# Parlour::RbiGenerator::Parameter.new('array_of_strings_or_symbols', type: 'T.nilable(T::Array(String, Symbol))')
|
21
|
+
# @example Create a block parameter.
|
22
|
+
# Parlour::RbiGenerator::Parameter.new('&blk', type: 'T.proc.void')
|
23
|
+
# @example Create a parameter with a default value.
|
24
|
+
# Parlour::RbiGenerator::Parameter.new('name', type: 'String', default: 'Parlour')
|
25
|
+
#
|
26
|
+
# @param name [String] The name of this parameter. This may start with +*+, +**+,
|
27
|
+
# or +&+, or end with +:+, which will infer the {kind} of this
|
28
|
+
# parameter. (If it contains none of those, {kind} will be +:normal+.)
|
29
|
+
# @param type [String, nil] A Sorbet string of this parameter's type, such as
|
30
|
+
# +"String"+ or +"T.untyped"+.
|
31
|
+
# @param default [String, nil] A string of Ruby code for this parameter's default value.
|
32
|
+
# For example, the default value of an empty string would be represented
|
33
|
+
# as +"\"\""+ (or +'""'+). The default value of the decimal +3.14+
|
34
|
+
# would be +"3.14"+.
|
35
|
+
# @return [void]
|
14
36
|
def initialize(name, type: nil, default: nil)
|
15
37
|
@name = name
|
16
38
|
|
@@ -24,6 +46,11 @@ module Parlour
|
|
24
46
|
end
|
25
47
|
|
26
48
|
sig { params(other: Object).returns(T::Boolean) }
|
49
|
+
# Returns true if this instance is equal to another method.
|
50
|
+
#
|
51
|
+
# @param other [Object] The other instance. If this is not a {Parameter} (or a
|
52
|
+
# subclass of it), this will always return false.
|
53
|
+
# @return [Boolean]
|
27
54
|
def ==(other)
|
28
55
|
Parameter === other &&
|
29
56
|
name == other.name &&
|
@@ -33,9 +60,16 @@ module Parlour
|
|
33
60
|
end
|
34
61
|
|
35
62
|
sig { returns(String) }
|
63
|
+
# The name of this parameter, including any prefixes or suffixes such as
|
64
|
+
# +*+.
|
65
|
+
# @return [String]
|
36
66
|
attr_reader :name
|
37
67
|
|
38
68
|
sig { returns(String) }
|
69
|
+
# The name of this parameter, stripped of any prefixes or suffixes. For
|
70
|
+
# example, +*rest+ would become +rest+, or +foo:+ would become +foo+.
|
71
|
+
#
|
72
|
+
# @return [String]
|
39
73
|
def name_without_kind
|
40
74
|
return T.must(name[0..-2]) if kind == :keyword
|
41
75
|
|
@@ -46,15 +80,28 @@ module Parlour
|
|
46
80
|
end
|
47
81
|
|
48
82
|
sig { returns(T.nilable(String)) }
|
83
|
+
# A Sorbet string of this parameter's type, such as +"String"+ or
|
84
|
+
# +"T.untyped"+.
|
85
|
+
# @return [String, nil]
|
49
86
|
attr_reader :type
|
50
87
|
|
51
88
|
sig { returns(T.nilable(String)) }
|
89
|
+
# A string of Ruby code for this parameter's default value. For example,
|
90
|
+
# the default value of an empty string would be represented as +"\"\""+
|
91
|
+
# (or +'""'+). The default value of the decimal +3.14+ would be +"3.14"+.
|
92
|
+
# @return [String, nil]
|
52
93
|
attr_reader :default
|
53
94
|
|
54
95
|
sig { returns(Symbol) }
|
96
|
+
# The kind of parameter that this is. This will be one of +:normal+,
|
97
|
+
# +:splat+, +:double_splat+, +:block+ or +:keyword+.
|
98
|
+
# @return [Symbol]
|
55
99
|
attr_reader :kind
|
56
100
|
|
57
101
|
sig { returns(String) }
|
102
|
+
# A string of how this parameter should be defined in a method definition.
|
103
|
+
#
|
104
|
+
# @return [String]
|
58
105
|
def to_def_param
|
59
106
|
if default.nil?
|
60
107
|
"#{name}"
|
@@ -66,10 +113,14 @@ module Parlour
|
|
66
113
|
end
|
67
114
|
|
68
115
|
sig { returns(String) }
|
116
|
+
# A string of how this parameter should be defined in a Sorbet +sig+.
|
117
|
+
#
|
118
|
+
# @return [String]
|
69
119
|
def to_sig_param
|
70
120
|
"#{name_without_kind}: #{type || 'T.untyped'}"
|
71
|
-
end
|
121
|
+
end#
|
72
122
|
|
123
|
+
# A mapping of {kind} values to the characteristic prefixes each kind has.
|
73
124
|
PREFIXES = {
|
74
125
|
normal: '',
|
75
126
|
splat: '*',
|
@@ -1,10 +1,76 @@
|
|
1
1
|
# typed: true
|
2
2
|
module Parlour
|
3
3
|
class RbiGenerator
|
4
|
-
|
4
|
+
# An abstract class which is subclassed by any classes which can generate
|
5
|
+
# entire lines of an RBI, such as {Namespace} and {Method}. (As an example,
|
6
|
+
# {Parameter} is _not_ a subclass because it does not generate lines, only
|
7
|
+
# segments of definition and signature lines.)
|
8
|
+
# @abstract
|
9
|
+
class RbiObject
|
5
10
|
extend T::Helpers
|
6
11
|
extend T::Sig
|
7
|
-
|
12
|
+
abstract!
|
13
|
+
|
14
|
+
sig { params(generator: RbiGenerator, name: String).void }
|
15
|
+
# Creates a new RBI object.
|
16
|
+
# @note Don't call this directly.
|
17
|
+
#
|
18
|
+
# @param generator [RbiGenerator] The current RbiGenerator.
|
19
|
+
# @param name [String] The name of this module.
|
20
|
+
# @return [void]
|
21
|
+
def initialize(generator, name)
|
22
|
+
@generator = generator
|
23
|
+
@generated_by = generator.current_plugin
|
24
|
+
@name = name
|
25
|
+
@comments = []
|
26
|
+
end
|
27
|
+
|
28
|
+
sig { returns(RbiGenerator) }
|
29
|
+
# The generator which this object belongs to.
|
30
|
+
# @return [RbiGenerator]
|
31
|
+
attr_reader :generator
|
32
|
+
|
33
|
+
sig { returns(T.nilable(Plugin)) }
|
34
|
+
# The {Plugin} which was controlling the {generator} when this object was
|
35
|
+
# created.
|
36
|
+
# @return [Plugin, nil]
|
37
|
+
attr_reader :generated_by
|
38
|
+
|
39
|
+
sig { returns(String) }
|
40
|
+
# The name of this object.
|
41
|
+
# @return [String]
|
42
|
+
attr_reader :name
|
43
|
+
|
44
|
+
sig { returns(T::Array[String]) }
|
45
|
+
# An array of comments which will be placed above the object in the RBI
|
46
|
+
# file.
|
47
|
+
# @return [Array<String>]
|
48
|
+
attr_reader :comments
|
49
|
+
|
50
|
+
sig { params(comment: T.any(String, T::Array[String])).void }
|
51
|
+
# Adds one or more comments to this RBI object.
|
52
|
+
#
|
53
|
+
# @example Creating a module with a comment.
|
54
|
+
# namespace.create_module('M') do |m|
|
55
|
+
# m.add_comment('This is a module')
|
56
|
+
# end
|
57
|
+
#
|
58
|
+
# @example Creating a class with a multi-line comment.
|
59
|
+
# namespace.create_class('C') do |c|
|
60
|
+
# c.add_comment(['This is a multi-line comment!', 'It can be as long as you want!'])
|
61
|
+
# end
|
62
|
+
#
|
63
|
+
# @param comment [String, Array<String>] The new comment(s).
|
64
|
+
# @return [void]
|
65
|
+
def add_comment(comment)
|
66
|
+
if comment.is_a?(String)
|
67
|
+
comments << comment
|
68
|
+
elsif comment.is_a?(Array)
|
69
|
+
comments.concat(comment)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
alias_method :add_comments, :add_comment
|
8
74
|
|
9
75
|
sig do
|
10
76
|
abstract.params(
|
@@ -12,6 +78,12 @@ module Parlour
|
|
12
78
|
options: Options
|
13
79
|
).returns(T::Array[String])
|
14
80
|
end
|
81
|
+
# Generates the RBI lines for this object.
|
82
|
+
#
|
83
|
+
# @abstract
|
84
|
+
# @param indent_level [Integer] The indentation level to generate the lines at.
|
85
|
+
# @param options [Options] The formatting options to use.
|
86
|
+
# @return [Array<String>] The RBI lines, formatted as specified.
|
15
87
|
def generate_rbi(indent_level, options); end
|
16
88
|
|
17
89
|
sig do
|
@@ -19,6 +91,13 @@ module Parlour
|
|
19
91
|
others: T::Array[RbiGenerator::RbiObject]
|
20
92
|
).returns(T::Boolean)
|
21
93
|
end
|
94
|
+
# Given an array of other objects, returns true if they may be merged
|
95
|
+
# into this instance using {merge_into_self}. Each subclass will have its
|
96
|
+
# own criteria on what allows objects to be mergeable.
|
97
|
+
#
|
98
|
+
# @abstract
|
99
|
+
# @param others [Array<RbiGenerator::RbiObject>] An array of other {RbiObject} instances.
|
100
|
+
# @return [Boolean] Whether this instance may be merged with them.
|
22
101
|
def mergeable?(others); end
|
23
102
|
|
24
103
|
sig do
|
@@ -26,7 +105,41 @@ module Parlour
|
|
26
105
|
others: T::Array[RbiGenerator::RbiObject]
|
27
106
|
).void
|
28
107
|
end
|
108
|
+
# Given an array of other objects, merges them into this one. Each
|
109
|
+
# subclass will do this differently.
|
110
|
+
# You MUST ensure that {mergeable?} is true for those instances.
|
111
|
+
#
|
112
|
+
# @abstract
|
113
|
+
# @param others [Array<RbiGenerator::RbiObject>] An array of other {RbiObject} instances.
|
114
|
+
# @return [void]
|
29
115
|
def merge_into_self(others); end
|
116
|
+
|
117
|
+
sig { abstract.returns(String) }
|
118
|
+
# Returns a human-readable brief string description of this object. This
|
119
|
+
# is displayed during manual conflict resolution with the +parlour+ CLI.
|
120
|
+
#
|
121
|
+
# @abstract
|
122
|
+
# @return [String]
|
123
|
+
def describe; end
|
124
|
+
|
125
|
+
private
|
126
|
+
|
127
|
+
sig do
|
128
|
+
params(
|
129
|
+
indent_level: Integer,
|
130
|
+
options: Options
|
131
|
+
).returns(T::Array[String])
|
132
|
+
end
|
133
|
+
# Generates the RBI lines for this object's comments.
|
134
|
+
#
|
135
|
+
# @param indent_level [Integer] The indentation level to generate the lines at.
|
136
|
+
# @param options [Options] The formatting options to use.
|
137
|
+
# @return [Array<String>] The RBI lines for each comment, formatted as specified.
|
138
|
+
def generate_comments(indent_level, options)
|
139
|
+
comments.any? \
|
140
|
+
? comments.map { |c| options.indented(indent_level, "# #{c}") }
|
141
|
+
: []
|
142
|
+
end
|
30
143
|
end
|
31
144
|
end
|
32
|
-
end
|
145
|
+
end
|
data/lib/parlour/version.rb
CHANGED
data/parlour.gemspec
CHANGED
@@ -23,6 +23,7 @@ Gem::Specification.new do |spec|
|
|
23
23
|
spec.require_paths = ["lib"]
|
24
24
|
|
25
25
|
spec.add_dependency "sorbet-runtime"
|
26
|
+
spec.add_dependency "rainbow", "~> 3.0.0"
|
26
27
|
|
27
28
|
spec.add_development_dependency "bundler", "~> 2.0"
|
28
29
|
spec.add_development_dependency "rake", "~> 10.0"
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'parlour'
|
2
|
+
|
3
|
+
module FooBar
|
4
|
+
class Plugin < Parlour::Plugin
|
5
|
+
def generate(root)
|
6
|
+
root.create_module('Foo') do |foo|
|
7
|
+
foo.add_comment('This is an example plugin!')
|
8
|
+
foo.create_module('Bar')
|
9
|
+
foo.create_module('Bar', interface: true)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: parlour
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aaron Christiansen
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-07-
|
11
|
+
date: 2019-07-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sorbet-runtime
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rainbow
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 3.0.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 3.0.0
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: bundler
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -97,20 +111,28 @@ dependencies:
|
|
97
111
|
description:
|
98
112
|
email:
|
99
113
|
- hello@aaronc.cc
|
100
|
-
executables:
|
114
|
+
executables:
|
115
|
+
- parlour
|
101
116
|
extensions: []
|
102
117
|
extra_rdoc_files: []
|
103
118
|
files:
|
119
|
+
- ".github/ISSUE_TEMPLATE/bug-report.md"
|
120
|
+
- ".github/ISSUE_TEMPLATE/feature-request.md"
|
104
121
|
- ".gitignore"
|
105
122
|
- ".rspec"
|
123
|
+
- ".travis.yml"
|
106
124
|
- CHANGELOG.md
|
107
125
|
- CODE_OF_CONDUCT.md
|
108
126
|
- Gemfile
|
109
127
|
- LICENSE.txt
|
110
128
|
- README.md
|
129
|
+
- Rakefile
|
130
|
+
- exe/parlour
|
111
131
|
- lib/parlour.rb
|
112
132
|
- lib/parlour/conflict_resolver.rb
|
133
|
+
- lib/parlour/plugin.rb
|
113
134
|
- lib/parlour/rbi_generator.rb
|
135
|
+
- lib/parlour/rbi_generator/attribute.rb
|
114
136
|
- lib/parlour/rbi_generator/class_namespace.rb
|
115
137
|
- lib/parlour/rbi_generator/method.rb
|
116
138
|
- lib/parlour/rbi_generator/module_namespace.rb
|
@@ -120,6 +142,7 @@ files:
|
|
120
142
|
- lib/parlour/rbi_generator/rbi_object.rb
|
121
143
|
- lib/parlour/version.rb
|
122
144
|
- parlour.gemspec
|
145
|
+
- plugin_examples/foobar_plugin.rb
|
123
146
|
- sorbet/config
|
124
147
|
- sorbet/rbi/gems/rake.rbi
|
125
148
|
- sorbet/rbi/gems/rspec-core.rbi
|