rbi 0.0.6 → 0.0.10

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.
@@ -0,0 +1,143 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module RBI
5
+ module Rewriters
6
+ # Remove all definitions existing in the index from the current tree
7
+ #
8
+ # Let's create an `Index` from two different `Tree`s:
9
+ # ~~~rb
10
+ # tree1 = Parse.parse_string(<<~RBI)
11
+ # class Foo
12
+ # def foo; end
13
+ # end
14
+ # RBI
15
+ #
16
+ # tree2 = Parse.parse_string(<<~RBI)
17
+ # FOO = 10
18
+ # RBI
19
+ #
20
+ # index = Index.index(tree1, tree2)
21
+ # ~~~
22
+ #
23
+ # We can use `RemoveKnownDefinitions` to remove the definitions found in the `index` from the `Tree` to clean:
24
+ # ~~~rb
25
+ # tree_to_clean = Parser.parse_string(<<~RBI)
26
+ # class Foo
27
+ # def foo; end
28
+ # def bar; end
29
+ # end
30
+ # FOO = 10
31
+ # BAR = 42
32
+ # RBI
33
+ #
34
+ # cleaned_tree, operations = RemoveKnownDefinitions.remove(tree_to_clean, index)
35
+ #
36
+ # assert_equal(<<~RBI, cleaned_tree)
37
+ # class Foo
38
+ # def bar; end
39
+ # end
40
+ # BAR = 42
41
+ # RBI
42
+ #
43
+ # assert_equal(<<~OPERATIONS, operations.join("\n"))
44
+ # Deleted ::Foo#foo at -:2:2-2-16 (duplicate from -:2:2-2:16)
45
+ # Deleted ::FOO at -:5:0-5:8 (duplicate from -:1:0-1:8)
46
+ # OPERATIONS
47
+ # ~~~
48
+ class RemoveKnownDefinitions < Visitor
49
+ extend T::Sig
50
+
51
+ sig do
52
+ params(
53
+ tree: Tree,
54
+ index: Index
55
+ ).returns([Tree, T::Array[Operation]])
56
+ end
57
+ def self.remove(tree, index)
58
+ v = RemoveKnownDefinitions.new(index)
59
+ v.visit(tree)
60
+ [tree, v.operations]
61
+ end
62
+
63
+ sig { returns(T::Array[Operation]) }
64
+ attr_reader :operations
65
+
66
+ sig { params(index: Index).void }
67
+ def initialize(index)
68
+ super()
69
+ @index = index
70
+ @operations = T.let([], T::Array[Operation])
71
+ end
72
+
73
+ sig { params(nodes: T::Array[Node]).void }
74
+ def visit_all(nodes)
75
+ nodes.dup.each { |node| visit(node) }
76
+ end
77
+
78
+ sig { override.params(node: T.nilable(Node)).void }
79
+ def visit(node)
80
+ return unless node
81
+
82
+ case node
83
+ when Scope
84
+ visit_all(node.nodes)
85
+ previous = previous_definition_for(node)
86
+ delete_node(node, previous) if previous && can_delete_node?(node, previous)
87
+ when Tree
88
+ visit_all(node.nodes)
89
+ when Indexable
90
+ previous = previous_definition_for(node)
91
+ delete_node(node, previous) if previous && can_delete_node?(node, previous)
92
+ end
93
+ end
94
+
95
+ private
96
+
97
+ sig { params(node: Indexable).returns(T.nilable(Node)) }
98
+ def previous_definition_for(node)
99
+ node.index_ids.each do |id|
100
+ previous = @index[id].first
101
+ return previous if previous
102
+ end
103
+ nil
104
+ end
105
+
106
+ sig { params(node: Node, previous: Node).returns(T::Boolean) }
107
+ def can_delete_node?(node, previous)
108
+ return false unless node.class == previous.class
109
+
110
+ case node
111
+ when Scope
112
+ node.empty?
113
+ when Attr
114
+ previous = T.cast(previous, Attr)
115
+ node.names == previous.names && node.sigs == previous.sigs
116
+ when Method
117
+ previous = T.cast(previous, Method)
118
+ node.params == previous.params && node.sigs == previous.sigs
119
+ else
120
+ true
121
+ end
122
+ end
123
+
124
+ sig { params(node: Node, previous: Node).void }
125
+ def delete_node(node, previous)
126
+ node.detach
127
+ @operations << Operation.new(deleted_node: node, duplicate_of: previous)
128
+ end
129
+
130
+ class Operation < T::Struct
131
+ extend T::Sig
132
+
133
+ const :deleted_node, Node
134
+ const :duplicate_of, Node
135
+
136
+ sig { returns(String) }
137
+ def to_s
138
+ "Deleted #{duplicate_of} at #{deleted_node.loc} (duplicate from #{duplicate_of.loc})"
139
+ end
140
+ end
141
+ end
142
+ end
143
+ end
@@ -8,14 +8,22 @@ module RBI
8
8
 
9
9
  sig { override.params(node: T.nilable(Node)).void }
10
10
  def visit(node)
11
+ sort_node_names!(node) if node
12
+
11
13
  return unless node.is_a?(Tree)
12
14
  visit_all(node.nodes)
13
15
  original_order = node.nodes.map.with_index.to_h
14
16
  node.nodes.sort! do |a, b|
17
+ # First we try to compare the nodes by their node rank (based on the node type)
15
18
  res = node_rank(a) <=> node_rank(b)
