rbs2ts 1.0.0.pre.alpha.4 → 1.3.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 19a2022b86feae5d562c59457ea77de37ef3a94f6c32b2b148f278610cf3e64d
4
- data.tar.gz: 94639b023729996b58f6a7ed7f59cbfe58b7738e820ea70fb100ad9e7f079690
3
+ metadata.gz: bce4c75f9675cfc5cccfac710ac9547d5c33153e76e5ef1299bc1f1808612f05
4
+ data.tar.gz: c550da676c3b095c07438e7085f176f8fa150d061ba10803ea9bb0805917067d
5
5
  SHA512:
6
- metadata.gz: 918d61866526af2f4d258fe349c5617dfc65d799086fff57fb32bfa2e6104713fed20558dd2e451ba09c860316aedb07f6637a5cdd650babfa477a61ca490f78
7
- data.tar.gz: 5fd2d4d0c042f9a226f89dd8867d48464ccae74333afb5f77e437eb793f5db85ae2882c49ac600f2abd8caf7f8e948d9cefa23b28ce30b4b8cb54dc8d663321d
6
+ metadata.gz: 34aa7a35786539f22d03e58e25902fdc4a074bd76bc1b54d05dc2a52b9bb1864e27f4a2a1eea916fb6e06e62a1371b9490b40e117f119dd70bb31b250c010769
7
+ data.tar.gz: 76ba38c3514225a63ecd288d17891281c5b1b90a1edea1e8a655b3d91357a62eb6b8c02fa100c93e4505d5819ac8526dfd0d2fc87e9f9eec7dae65633eb15518
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Rbs2ts
2
2
 
3
- Convert RBS to TypeScript type definition.
3
+ A RubyGem that converts Ruby RBS to TypeScript definitions.
4
4
 
5
5
  ## Installation
6
6
 
@@ -33,8 +33,8 @@ type StringLiteral = 'abc'
33
33
  type TrueLiteral = true
34
34
  type FalseLiteral = false
35
35
 
36
- type UnionType = String & Integer & Bool
37
- type IntersectionType = String | Integer | Bool
36
+ type IntersectionType = String & Integer & Bool
37
+ type UnionType = String | Integer | Bool
38
38
 
39
39
  type ArrayType = Array[String]
40
40
 
@@ -52,6 +52,7 @@ type RecordType = {
52
52
  }
53
53
 
54
54
  class Klass
55
+ @val: String
55
56
  attr_accessor a: String
56
57
  attr_reader b: Integer
57
58
  attr_writer c: Bool
@@ -64,8 +65,44 @@ class Klass
64
65
  }?
65
66
  }
66
67
 
67
- def to_s: () -> String
68
- def tuple: () -> [{ s: String, f: Float }?]
68
+ def to_tuple: () -> [{ s: String, f: Float }?]
69
+ def required_positional: (String) -> void
70
+ def required_positional_name: (String str) -> void
71
+ def optional_positional: (?String) -> void
72
+ def optional_positional_name: (?String? str) -> void
73
+ def rest_positional: (*String) -> void
74
+ def rest_positional_name: (*String str) -> void
75
+ def rest_positional_with_trailing: (*String, Integer) -> void
76
+ def rest_positional_name_with_trailing: (*String str, Integer trailing) -> void
77
+ def required_keyword: (str: String) -> void
78
+ def optional_keyword: (?str: String?) -> void
79
+ def rest_keywords: (**String) -> void
80
+ def rest_keywords_name: (**String rest) -> void
81
+
82
+ def all_arguments: (
83
+ String required_positional,
84
+ ?Integer? optional_positional,
85
+ *String rest_positionals_s,
86
+ Integer trailing_positional_s,
87
+ required_keyword: String,
88
+ ?optional_keyword: Integer?,
89
+ **String rest_keywords
90
+ ) -> [{ s: String, f: Float }?]
91
+ end
92
+
93
+ module Module
94
+ @val: String
95
+ type AliasType = String
96
+
97
+ def func: (String, Integer) -> { str: String, int: Integer }
98
+
99
+ class NestedClass
100
+ attr_accessor a: AliasType
101
+ end
102
+ end
103
+
104
+ interface _Interface
105
+ def func: (String, Integer) -> { str: String, int: Integer }
69
106
  end
