rbs-inline 0.1.0 → 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/README.md +6 -1
- data/lib/rbs/inline/annotation_parser.rb +1 -1
- data/lib/rbs/inline/ast/members.rb +2 -2
- data/lib/rbs/inline/cli.rb +75 -18
- data/lib/rbs/inline/parser.rb +5 -6
- data/lib/rbs/inline/version.rb +1 -1
- data/sig/generated/rbs/inline/annotation_parser.rbs +1 -1
- data/sig/generated/rbs/inline/ast/members.rbs +1 -1
- data/sig/generated/rbs/inline/cli.rbs +31 -0
- data/sig/generated/rbs/inline/parser.rbs +2 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '091f44026573a60f39acf39a0b8865a3cee4a4f72401cd0ab8ce37d9e397caad'
|
4
|
+
data.tar.gz: 95236c91fac2461db268a7fbd81503210d0d818bad958a6b9ff03d708a28558b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e76c5c6311109ffbac3a157625370a42f7f8b0cd2e1be58f8de4352d5e1528027acff819ecf7db6d9a6bb16bbb478adadfcb09d474816f7cc942a5a42be63729
|
7
|
+
data.tar.gz: 8d7d4aba2f04cac960975add67c7d7ad30366806a540cd899a11f1250a7045145a9578732c055cf75ad50d1a68949d6aea55c7f7e3077d958aafb042f7c52149
|
data/README.md
CHANGED
@@ -3,11 +3,16 @@
|
|
3
3
|
RBS::Inline allows embedding RBS type declarations into Ruby code as comments. You can declare types, write the implementation, and verifies they are consistent without leaving the editor opening the Ruby code.
|
4
4
|
|
5
5
|
> [!IMPORTANT]
|
6
|
-
> The
|
6
|
+
> The syntax is experimental. We are still seeking the best syntax with your feedbacks.
|
7
|
+
|
8
|
+
> [!IMPORTANT]
|
9
|
+
> This gem is a prototype for testing. We plan to merge this feature to rbs-gem and deprecate rbs-inline gem after that.
|
7
10
|
|
8
11
|
Here is a quick example of embedded declarations.
|
9
12
|
|
10
13
|
```rb
|
14
|
+
# rbs_inline: enabled
|
15
|
+
|
11
16
|
class Person
|
12
17
|
attr_reader :name #:: String
|
13
18
|
|
@@ -501,7 +501,7 @@ module RBS
|
|
501
501
|
#
|
502
502
|
# ```
|
503
503
|
# Integer -- Foo # => Returns `Integer`, tokenizer has `--` as its current token
|
504
|
-
# Integer[ -- Foo # => Returns a tree for `Integer[`, tokenizer has `--` as its
|
504
|
+
# Integer[ -- Foo # => Returns a tree for `Integer[`, tokenizer has `--` as its current token
|
505
505
|
# Integer[ Foo # => Returns a tree for `Integer[ Foo`, tokenizer is at the end of the input
|
506
506
|
# ```
|
507
507
|
#
|
@@ -69,7 +69,7 @@ module RBS
|
|
69
69
|
# [FIXME] It only supports `self` receiver.
|
70
70
|
#
|
71
71
|
# ```rb
|
72
|
-
# def self.foo = () # :
|
72
|
+
# def self.foo = () # :singleton
|
73
73
|
# def object.foo = () # Not supported (returns :instance)
|
74
74
|
# ```
|
75
75
|
#
|
@@ -578,7 +578,7 @@ module RBS
|
|
578
578
|
end
|
579
579
|
RBS
|
580
580
|
|
581
|
-
_,
|
581
|
+
_, _, decls = RBS::Parser.parse_signature(source)
|
582
582
|
|
583
583
|
mod = decls[0]
|
584
584
|
mod.is_a?(RBS::AST::Declarations::Module) or raise
|
data/lib/rbs/inline/cli.rb
CHANGED
@@ -5,6 +5,56 @@ require "optparse"
|
|
5
5
|
module RBS
|
6
6
|
module Inline
|
7
7
|
class CLI
|
8
|
+
# Calculate the path under `output_path` that has the same structure relative to one of the `base_paths`
|
9
|
+
#
|
10
|
+
# ```rb
|
11
|
+
# calculator = PathCalculator.new(Pathname("/rbs-inline"), [Pathname("app"), Pathname("lib")], Pathname("/tmp/sig"))
|
12
|
+
# calculator.calculate(Pathname("/rbs-inline/app/models/foo.rb")) # => Pathname("/tmp/sig/models/foo.rb")
|
13
|
+
# calculator.calculate(Pathname("/rbs-inline/lib/bar.rb")) # => Pathname("/tmp/sig/bar.rb")
|
14
|
+
# calculator.calculate(Pathname("/rbs-inline/hello/world.rb")) # => Pathname("/tmp/sig/hello/world.rb")
|
15
|
+
# calculator.calculate(Pathname("/foo.rb")) # => nil
|
16
|
+
# ```
|
17
|
+
#
|
18
|
+
#
|
19
|
+
class PathCalculator
|
20
|
+
attr_reader :pwd #:: Pathname
|
21
|
+
|
22
|
+
attr_reader :base_paths #:: Array[Pathname]
|
23
|
+
|
24
|
+
attr_reader :output_path #:: Pathname
|
25
|
+
|
26
|
+
# @rbs pwd: Pathname
|
27
|
+
# @rbs base_paths: Array[Pathname]
|
28
|
+
# @rbs output_path: Pathname
|
29
|
+
def initialize(pwd, base_paths, output_path) #:: void
|
30
|
+
@pwd = pwd
|
31
|
+
@base_paths = base_paths
|
32
|
+
@output_path = output_path
|
33
|
+
end
|
34
|
+
|
35
|
+
#:: (Pathname) -> Pathname?
|
36
|
+
def calculate(path)
|
37
|
+
path = pwd + path if path.relative?
|
38
|
+
path = path.cleanpath
|
39
|
+
return nil unless has_prefix?(path, prefix: pwd)
|
40
|
+
|
41
|
+
if prefix = base_paths.find {|base| has_prefix?(path, prefix: pwd + base) }
|
42
|
+
relative_to_output = path.relative_path_from(pwd + prefix)
|
43
|
+
else
|
44
|
+
relative_to_output = path.relative_path_from(pwd)
|
45
|
+
end
|
46
|
+
|
47
|
+
output_path + relative_to_output
|
48
|
+
end
|
49
|
+
|
50
|
+
# @rbs path: Pathname
|
51
|
+
# @rbs prefix: Pathname
|
52
|
+
# @rbs returns bool
|
53
|
+
def has_prefix?(path, prefix:)
|
54
|
+
path.descend.include?(prefix)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
8
58
|
attr_reader :stdout, :stderr #:: IO
|
9
59
|
attr_reader :logger #:: Logger
|
10
60
|
|
@@ -20,12 +70,13 @@ module RBS
|
|
20
70
|
# @rbs args: Array[String]
|
21
71
|
# @rbs returns Integer
|
22
72
|
def run(args)
|
23
|
-
|
73
|
+
base_paths = [Pathname("lib"), Pathname("app")]
|
24
74
|
output_path = nil #: Pathname?
|
25
75
|
|
26
76
|
OptionParser.new do |opts|
|
27
|
-
opts.on("--base=[BASE]", "The path to calculate relative path of files (defaults to #{
|
28
|
-
|
77
|
+
opts.on("--base=[BASE]", "The path to calculate relative path of files (defaults to #{base_paths.join(File::PATH_SEPARATOR)})") do |str|
|
78
|
+
# @type var str: String
|
79
|
+
base_paths = str.split(File::PATH_SEPARATOR).map {|path| Pathname(path) }
|
29
80
|
end
|
30
81
|
|
31
82
|
opts.on("--output=[BASE]", "The directory where the RBS files are saved at (defaults to STDOUT if not specified)") do
|
@@ -37,17 +88,17 @@ module RBS
|
|
37
88
|
end
|
38
89
|
end.parse!(args)
|
39
90
|
|
40
|
-
|
91
|
+
logger.debug { "base_paths = #{base_paths.join(File::PATH_SEPARATOR)}, output_path = #{output_path}" }
|
41
92
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
path = Pathname(_1)
|
93
|
+
if output_path
|
94
|
+
calculator = PathCalculator.new(Pathname.pwd, base_paths, output_path)
|
95
|
+
end
|
46
96
|
|
97
|
+
targets = args.flat_map { Pathname.glob(_1) }.flat_map do |path|
|
47
98
|
if path.directory?
|
48
99
|
pattern = path + "**/*.rb"
|
49
100
|
Pathname.glob(pattern.to_s)
|
50
|
-
else
|
101
|
+
else
|
51
102
|
path
|
52
103
|
end
|
53
104
|
end
|
@@ -58,12 +109,14 @@ module RBS
|
|
58
109
|
count = 0
|
59
110
|
|
60
111
|
targets.each do |target|
|
61
|
-
|
62
|
-
if output_path
|
63
|
-
output = output_path + relative_path.sub_ext(".rbs")
|
112
|
+
absolute_path = Pathname.pwd + target
|
64
113
|
|
65
|
-
|
66
|
-
|
114
|
+
if output_path && calculator
|
115
|
+
output_file_path = calculator.calculate(absolute_path)
|
116
|
+
if output_file_path
|
117
|
+
output = output_file_path.sub_ext(".rbs")
|
118
|
+
else
|
119
|
+
raise "Cannot calculate the output file path for #{target} in #{output_path}: calculated = #{output}"
|
67
120
|
end
|
68
121
|
|
69
122
|
logger.debug { "Generating #{output} from #{target} ..." }
|
@@ -84,14 +137,18 @@ module RBS
|
|
84
137
|
output.parent.mkpath
|
85
138
|
end
|
86
139
|
|
87
|
-
|
88
|
-
|
140
|
+
if output.file? && output.read == writer.output
|
141
|
+
logger.debug { "Skip writing identical RBS file" }
|
142
|
+
else
|
143
|
+
logger.debug { "Writing RBS file to #{output}..." }
|
144
|
+
output.write(writer.output)
|
145
|
+
count += 1
|
146
|
+
end
|
89
147
|
else
|
90
148
|
stdout.puts writer.output
|
91
149
|
stdout.puts
|
150
|
+
count += 1
|
92
151
|
end
|
93
|
-
|
94
|
-
count += 1
|
95
152
|
else
|
96
153
|
logger.debug { "Skipping #{target} because `# rbs_inline: enabled` comment not found" }
|
97
154
|
end
|
data/lib/rbs/inline/parser.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
# rbs_inline: enabled
|
2
|
-
|
3
1
|
# @rbs use Prism::*
|
4
2
|
|
5
3
|
module RBS
|
@@ -50,9 +48,10 @@ module RBS
|
|
50
48
|
instance.comments[result.line_range.end] = result
|
51
49
|
end
|
52
50
|
|
53
|
-
|
54
|
-
|
55
|
-
|
51
|
+
with_magic_comment = result.comments.any? {|comment| comment.location.slice =~ /\A# rbs_inline: enabled\Z/}
|
52
|
+
with_annotation = annots.any? {|result| result.annotations.any? }
|
53
|
+
|
54
|
+
return unless with_magic_comment || with_annotation
|
56
55
|
|
57
56
|
uses = [] #: Array[AST::Annotations::Use]
|
58
57
|
annots.each do |annot|
|
@@ -71,7 +70,7 @@ module RBS
|
|
71
70
|
]
|
72
71
|
end
|
73
72
|
|
74
|
-
# @rbs
|
73
|
+
# @rbs returns AST::Declarations::ModuleDecl | AST::Declarations::ClassDecl | nil
|
75
74
|
def current_class_module_decl
|
76
75
|
surrounding_decls.last
|
77
76
|
end
|
data/lib/rbs/inline/version.rb
CHANGED
@@ -146,7 +146,7 @@ module RBS
|
|
146
146
|
#
|
147
147
|
# ```
|
148
148
|
# Integer -- Foo # => Returns `Integer`, tokenizer has `--` as its current token
|
149
|
-
# Integer[ -- Foo # => Returns a tree for `Integer[`, tokenizer has `--` as its
|
149
|
+
# Integer[ -- Foo # => Returns a tree for `Integer[`, tokenizer has `--` as its current token
|
150
150
|
# Integer[ Foo # => Returns a tree for `Integer[ Foo`, tokenizer is at the end of the input
|
151
151
|
# ```
|
152
152
|
#
|
@@ -49,7 +49,7 @@ module RBS
|
|
49
49
|
# [FIXME] It only supports `self` receiver.
|
50
50
|
#
|
51
51
|
# ```rb
|
52
|
-
# def self.foo = () # :
|
52
|
+
# def self.foo = () # :singleton
|
53
53
|
# def object.foo = () # Not supported (returns :instance)
|
54
54
|
# ```
|
55
55
|
def method_kind: () -> RBS::AST::Members::MethodDefinition::kind
|
@@ -3,6 +3,37 @@
|
|
3
3
|
module RBS
|
4
4
|
module Inline
|
5
5
|
class CLI
|
6
|
+
# Calculate the path under `output_path` that has the same structure relative to one of the `base_paths`
|
7
|
+
#
|
8
|
+
# ```rb
|
9
|
+
# calculator = PathCalculator.new(Pathname("/rbs-inline"), [Pathname("app"), Pathname("lib")], Pathname("/tmp/sig"))
|
10
|
+
# calculator.calculate(Pathname("/rbs-inline/app/models/foo.rb")) # => Pathname("/tmp/sig/models/foo.rb")
|
11
|
+
# calculator.calculate(Pathname("/rbs-inline/lib/bar.rb")) # => Pathname("/tmp/sig/bar.rb")
|
12
|
+
# calculator.calculate(Pathname("/rbs-inline/hello/world.rb")) # => Pathname("/tmp/sig/hello/world.rb")
|
13
|
+
# calculator.calculate(Pathname("/foo.rb")) # => nil
|
14
|
+
# ```
|
15
|
+
#
|
16
|
+
class PathCalculator
|
17
|
+
attr_reader pwd: Pathname
|
18
|
+
|
19
|
+
attr_reader base_paths: Array[Pathname]
|
20
|
+
|
21
|
+
attr_reader output_path: Pathname
|
22
|
+
|
23
|
+
# @rbs pwd: Pathname
|
24
|
+
# @rbs base_paths: Array[Pathname]
|
25
|
+
# @rbs output_path: Pathname
|
26
|
+
def initialize: (Pathname pwd, Array[Pathname] base_paths, Pathname output_path) -> void
|
27
|
+
|
28
|
+
# :: (Pathname) -> Pathname?
|
29
|
+
def calculate: (Pathname) -> Pathname?
|
30
|
+
|
31
|
+
# @rbs path: Pathname
|
32
|
+
# @rbs prefix: Pathname
|
33
|
+
# @rbs returns bool
|
34
|
+
def has_prefix?: (Pathname path, prefix: Pathname) -> bool
|
35
|
+
end
|
36
|
+
|
6
37
|
attr_reader stdout: IO
|
7
38
|
|
8
39
|
attr_reader stderr: IO
|
@@ -34,8 +34,8 @@ module RBS
|
|
34
34
|
# @rbs returns [Array[AST::Annotations::Use], Array[AST::Declarations::t]]?
|
35
35
|
def self.parse: (ParseResult[ProgramNode] result) -> [ Array[AST::Annotations::Use], Array[AST::Declarations::t] ]?
|
36
36
|
|
37
|
-
# @rbs
|
38
|
-
def current_class_module_decl: () ->
|
37
|
+
# @rbs returns AST::Declarations::ModuleDecl | AST::Declarations::ClassDecl | nil
|
38
|
+
def current_class_module_decl: () -> (AST::Declarations::ModuleDecl | AST::Declarations::ClassDecl | nil)
|
39
39
|
|
40
40
|
# @rbs returns AST::Declarations::ModuleDecl | AST::Declarations::ClassDecl
|
41
41
|
def current_class_module_decl!: () -> (AST::Declarations::ModuleDecl | AST::Declarations::ClassDecl)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rbs-inline
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Soutaro Matsumoto
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-05-
|
11
|
+
date: 2024-05-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: prism
|