parlour 2.0.0 → 5.0.0.beta.1

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 (68) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE/bug-report.md +0 -0
  3. data/.github/ISSUE_TEMPLATE/feature-request.md +0 -0
  4. data/.gitignore +1 -1
  5. data/.parlour +5 -0
  6. data/.rspec +0 -0
  7. data/.travis.yml +3 -3
  8. data/CHANGELOG.md +64 -0
  9. data/CODE_OF_CONDUCT.md +0 -0
  10. data/Gemfile +0 -0
  11. data/LICENSE.txt +0 -0
  12. data/README.md +233 -19
  13. data/Rakefile +0 -0
  14. data/exe/parlour +109 -4
  15. data/lib/parlour.rb +29 -1
  16. data/lib/parlour/conflict_resolver.rb +75 -27
  17. data/lib/parlour/conversion/converter.rb +34 -0
  18. data/lib/parlour/conversion/rbi_to_rbs.rb +223 -0
  19. data/lib/parlour/debugging.rb +0 -0
  20. data/lib/parlour/detached_rbi_generator.rb +1 -6
  21. data/lib/parlour/detached_rbs_generator.rb +25 -0
  22. data/lib/parlour/generator.rb +34 -0
  23. data/lib/parlour/kernel_hack.rb +0 -0
  24. data/lib/parlour/options.rb +71 -0
  25. data/lib/parlour/parse_error.rb +0 -0
  26. data/lib/parlour/plugin.rb +1 -1
  27. data/lib/parlour/rbi_generator.rb +24 -37
  28. data/lib/parlour/rbi_generator/arbitrary.rb +5 -2
  29. data/lib/parlour/rbi_generator/attribute.rb +14 -5
  30. data/lib/parlour/rbi_generator/class_namespace.rb +8 -3
  31. data/lib/parlour/rbi_generator/constant.rb +28 -8
  32. data/lib/parlour/rbi_generator/enum_class_namespace.rb +32 -5
  33. data/lib/parlour/rbi_generator/extend.rb +5 -2
  34. data/lib/parlour/rbi_generator/include.rb +5 -2
  35. data/lib/parlour/rbi_generator/method.rb +15 -10
  36. data/lib/parlour/rbi_generator/module_namespace.rb +7 -2
  37. data/lib/parlour/rbi_generator/namespace.rb +115 -27
  38. data/lib/parlour/rbi_generator/parameter.rb +13 -7
  39. data/lib/parlour/rbi_generator/rbi_object.rb +19 -78
  40. data/lib/parlour/rbi_generator/struct_class_namespace.rb +110 -0
  41. data/lib/parlour/rbi_generator/struct_prop.rb +139 -0
  42. data/lib/parlour/rbi_generator/type_alias.rb +101 -0
  43. data/lib/parlour/rbs_generator.rb +24 -0
  44. data/lib/parlour/rbs_generator/arbitrary.rb +92 -0
  45. data/lib/parlour/rbs_generator/attribute.rb +82 -0
  46. data/lib/parlour/rbs_generator/block.rb +49 -0
  47. data/lib/parlour/rbs_generator/class_namespace.rb +106 -0
  48. data/lib/parlour/rbs_generator/constant.rb +95 -0
  49. data/lib/parlour/rbs_generator/extend.rb +92 -0
  50. data/lib/parlour/rbs_generator/include.rb +92 -0
  51. data/lib/parlour/rbs_generator/interface_namespace.rb +34 -0
  52. data/lib/parlour/rbs_generator/method.rb +146 -0
  53. data/lib/parlour/rbs_generator/method_signature.rb +104 -0
  54. data/lib/parlour/rbs_generator/module_namespace.rb +35 -0
  55. data/lib/parlour/rbs_generator/namespace.rb +627 -0
  56. data/lib/parlour/rbs_generator/parameter.rb +145 -0
  57. data/lib/parlour/rbs_generator/rbs_object.rb +78 -0
  58. data/lib/parlour/rbs_generator/type_alias.rb +96 -0
  59. data/lib/parlour/type_loader.rb +30 -10
  60. data/lib/parlour/type_parser.rb +440 -43
  61. data/lib/parlour/typed_object.rb +87 -0
  62. data/lib/parlour/types.rb +445 -0
  63. data/lib/parlour/version.rb +1 -1
  64. data/parlour.gemspec +2 -2
  65. data/plugin_examples/foobar_plugin.rb +0 -0
  66. data/rbi/parlour.rbi +1799 -0
  67. metadata +42 -15
  68. data/lib/parlour/rbi_generator/options.rb +0 -74