70
107
  ```
71
108
 
@@ -96,9 +133,9 @@ export type TrueLiteral = true;
96
133
 
97
134
  export type FalseLiteral = false;
98
135
 
99
- export type UnionType = string & number & boolean;
136
+ export type IntersectionType = string & number & boolean;
100
137
 
101
- export type IntersectionType = string | number | boolean;
138
+ export type UnionType = string | number | boolean;
102
139
 
103
140
  export type ArrayType = string[];
104
141
 
@@ -116,34 +153,56 @@ export type RecordType = {
116
153
  } | null | undefined;
117
154
  };
118
155
 
119
- export namespace Klass {
120
- export type a = string;
121
- export type b = number;
122
- export type r = {
156
+ export declare class Klass {
157
+ val: string;
158
+ a: string;
159
+ readonly b: number;
160
+ c: boolean;
161
+ readonly r: {
123
162
  d: string;
124
163
  e: {
125
164
  f: string;
126
165
  g: string | null | undefined;
127
166
  } | null | undefined;
128
167
  };
129
- export type toSReturnType = string;
130
- export type tupleReturnType = [({
168
+ toTuple(): [({
169
+ s: string;
170
+ f: number;
171
+ } | null | undefined)];
172
+ requiredPositional(arg1: string): void;
173
+ requiredPositionalName(str: string): void;
174
+ optionalPositional(arg1?: string): void;
175
+ optionalPositionalName(str?: string | null | undefined): void;
176
+ restPositional(...arg1: string[]): void;
177
+ restPositionalName(...str: string[]): void;
178
+ restPositionalWithTrailing(arg1: string[], arg2: number): void;
179
+ restPositionalNameWithTrailing(str: string[], trailing: number): void;
180
+ requiredKeyword(arg1: { str: string }): void;
181
+ optionalKeyword(arg1: { str?: string | null | undefined }): void;
182
+ restKeywords(arg1: { [key: string]: unknown; }): void;
183
+ restKeywordsName(arg1: { [key: string]: unknown; }): void;
184
+ allArguments(requiredPositional: string, optionalPositional?: number | null | undefined, restPositionalsS?: string[], trailingPositionalS?: number, arg1?: { requiredKeyword: string, optionalKeyword?: number | null | undefined, [key: string]: unknown; }): [({
131
185
  s: string;
132
186
  f: number;
133
187
  } | null | undefined)];
134
188
  };
135
- ```
136
-
137
- ---
138
189
 
139
- ## ToDo
190
+ export namespace Module {
191
+ export declare let val: string;
192
+ export type AliasType = string;
193
+ export declare function func(arg1: string, arg2: number): {
194
+ str: string;
195
+ int: number;
196
+ };
197
+ export declare class NestedClass {
198
+ a: AliasType;
199
+ };
200
+ };
140
201
 
