rbi 0.0.6 → 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
@@ -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