16
- res = node_name(a) <=> node_name(b) if res == 0
17
- res = (original_order[a] || 0) <=> (original_order[b] || 0) if res == 0
18
- res || 0
19
+ next res if res != 0 # we can sort the nodes by their rank, let's stop here
20
+
21
+ # Then, if the nodes ranks are the same (res == 0), we try to compare the nodes by their name
22
+ res = node_name(a) <=> node_name(b)
23
+ next res if res && res != 0 # we can sort the nodes by their name, let's stop here
24
+
25
+ # Finally, if the two nodes have the same rank and the same name or at least one node is anonymous then,
26
+ T.must(original_order[a]) <=> T.must(original_order[b]) # we keep the original order
19
27
  end
20
28
  end
21
29
 
@@ -26,22 +34,26 @@ module RBI
26
34
  case node
27
35
  when Group then group_rank(node.kind)
28
36
  when Include, Extend then 10
37
+ when RequiresAncestor then 15
29
38
  when Helper then 20
30
39
  when TypeMember then 30
31
40
  when MixesInClassMethods then 40
32
- when TStructField then 50
33
- when TEnumBlock then 60
41
+ when Send then 50
42
+ when TStructField then 60
43
+ when TEnumBlock then 70
44
+ when Attr then 75
34
45
  when Method
35
46
  if node.name == "initialize"
36
- 71
47
+ 81
37
48
  elsif !node.is_singleton
38
- 72
49
+ 82
39
50
  else
40
- 73
51
+ 83
41
52
  end
42
- when Scope, Const then 80
53
+ when SingletonClass then 90
54
+ when Scope, Const then 100
43
55
  else
44
- 100
56
+ 110
45
57
  end
46
58
  end
47
59
 
@@ -49,14 +61,18 @@ module RBI
49
61
  def group_rank(kind)
50
62
  case kind
51
63
  when Group::Kind::Mixins then 0
52
- when Group::Kind::Helpers then 1
53
- when Group::Kind::TypeMembers then 2
54
- when Group::Kind::MixesInClassMethods then 3
55
- when Group::Kind::TStructFields then 4
56
- when Group::Kind::TEnums then 5
57
- when Group::Kind::Inits then 6
58
- when Group::Kind::Methods then 7
59
- when Group::Kind::Consts then 8
64
+ when Group::Kind::RequiredAncestors then 1
65
+ when Group::Kind::Helpers then 2
66
+ when Group::Kind::TypeMembers then 3
67
+ when Group::Kind::MixesInClassMethods then 4
68
+ when Group::Kind::Sends then 5
69
+ when Group::Kind::TStructFields then 6
70
+ when Group::Kind::TEnums then 7
71
+ when Group::Kind::Attrs then 8
72
+ when Group::Kind::Inits then 9
73
+ when Group::Kind::Methods then 10
74
+ when Group::Kind::SingletonClasses then 11
75
+ when Group::Kind::Consts then 12
60
76
  else
61
77
  T.absurd(kind)
62
78
  end
@@ -65,8 +81,18 @@ module RBI
65
81
  sig { params(node: Node).returns(T.nilable(String)) }
66
82
  def node_name(node)
67
83
  case node
68
- when Module, Class, Struct, Const, Method, Helper, TStructField
84
+ when Module, Class, Struct, Const, Method, Helper, TStructField, RequiresAncestor
69
85
  node.name
86
+ when Attr
87
+ node.names.first.to_s
88
+ end
89
+ end
90
+
91
+ sig { params(node: Node).void }
92
+ def sort_node_names!(node)
93
+ case node
94
+ when Attr
95
+ node.names.sort!
70
96
  end
71
97
  end
72
98
  end
data/lib/rbi/version.rb CHANGED
@@ -2,5 +2,5 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module RBI
5
- VERSION = "0.0.6"
5
+ VERSION = "0.0.10"
6
6
  end
data/lib/rbi.rb CHANGED
@@ -13,10 +13,13 @@ require "rbi/model"
13
13
  require "rbi/visitor"
14
14
  require "rbi/index"
15
15
  require "rbi/rewriters/add_sig_templates"
16
+ require "rbi/rewriters/annotate"
17
+ require "rbi/rewriters/deannotate"
16
18
  require "rbi/rewriters/merge_trees"
17
19
  require "rbi/rewriters/nest_singleton_methods"
18
20
  require "rbi/rewriters/nest_non_public_methods"
19
21
  require "rbi/rewriters/group_nodes"
22
+ require "rbi/rewriters/remove_known_definitions"
20
23
  require "rbi/rewriters/sort_nodes"
21
24
  require "rbi/parser"
22
25
  require "rbi/printer"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rbi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 0.0.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexandre Terrasa
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-10-06 00:00:00.000000000 Z
11
+ date: 2022-01-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ast
@@ -83,10 +83,13 @@ files:
83
83
  - lib/rbi/parser.rb
84
84
  - lib/rbi/printer.rb
85
85
  - lib/rbi/rewriters/add_sig_templates.rb
86
+ - lib/rbi/rewriters/annotate.rb
87
+ - lib/rbi/rewriters/deannotate.rb
86
88
  - lib/rbi/rewriters/group_nodes.rb
87
89
  - lib/rbi/rewriters/merge_trees.rb
88
90
  - lib/rbi/rewriters/nest_non_public_methods.rb
89
91
  - lib/rbi/rewriters/nest_singleton_methods.rb
92
+ - lib/rbi/rewriters/remove_known_definitions.rb
90
93
  - lib/rbi/rewriters/sort_nodes.rb
91
94
  - lib/rbi/version.rb
92
95
  - lib/rbi/visitor.rb