rbs-inline-annotator 0.1.0 → 0.2.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b957db6fbd29cfa5e3b4b5613386beeeb3aebf40f7a576e01a95e31fa88267b3
4
- data.tar.gz: 7d6a684f4c95daec4926e3f2500d55b294d33b423cda307c1af0276db2400390
3
+ metadata.gz: d398c9f6b34b3f6ac6d807527341b09c180dde4f3bb75962c6fbc0f36cccd791
4
+ data.tar.gz: 34af7fd6c55711068669e67924403fd937a1301c4cede7e8e7fee4cf485ed320
5
5
  SHA512:
6
- metadata.gz: 6bd9cabe241ca29a157fc3bf91cbe962fe182d629d9417c571a98db6117f61f331327bd4d713340272a63d0d228aa467596da3d9a5478c2e24ad09910d46d1ed
7
- data.tar.gz: 0a432b269bb9d2ce12618bfa5eb766db14ea987b68135115f7c636c6d4cba2390b04707c1edbac6df96ad2f270e979d9b21c831e2965ac8208d419d46036c0f1
6
+ metadata.gz: e9096854e21fbc7e4ed5b982a6b7c0969438f475456b8b84256fba394c8114486a0f7a81d908014109e039ba945e02923805677d3d8513352d05404fae45128d
7
+ data.tar.gz: 61c6fcf5e3a26f81792ea91298e29433ef319482e92349864140bb1a2a22913430b6071ecbc017bd0731dcb633c39d0e992232f87dba5a5148d4da417c48302c
data/README.md CHANGED
@@ -35,18 +35,16 @@ end
35
35
 
36
36
  ## Installation
37
37
 
38
- TODO: Replace `UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG` with your gem name right after releasing it to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with instructions to install your gem from git if you don't plan to release to RubyGems.org.
39
-
40
38
  Install the gem and add to the application's Gemfile by executing:
41
39
 
42
40
  ```bash
43
- bundle add UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
41
+ bundle add rbs-inline-annotator
44
42
  ```
45
43
 
46
44
  If bundler is not being used to manage dependencies, install the gem by executing:
47
45
 
48
46
  ```bash
49
- gem install UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
47
+ gem install rbs-inline-annotator
50
48
  ```
51
49
 
52
50
  ## Usage
@@ -52,10 +52,10 @@ module RBS::Inline::Annotator
52
52
  Spinner.new.tap do |spinner|
53
53
  print "\e[?25l" if @options.mode == 'write'
54
54
  targets.each do |target|
55
- annotated_code = Processor.new(target:, env:).process
55
+ annotated_code, changed = Processor.new(target:, env:).process
56
56
  case @options.mode
57
57
  when 'write'
58
- File.write(target, annotated_code)
58
+ File.write(target, annotated_code) if changed
59
59
  when 'print-only'
60
60
  puts annotated_code
61
61
  when 'quiet'
@@ -17,15 +17,18 @@ module RBS::Inline::Annotator
17
17
  @env = env
18
18
  end
19
19
 
20
+ # @rbs return: [String, bool] -- [code string, changed flag]
20
21
  def process
21
22
  absolute_path = Pathname.pwd + target
22
23
  source = absolute_path.read
23
24
  writer = Writer.new(source)
24
25
  result = Result.new(writer:, prism_result: Prism.parse_file(absolute_path.to_s))
25
26
  result.prism_result.value.accept(Visitor.new(env:, result:))
26
- return if result.writer.actions.empty?
27
-
28
- writer.process
27
+ if result.writer.actions.empty?
28
+ [source, false]
29
+ else
30
+ [writer.process, true]
31
+ end
29
32
  end
30
33
  end
31
34
  end
@@ -3,7 +3,7 @@
3
3
  module RBS
4
4
  module Inline
5
5
  module Annotator
6
- VERSION = "0.1.0"
6
+ VERSION = "0.2.0"
7
7
  end
8
8
  end
9
9
  end
@@ -26,8 +26,8 @@ module RBS::Inline::Annotator
26
26
 
27
27
  def node_range(node)
28
28
  Range.new(
29
- node.location.start_offset,
30
- node.location.end_offset,
29
+ node.location.start_character_offset,
30
+ node.location.end_character_offset,
31
31
  )
32
32
  end
33
33
 
@@ -49,6 +49,7 @@ module RBS::Inline::Annotator
49
49
 
50
50
  def visit_class_node(node)
51
51
  push_type_name(node) do
52
+ with_generics(node)
52
53
  with_superclass(node.superclass)
53
54
  # TODO: Which file should we write to?
54
55
  # with_embedding_rbs(header_node(node), node)
@@ -59,6 +60,7 @@ module RBS::Inline::Annotator
59
60
 
60
61
  def visit_module_node(node)
61
62
  push_type_name(node) do
63
+ with_generics(node)
62
64
  with_module_self(node)
63
65
  # TODO: Which file should we write to?
64
66
  # with_embedding_rbs(header_node(node), node)
@@ -67,6 +69,14 @@ module RBS::Inline::Annotator
67
69
  end
68
70
  end
69
71
 
72
+ def with_generics(node)
73
+ entry = module_class_entry or return
74
+ indent = " " * node.location.start_column
75
+ entry.primary_decl.type_params.each do |type_param|
76
+ insert_before(node_range(node), "# @rbs generic #{type_param}\n#{indent}")
77
+ end
78
+ end
79
+
70
80
  def header_node(node)
71
81
  case node
72
82
  when Prism::ClassNode
@@ -252,13 +262,18 @@ module RBS::Inline::Annotator
252
262
  new_annotation.call("return", return_type)
253
263
  }
254
264
  if node.parameters