@@ -0,0 +1,24 @@
1
+ # typed: true
2
+ module Parlour
3
+ # The RBS generator.
4
+ class RbsGenerator < Generator
5
+ def initialize(**hash)
6
+ super
7
+ @root = RbsGenerator::Namespace.new(self)
8
+ end
9
+
10
+ sig { overridable.returns(RbsGenerator::Namespace) }
11
+ # The root {Namespace} of this generator.
12
+ # @return [Namespace]
13
+ attr_reader :root
14
+
15
+ sig { overridable.returns(String) }
16
+ # Returns the complete contents of the generated RBS file as a string.
17
+ #
18
+ # @return [String] The generated RBS file
19
+ def rbs
20
+ root.generate_rbs(0, options).join("\n")
21
+ end
22
+ end
23
+ end
24
+
@@ -0,0 +1,92 @@
1
+ # typed: true
2
+ module Parlour
3
+ class RbsGenerator < Generator
4
+ # Represents miscellaneous Ruby code.
5
+ class Arbitrary < RbsObject
6
+ sig do
7
+ params(
8
+ generator: Generator,
9
+ code: String,
10
+ block: T.nilable(T.proc.params(x: Arbitrary).void)
11
+ ).void
12
+ end
13
+ # Creates new arbitrary code.
14
+ #
15
+ # @param code [String] The arbitrary code string. Indentation is added to
16
+ # the beginning of each line.
17
+ def initialize(generator, code: '', &block)
18
+ super(generator, '')
19
+ @code = code
20
+ yield_self(&block) if block
21
+ end
22
+
23
+ sig { returns(String) }
24
+ # Returns arbitrary code string.
25
+ attr_accessor :code
26
+
27
+ sig { params(other: Object).returns(T::Boolean) }
28
+ # Returns true if this instance is equal to another arbitrary code line.
29
+ #
30
+ # @param other [Object] The other instance. If this is not a {Arbitrary} (or a
31
+ # subclass of it), this will always return false.
32
+ # @return [Boolean]
33
+ def ==(other)
34
+ Arbitrary === other && code == other.code
35
+ end
36
+
37
+ sig do
38
+ override.params(
39
+ indent_level: Integer,
40
+ options: Options
41
+ ).returns(T::Array[String])
42
+ end
43
+ # Generates the RBS lines for this arbitrary code.
44
+ #
45
+ # @param indent_level [Integer] The indentation level to generate the lines at.
46
+ # @param options [Options] The formatting options to use.
47
+ # @return [Array<String>] The RBS lines, formatted as specified.
48
+ def generate_rbs(indent_level, options)
49
+ code.split("\n").map { |l| options.indented(indent_level, l) }
50
+ end
51
+
52
+ sig do
53
+ override.params(
54
+ others: T::Array[RbsGenerator::RbsObject]
55
+ ).returns(T::Boolean)
56
+ end
57
+ # Given an array of {Arbitrary} instances, returns true if they may be
58
+ # merged into this instance using {merge_into_self}. This is always false.
59
+ #
60
+ # @param others [Array<RbsGenerator::RbsObject>] An array of other
61
+ # {Arbitrary} instances.
62
+ # @return [Boolean] Whether this instance may be merged with them.
63
+ def mergeable?(others)
64
+ false
65
+ end
66
+
67
+ sig do
68
+ override.params(
69
+ others: T::Array[RbsGenerator::RbsObject]
70
+ ).void
71
+ end
72
+ # Given an array of {Arbitrary} instances, merges them into this one.
73
+ # This particular implementation always throws an exception, because
74
+ # {mergeable?} is always false.
75
+ #
76
+ # @param others [Array<RbsGenerator::RbsObject>] An array of other
77
+ # {Arbitrary} instances.
78
+ # @return [void]
79
+ def merge_into_self(others)
80
+ raise 'arbitrary code is never mergeable'
81
+ end
82
+
83
+ sig { override.returns(String) }
84
+ # Returns a human-readable brief string description of this code.
85
+ #
86
+ # @return [String]
87
+ def describe
88
+ "Arbitrary code (#{code})"
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,82 @@
1
+ # typed: true
2
+ module Parlour
3
+ class RbsGenerator < Generator
4
+ # Represents an attribute reader, writer or accessor.
5
+ class Attribute < RbsGenerator::Method
6
+ extend T::Sig
7
+
8
+ sig do
9
+ params(
10
+ generator: Generator,
11
+ name: String,
12
+ kind: Symbol,
13
+ type: Types::TypeLike,
14
+ block: T.nilable(T.proc.params(x: Attribute).void)
15
+ ).void
16
+ end
17
+ # Creates a new attribute.
18
+ # @note You should use {Namespace#create_attribute} rather than this directly.
19
+ #
20
+ # @param generator [RbsGenerator] The current RbsGenerator.
21
+ # @param name [String] The name of this attribute.
22
+ # @param kind [Symbol] The kind of attribute this is; one of :writer, :reader or
23
+ # :accessor.
24
+ # @param type [String, Types::Type] This attribute's type.
25
+ # @param block A block which the new instance yields itself to.
26
+ # @return [void]
27
+ def initialize(generator, name, kind, type, &block)
28
+ @type = type
29
+ @kind = kind
30
+ case kind
31
+ when :accessor, :reader
32
+ super(generator, name, [MethodSignature.new([], type)], &block)
33
+ when :writer
34
+ super(generator, name, [MethodSignature.new([
35
+ Parameter.new(name, type: type)
36
+ ], type)], &block)
37
+ else
38
+ raise 'unknown kind'
39
+ end
40
+ end
41
+
42
+ sig { returns(Symbol) }
43
+ # The kind of attribute this is; one of +:writer+, +:reader+, or +:accessor+.
44
+ # @return [Symbol]
45
+ attr_reader :kind
46
+
47
+ sig { returns(Types::TypeLike) }
48
+ # The type of this attribute.
49
+ attr_reader :type
50
+
51
+ sig do
52
+ override.params(
53
+ indent_level: Integer,
54
+ options: Options
55
+ ).returns(T::Array[String])
56
+ end
57
+ # Generates the RBS lines for this arbstrary code.
58
+ #
59
+ # @param indent_level [Integer] The indentation level to generate the lines at.
60
+ # @param options [Options] The formatting options to use.
61
+ # @return [Array<String>] The RBS lines, formatted as specified.
62
+ def generate_rbs(indent_level, options)
63
+ [options.indented(
64
+ indent_level,
65
+ "attr_#{kind} #{name}: #{String === @type ? @type : @type.generate_rbs}"
66
+ )]
67
+ end
68
+
69
+ sig { override.params(other: Object).returns(T::Boolean) }
70
+ # Returns true if this instance is equal to another attribute.
71
+ #
72
+ # @param other [Object] The other instance. If this is not a {Attribute}
73
+ # (or a subclass of it), this will always return false.
74
+ # @return [Boolean]
75
+ def ==(other)
76
+ T.must(
77
+ super(other) && Attribute === other && kind == other.kind
78
+ )
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,49 @@
1
+ # typed: true
2
+ module Parlour
3
+ class RbsGenerator < Generator
4
+ # Represents a block in a method signature.
5
+ # (This is not an RbsObject because it doesn't generate a full line.)
6
+ class Block
7
+ extend T::Sig
8
+
9
+ sig { params(type: Types::Proc, required: T::Boolean).void }
10
+ # Creates a new block for a method signature.
11
+ #
12
+ # @param type [Types::Proc] The type of this block.
13
+ # @param required [T::Boolean] Whether this block is required.
14
+ def initialize(type, required)
15
+ @type = type
16
+ @required = required
17
+ end
18
+
19
+ sig { overridable.params(other: Object).returns(T::Boolean).checked(:never) }
20
+ # Returns true if this instance is equal to another method signature.
21
+ #
22
+ # @param other [Object] The other instance. If this is not a {MethodSignature} (or a
23
+ # subclass of it), this will always return false.
24
+ # @return [Boolean]
25
+ def ==(other)
26
+ Block === other && type == other.type && required == other.required
27
+ end
28
+
29
+ sig { returns(Types::Proc) }
30
+ # The type of this block.
31
+ # @return [Types::Proc]
32
+ attr_reader :type
33
+
34
+ sig { returns(T::Boolean) }
35
+ # Whether this block is required.
36
+ # @return [Boolean]
37
+ attr_reader :required
38
+
39
+ sig { params(options: Options).returns(T::Array[String]) }
40
+ # Generates the RBS string for this signature.
41
+ #
42
+ # @param options [Options] The formatting options to use.
43
+ # @return [Array<String>] The RBS string, formatted as specified.
44
+ def generate_rbs(options)
45
+ ["#{required ? '' : '?'}{ #{type.generate_rbs} }"]
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,106 @@
1
+ # typed: true
2
+ module Parlour
3
+ class RbsGenerator < Generator
4
+ # Represents a class definition.
5
+ class ClassNamespace < Namespace
6
+ extend T::Sig
7
+
8
+ sig do
9
+ params(
10
+ generator: Generator,
11
+ name: String,
12
+ superclass: T.nilable(Types::TypeLike),
13
+ block: T.nilable(T.proc.params(x: ClassNamespace).void)
14
+ ).void
15
+ end
16
+ # Creates a new class definition.
17
+ # @note You should use {Namespace#create_class} rather than this directly.
18
+ #
19
+ # @param generator [RbsGenerator] The current RbsGenerator.
20
+ # @param name [String] The name of this class.
21
+ # @param final [Boolean] Whether this namespace is final.
22
+ # @param superclass [String, nil] The superclass of this class, or nil if it doesn't
23
+ # have one.
24
+ # @param abstract [Boolean] A boolean indicating whether this class is abstract.
25
+ # @param block A block which the new instance yields itself to.
26
+ # @return [void]
27
+ def initialize(generator, name, superclass, &block)
28
+ super(generator, name, &block)
29
+ @superclass = superclass
30
+ end
31
+
32
+ sig do
33
+ override.params(
34
+ indent_level: Integer,
35
+ options: Options
36
+ ).returns(T::Array[String])
37
+ end
38
+ def generate_rbs(indent_level, options)
39
+ class_definition = @superclass.nil? \
40
+ ? "class #{name}"
41
+ : "class #{name} < #{String === @superclass ? @superclass : @superclass.generate_rbs}"
42
+
43
+ lines = generate_comments(indent_level, options)
44
+ lines << options.indented(indent_level, class_definition)
45
+ lines += generate_body(indent_level + 1, options)
46
+ lines << options.indented(indent_level, "end")
47
+ end
48
+
49
+ sig { returns(T.nilable(Types::TypeLike)) }
50
+ # The superclass of this class, or nil if it doesn't have one.
51
+ # @return [Types::TypeLike, nil]
52
+ attr_reader :superclass
53
+
54
+ sig do
55
+ override.params(
56
+ others: T::Array[RbsGenerator::RbsObject]
57
+ ).returns(T::Boolean)
58
+ end
59
+ # Given an array of {Namespace} instances, returns true if they may
60
+ # be merged into this instance using {merge_into_self}. For instances to
61
+ # be mergeable, they must either all be abstract or all not be abstract,
62
+ # and they must define the same superclass (or none at all).
63
+ #
64
+ # @param others [Array<RbsGenerator::RbsObject>] An array of other {Namespace} instances.
65
+ # @return [Boolean] Whether this instance may be merged with them.
66
+ def mergeable?(others)
67
+ others = T.cast(others, T::Array[Namespace]) rescue (return false)
68
+ all = others + [self]
69
+
70
+ all_classes = T.cast(all.select { |x| ClassNamespace === x }, T::Array[ClassNamespace])
71
+
72
+ all_classes.map(&:superclass).compact.uniq.length <= 1
73
+ end
74
+
75
+ sig do
76
+ override.params(
77
+ others: T::Array[RbsGenerator::RbsObject]
78
+ ).void
79
+ end
80
+ # Given an array of {ClassNamespace} instances, merges them into this one.
81
+ # You MUST ensure that {mergeable?} is true for those instances.
82
+ #
83
+ # @param others [Array<RbsGenerator::RbsObject>] An array of other {ClassNamespace} instances.
84
+ # @return [void]
85
+ def merge_into_self(others)
86
+ super
87
+
88
+ others.each do |other|
89
+ next unless ClassNamespace === other
90
+ other = T.cast(other, ClassNamespace)
91
+
92
+ @superclass = other.superclass unless superclass
93
+ end
94
+ end
95
+
96
+ sig { override.returns(String) }
97
+ # Returns a human-readable brief string description of this class.
98
+ # @return [String]
99
+ def describe
100
+ "Class #{name} - #{"superclass #{superclass}, " if superclass}" +
101
+ "#{children.length} children, " +
102
+ "#{includes.length} includes, #{extends.length} extends"
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,95 @@
1
+ # typed: true
2
+ module Parlour
3
+ class RbsGenerator < Generator
4
+ # Represents a constant definition.
5
+ class Constant < RbsObject
6
+ sig do
7
+ params(
8
+ generator: Generator,
9
+ name: String,
10
+ type: Types::TypeLike,
11
+ block: T.nilable(T.proc.params(x: Constant).void)
12
+ ).void
13
+ end
14
+ # Creates a new constant definition.
15
+ #
16
+ # @param name [String] The name of the constant.
17
+ # @param value [String] The value of the constant, as a Ruby code string.
18
+ # eigenclass of the current namespace.
19
+ def initialize(generator, name, type:, &block)
20
+ super(generator, name)
21
+ @type = type
22
+ yield_self(&block) if block
23
+ end
24
+
25
+ # @return [Types::TypeLike] The type of the constant.
26
+ sig { returns(Types::TypeLike) }
27
+ attr_reader :type
28
+
29
+ sig { params(other: Object).returns(T::Boolean) }
30
+ # Returns true if this instance is equal to another extend.
31
+ #
32
+ # @param other [Object] The other instance. If this is not a {Extend} (or a
33
+ # subclass of it), this will always return false.
34
+ # @return [Boolean]
35
+ def ==(other)
36
+ Constant === other && name == other.name && type == other.type
37
+ end
38
+
39
+ sig do
40
+ override.params(
41
+ indent_level: Integer,
42
+ options: Options
43
+ ).returns(T::Array[String])
44
+ end
45
+ # Generates the RBS lines for this constant.
46
+ #
47
+ # @param indent_level [Integer] The indentation level to generate the lines at.
48
+ # @param options [Options] The formatting options to use.
49
+ # @return [Array<String>] The RBS lines, formatted as specified.
50
+ def generate_rbs(indent_level, options)
51
+ [options.indented(indent_level, "#{name}: #{String === @type ? @type : @type.generate_rbs}")]
52
+ end
53
+
54
+ sig do
55
+ override.params(
56
+ others: T::Array[RbsGenerator::RbsObject]
57
+ ).returns(T::Boolean)
58
+ end
59
+ # Given an array of {Constant} instances, returns true if they may be
60
+ # merged into this instance using {merge_into_self}. This is always false.
61
+ #
62
+ # @param others [Array<RbsGenerator::RbsObject>] An array of other
63
+ # {Constant} instances.
64
+ # @return [Boolean] Whether this instance may be merged with them.
65
+ def mergeable?(others)
66
+ others.all? { |other| self == other }
67
+ end
68
+
69
+ sig do
70
+ override.params(
71
+ others: T::Array[RbsGenerator::RbsObject]
72
+ ).void
73
+ end
74
+ # Given an array of {Constant} instances, merges them into this one.
75
+ # This particular implementation will simply do nothing, as instances
76
+ # are only mergeable if they are indentical.
77
+ # You MUST ensure that {mergeable?} is true for those instances.
78
+ #
79
+ # @param others [Array<RbsGenerator::RbsObject>] An array of other
80
+ # {Extend} instances.
81
+ # @return [void]
82
+ def merge_into_self(others)
83
+ # We don't need to change anything! We only merge identical constants
84
+ end
85
+
86
+ sig { override.returns(String) }
87
+ # Returns a human-readable brief string description of this code.
88
+ #
89
+ # @return [String]
90
+ def describe
91
+ "Constant (#{name} = #{type})"
92
+ end
93
+ end
94
+ end
95
+ end