141
- - [x] Literal type
142
- - [ ] Interface type
143
- - [x] Literal type
144
- - [x] Tuple Type
145
- - [x] Base Types
146
- - [x] Method Type (Argument Types and Return Types)
147
- - [x] Class declaration
148
- - [ ] Module declaration
149
- - [ ] Interface declaration
202
+ export interface Interface {
203
+ func(arg1: string, arg2: number): {
204
+ str: string;
205
+ int: number;
206
+ };
207
+ };
208
+ ```
@@ -3,5 +3,7 @@ end
3
3
 
4
4
  require 'case_transform'
5
5
 
6
+ require 'rbs2ts/converter/helper'
6
7
  require 'rbs2ts/converter/declarations'
7
8
  require 'rbs2ts/converter/types'
9
+ require 'rbs2ts/converter/members'
@@ -11,6 +11,10 @@ module Rbs2ts
11
11
  case d
12
12
  when ::RBS::AST::Declarations::Class then
13
13
  Converter::Declarations::Class.new(d).to_ts
14
+ when ::RBS::AST::Declarations::Module then
15
+ Converter::Declarations::Module.new(d).to_ts
16
+ when ::RBS::AST::Declarations::Interface then
17
+ Converter::Declarations::Interface.new(d).to_ts
14
18
  when ::RBS::AST::Declarations::Alias then
15
19
  Converter::Declarations::Alias.new(d).to_ts
16
20
  end
@@ -31,34 +35,23 @@ module Rbs2ts
31
35
  end
32
36
 
33
37
  def name
34
- declaration.name.to_s.gsub(/:/, '')
38
+ declaration.name.name.to_s
35
39
  end
36
40
 
37
41
  private
38
42
 
39
43
  attr_reader :declaration
40
44
  end
41
-
42
- class Class < Base
43
- INDENT = ' '
44
- @@nest = 0
45
45
 
46
+ class Class < Base
46
47
  def to_ts
47
- @@nest = @@nest + 1
48
-
49
48
  members_ts = declaration.members.map {|member|
50
- ts = member_to_ts(member)
51
- ts
52
- .split("\n")
53
- .map {|t| "#{INDENT * @@nest}#{t}" }
54
- .join("\n")
49
+ member_to_ts(member)
55
50
  }.reject(&:empty?).join("\n")
56
51
 
57
- @@nest = @@nest - 1
58
-
59
52
  <<~TS
60
- export namespace #{name} {
61
- #{members_ts}
53
+ export declare class #{Converter::Helper.convert_name(name)} {
54
+ #{Helper.indent(members_ts)}
62
55
  };
63
56
  TS
64
57
  .chomp
@@ -66,10 +59,16 @@ module Rbs2ts
66
59
 
67
60
  def member_to_ts(member)
68
61
  case member
69
- when ::RBS::AST::Members::AttrReader, ::RBS::AST::Members::AttrAccessor then
70
- "export type #{CaseTransform.camel_lower(member.name)} = #{Converter::Types::Resolver.to_ts(member.type)};"
62
+ when ::RBS::AST::Members::InstanceVariable then
63
+ Converter::Members::InstanceVariable.new(member).to_ts
64
+ when ::RBS::AST::Members::AttrReader then
65
+ Converter::Members::AttrReader.new(member).to_ts
66
+ when ::RBS::AST::Members::AttrWriter then
67
+ Converter::Members::AttrWriter.new(member).to_ts
68
+ when ::RBS::AST::Members::AttrAccessor then
69
+ Converter::Members::AttrAccessor.new(member).to_ts
71
70
  when ::RBS::AST::Members::MethodDefinition
72
- "export type #{CaseTransform.camel_lower(member.name)}ReturnType = #{Converter::Types::Resolver.to_ts(member.types.first.type.return_type)};"
71
+ Converter::Members::MethodDefinition.new(member).to_ts
73
72
  else
74
73
  ''
75
74
  end
@@ -77,14 +76,68 @@ module Rbs2ts
77
76
  end
78
77
 
79
78
  class Module < Base
79
+ def to_ts
80
+ members_ts = declaration.members.map {|member|
81
+ member_to_ts(member)
82
+ }.reject(&:empty?).join("\n")
83
+
84
+ <<~TS
85
+ export namespace #{Converter::Helper.convert_name(name)} {
86
+ #{Helper.indent(members_ts)}
87
+ };
88
+ TS
89
+ .chomp
90
+ end
91
+
92
+ def member_to_ts(member)
93
+ case member
94
+ when ::RBS::AST::Declarations::Class then
95
+ Converter::Declarations::Class.new(member).to_ts
96
+ when ::RBS::AST::Declarations::Module then
97
+ Converter::Declarations::Module.new(member).to_ts
98
+ when ::RBS::AST::Declarations::Interface then
99
+ Converter::Declarations::Interface.new(member).to_ts
100
+ when ::RBS::AST::Declarations::Alias then
101
+ Converter::Declarations::Alias.new(member).to_ts
102
+ when ::RBS::AST::Members::InstanceVariable
103
+ ts = Converter::Members::InstanceVariable.new(member).to_ts
104
+ "export declare let #{ts}"
105
+ when ::RBS::AST::Members::MethodDefinition
106
+ ts = Converter::Members::MethodDefinition.new(member).to_ts
107
+ "export declare function #{ts}"
108
+ else
109
+ ''
110
+ end
111
+ end
80
112
  end
81
113
 
82
114
  class Interface < Base
115
+ def to_ts
116
+ members_ts = declaration.members.map {|member|
117
+ member_to_ts(member)
118
+ }.reject(&:empty?).join("\n")
119
+
120
+ <<~TS
121
+ export interface #{Converter::Helper.convert_name(name.gsub(/_/, ''))} {
122
+ #{Helper.indent(members_ts)}
123
+ };
124
+ TS
125
+ .chomp
126
+ end
127
+
128
+ def member_to_ts(member)
129
+ case member
130
+ when ::RBS::AST::Members::MethodDefinition
131
+ Converter::Members::MethodDefinition.new(member).to_ts
132
+ else
133
+ ''
134
+ end
135
+ end
83
136
  end
84
137
 
85
138
  class Alias < Base
86
139
  def to_ts
87
- "export type #{name} = #{Converter::Types::Resolver.to_ts(declaration.type)};"
140
+ "export type #{Converter::Helper.convert_name(name)} = #{Converter::Types::Resolver.to_ts(declaration.type)};"
88
141
  end
89
142
  end
90
143
 
@@ -0,0 +1,38 @@
1
+ module Rbs2ts
2
+ module Converter
3
+ module Helper
4
+ class << self
5
+ INDENT = ' '
6
+
7
+ def indent(text, level = 1)
8
+ text
9
+ .split("\n")
10
+ .map {|t| "#{INDENT * level}#{t}" }
11
+ .join("\n")
12
+ end
13
+
14
+ TS_RESERVED_WORDS = %w(
15
+ any as boolean break case catch class const constructor continue debugger declare
16
+ default delete do else enum export extends false finally for from function get if
17
+ implements import in instanceof interface let module new null number of package
18
+ private protected public require return set static string super switch symbol
19
+ this throw true try type typeof var void while with yield
20
+ )
21
+
22
+ def convert_name(org_name)
23
+ name = org_name.to_s.gsub(/[:@]/, '')
24
+
25
+ unless name =~ /^[A-Z]/
26
+ name = CaseTransform.camel_lower(name)
27
+ end
28
+
29
+ if TS_RESERVED_WORDS.include?(name)
30
+ "#{name}Type"
31
+ else
32
+ name
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,146 @@
1
+ module Rbs2ts
2
+ module Converter
3
+ module Members
4
+ class Base
5
+ def initialize(member)
6
+ @member = member
7
+ end
8
+
9
+ def to_ts
10
+ ''
11
+ end
12
+
13
+ def name
14
+ Converter::Helper.convert_name(member.name)
15
+ end
16
+
17
+ private
18
+
19
+ attr_reader :member
20
+ end
21
+
22
+ class InstanceVariable < Base
23
+ def to_ts
24
+ "#{name}: #{Converter::Types::Resolver.to_ts(member.type)};"
25
+ end
26
+ end
27
+
28
+ class AttrReader < Base
29
+ def to_ts
30
+ "readonly #{name}: #{Converter::Types::Resolver.to_ts(member.type)};"
31
+ end
32
+ end
33
+
34
+ class AttrWriter < Base
35
+ def to_ts
36
+ "#{name}: #{Converter::Types::Resolver.to_ts(member.type)};"
37
+ end
38
+ end
39
+
40
+ class AttrAccessor < Base
41
+ def to_ts
42
+ "#{name}: #{Converter::Types::Resolver.to_ts(member.type)};"
43
+ end
44
+ end
45
+
46
+ class MethodDefinition < Base
47
+ def initialize(member)
48
+ super
49
+ @args_count = 0
50
+ end
51
+
52
+ def to_ts
53
+ "#{name}(#{args_to_ts}): #{return_type_to_ts};"
54
+ end
55
+
56
+ def args_to_ts
57
+ [
58
+ *required_positional_to_ts,
59
+ *optional_positional_to_ts,
60
+ *rest_positionals_to_ts,
61
+ *trailing_positionals_to_ts,
62
+ *keyword_args_to_ts
63
+ ].join(", ")
64
+ end
65
+
66
+ def arg_name(arg)
67
+ name = arg.name.nil? ? next_default_arg_name : arg.name.to_s
68
+ CaseTransform.camel_lower(name)
69
+ end
70
+
71
+ def next_default_arg_name
72
+ @args_count = @args_count + 1
73
+ "arg#{@args_count.to_s}"
74
+ end
75
+
76
+ def required_positional_to_ts
77
+ method_type.required_positionals.map {|arg|
78
+ "#{arg_name(arg)}: #{Converter::Types::Resolver.to_ts(arg.type)}"
79
+ }
80
+ end
81
+
82
+ def optional_positional_to_ts
83
+ method_type.optional_positionals.map {|arg|
84
+ "#{arg_name(arg)}?: #{Converter::Types::Resolver.to_ts(arg.type)}"
85
+ }
86
+ end
87
+
88
+ def rest_positionals_to_ts
89
+ arg = method_type.rest_positionals
90
+
91
+ return [] if arg.nil?
92
+
93
+ has_rest_after_arguments ?
94
+ ["#{arg_name(arg)}#{optional_ts_code}: #{Converter::Types::Resolver.to_ts(arg.type)}[]"] :
95
+ ["...#{arg_name(arg)}#{optional_ts_code}: #{Converter::Types::Resolver.to_ts(arg.type)}[]"]
96
+ end
97
+
98
+ def trailing_positionals_to_ts
99
+ method_type.trailing_positionals.map {|arg|
100
+ "#{arg_name(arg)}#{optional_ts_code}: #{Converter::Types::Resolver.to_ts(arg.type)}"
101
+ }
102
+ end
103
+
104
+ def keyword_args_to_ts
105
+ required_keywords_ts = method_type.required_keywords.map {|key, value|
106
+ "#{CaseTransform.camel_lower(key.to_s)}: #{Converter::Types::Resolver.to_ts(value.type)}"
107
+ }
108
+ optional_keywords_ts = method_type.optional_keywords.map {|key, value|
109
+ "#{CaseTransform.camel_lower(key.to_s)}?: #{Converter::Types::Resolver.to_ts(value.type)}"
110
+ }
111
+ rest_keywords_ts = method_type.rest_keywords.nil? ? [] : ["[key: string]: unknown;"]
112
+
113
+ ts_array = [
114
+ *required_keywords_ts,
115
+ *optional_keywords_ts,
116
+ *rest_keywords_ts
117
+ ]
118
+
119
+ return [] if ts_array.empty?
120
+
121
+ ts = ts_array.join(', ')
122
+
123
+ ["#{next_default_arg_name}#{optional_ts_code}: { #{ts} }"]
124
+ end
125
+
126
+ def method_type
127
+ member.types.first.type
128
+ end
129
+
130
+ def return_type_to_ts
131
+ Converter::Types::Resolver.to_ts(method_type.return_type)
132
+ end
133
+
134
+ def optional_ts_code
135
+ method_type.optional_positionals.present? ? '?' : ''
136
+ end
137
+
138
+ def has_rest_after_arguments
139
+ method_type.trailing_positionals.present? ||
140
+ method_type.required_keywords.present? ||
141
+ method_type.optional_keywords.present?
142
+ end
143
+ end
144
+ end
145
+ end
146
+ end
@@ -46,27 +46,19 @@ module Rbs2ts
46
46
  end
47
47
 
48
48
  class Record < ConverterBase
49
- INDENT = ' '
50
- @@nest = 0
51
-
52
49
  def to_ts
53
- @@nest = @@nest + 1
54
-
55
- indent = INDENT * @@nest
56
50
  field_lines = type.fields.map { |name, type|
57
- "#{indent}#{CaseTransform.camel_lower(name.to_s)}: #{Types::Resolver.to_ts(type)};"
51
+ "#{Converter::Helper.convert_name(name)}: #{Types::Resolver.to_ts(type)};"
58
52
  }
59
53
 
60
- @@nest = @@nest - 1
61
-
62
54
  return '{}' if field_lines.empty?
63
55
 
64
56
  field_ts = field_lines.join("\n")
65
57
 
66
58
  ts = <<~CODE
67
59
  {
68
- #{field_ts}
69
- #{INDENT * @@nest}}
60
+ #{Helper.indent(field_ts)}
61
+ }
70
62
  CODE
71
63
 
72
64
  ts.chomp
@@ -144,7 +136,7 @@ module Rbs2ts
144
136
  when 'Bool' then
145
137
  Types::Bool.new(type).to_ts
146
138
  else
147
- type.name.to_s.gsub(/:/, '')
139
+ Converter::Helper.convert_name(type.name.name)
148
140
  end
149
141
  end
150
142
  end
@@ -1,3 +1,3 @@
1
1
  module Rbs2ts
2
- VERSION = "1.0.0-alpha.4"
2
+ VERSION = "1.3.1"
3
3
  end
@@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
9
9
  spec.authors = ["mugi-uno"]
10
10
  spec.email = ["mugi.uno@gmail.com"]
11
11
 
12
- spec.summary = "Convert rbs to typescript"
12
+ spec.summary = "A RubyGem that converts Ruby RBS to TypeScript definitions."
13
13
  spec.homepage = "https://github.com/mugi-uno/rbs2ts"
14
14
  spec.license = "MIT"
15
15
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rbs2ts
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.pre.alpha.4
4
+ version: 1.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - mugi-uno
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-01-17 00:00:00.000000000 Z
11
+ date: 2021-01-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rbs
@@ -118,6 +118,8 @@ files:
118
118
  - lib/rbs2ts/cli.rb
119
119
  - lib/rbs2ts/converter.rb
120
120
  - lib/rbs2ts/converter/declarations.rb
121
+ - lib/rbs2ts/converter/helper.rb
122
+ - lib/rbs2ts/converter/members.rb
121
123
  - lib/rbs2ts/converter/types.rb
122
124
  - lib/rbs2ts/version.rb
123
125
  - rbs2ts.gemspec
@@ -136,12 +138,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
136
138
  version: '0'
137
139
  required_rubygems_version: !ruby/object:Gem::Requirement
138
140
  requirements:
139
- - - ">"
141
+ - - ">="
140
142
  - !ruby/object:Gem::Version
141
- version: 1.3.1
143
+ version: '0'
142
144
  requirements: []
143
145
  rubygems_version: 3.1.4
144
146
  signing_key:
145
147
  specification_version: 4
146
- summary: Convert rbs to typescript
148
+ summary: A RubyGem that converts Ruby RBS to TypeScript definitions.
147
149
  test_files: []