255
- for_positional_params.call(func.required_positionals, node.parameters.requireds)
256
- for_positional_params.call(func.optional_positionals, node.parameters.optionals)
257
- for_rest_param.call("*", func.rest_positionals, node.parameters.rest) if func.rest_positionals
258
- for_positional_params.call(func.trailing_positionals, node.parameters.posts) if func.trailing_positionals
259
- for_keyword_params.call(func.required_keywords, node.parameters.keywords.grep(Prism::RequiredKeywordParameterNode))
260
- for_keyword_params.call(func.optional_keywords, node.parameters.keywords.grep(Prism::OptionalKeywordParameterNode))
261
- for_rest_param.call("**", func.rest_keywords, node.parameters.keyword_rest) if func.rest_keywords
265
+ case func
266
+ when RBS::Types::UntypedFunction
267
+ # do nothing
268
+ when RBS::Types::Function
269
+ for_positional_params.call(func.required_positionals, node.parameters.requireds)
270
+ for_positional_params.call(func.optional_positionals, node.parameters.optionals)
271
+ for_rest_param.call("*", func.rest_positionals, node.parameters.rest) if func.rest_positionals
272
+ for_positional_params.call(func.trailing_positionals, node.parameters.posts) if func.trailing_positionals
273
+ for_keyword_params.call(func.required_keywords, node.parameters.keywords.grep(Prism::RequiredKeywordParameterNode))
274
+ for_keyword_params.call(func.optional_keywords, node.parameters.keywords.grep(Prism::OptionalKeywordParameterNode))
275
+ for_rest_param.call("**", func.rest_keywords, node.parameters.keyword_rest) if func.rest_keywords
276
+ end
262
277
  end
263
278
  if method_type.block
264
279
  name = node.parameters&.block&.name
@@ -297,6 +312,7 @@ module RBS::Inline::Annotator
297
312
  (node.name == :attr_writer && member.is_a?(RBS::AST::Members::AttrWriter)) ||
298
313
  (node.name == :attr_accessor && member.is_a?(RBS::AST::Members::AttrAccessor))
299
314
  next unless member.name == value.to_sym
315
+ next unless member.kind == @kind
300
316
 
301
317
  type = member.type.to_s
302
318
  next if type == "untyped"
@@ -316,6 +332,7 @@ module RBS::Inline::Annotator
316
332
  (node.name == :attr_writer && member.is_a?(RBS::AST::Members::AttrWriter)) ||
317
333
  (node.name == :attr_accessor && member.is_a?(RBS::AST::Members::AttrAccessor))
318
334
  next unless member.name == value.to_sym
335
+ next unless member.kind == @kind
319
336
 
320
337
  indent = replaced_count == 0 ? "" : " " * node.location.start_column
321
338
  insert_before(node_range(node), "#{indent}#{node.name} :#{value} #: #{member.type}\n")
@@ -387,18 +404,61 @@ module RBS::Inline::Annotator
387
404
  end
388
405
  end
389
406
 
407
+ def visit_constant_path_write_node(node)
408
+ constant_type_name = RBS::TypeName.parse(node.target.full_name).then do |c|
409
+ type_name ? type_name + c : c.absolute!
410
+ end
411
+ type = constant_type(node, constant_type_name) or return
412
+ add_rbs_inline_annotation_for_trailing(node:, type:)
413
+ end
414
+
390
415
  def visit_constant_write_node(node)
416
+ namespace = type_name ? type_name.to_namespace : RBS::Namespace.root
391
417
  constant_type_name = RBS::TypeName.new(
392
418
  name: node.name,
393
- namespace: type_name.to_namespace
419
+ namespace:
394
420
  )
395
- entry = @env.constant_decls[constant_type_name] or return
396
- type = entry.decl.type.to_s
397
- return if type == "untyped"
398
-
421
+ type = constant_type(node, constant_type_name) or return
399
422
  add_rbs_inline_annotation_for_trailing(node:, type:)
400
423
  end
401
424
 
425
+ def constant_type(node, type_name)
426
+ entry = @env.constant_entry(type_name) or return
427
+ case entry
428
+ when RBS::Environment::ModuleAliasEntry
429
+ case node.value
430
+ when Prism::CallNode
431
+ "module-alias #{entry.decl.old_name}"
432
+ when Prism::ConstantReadNode, Prism::ConstantPathNode
433
+ "module-alias"
434
+ else
435
+ warn "Unsupported node: #{node.value.class}"
436
+ end
437
+ when RBS::Environment::ClassAliasEntry
438
+ case node.value
439
+ when Prism::CallNode
440
+ "class-alias #{entry.decl.old_name}"
441
+ when Prism::ConstantReadNode, Prism::ConstantPathNode
442
+ "class-alias"
443
+ else
444
+ warn "Unsupported node: #{node.value.class}"
445
+ end
446
+ when RBS::Environment::ConstantEntry
447
+ t = entry.decl.type.to_s
448
+ if (node.value.is_a?(Prism::IntegerNode) && t == "Integer" ||
449
+ node.value.is_a?(Prism::FloatNode) && t == "Float" ||
450
+ node.value.is_a?(Prism::TrueNode) && t == "bool" ||
451
+ node.value.is_a?(Prism::FalseNode) && t == "bool" ||
452
+ node.value.is_a?(Prism::StringNode) && t == "String" ||
453
+ node.value.is_a?(Prism::SymbolNode) && t == ":#{node.value.value}")
454
+ # The types of constants may be automatically inferred
455
+ nil
456
+ else
457
+ t
458
+ end
459
+ end
460
+ end
461
+
402
462
  def add_rbs_inline_annotation_for_trailing(node:, type:)
403
463
  return if type == "untyped"
404
464
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rbs-inline-annotator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ksss