orbacle 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.
@@ -48,14 +48,13 @@ module Orbacle
48
48
  @worklist.message_sends.each do |message_send|
49
49
  case message_send
50
50
  when Worklist::MessageSend
51
- if satisfied_message_send?(message_send) && !@worklist.message_send_handled?(message_send)
51
+ if satisfied_message_send?(message_send)
52
52
  handle_message_send(message_send)
53
- @worklist.mark_message_send_as_handled(message_send)
54
53
  end
55
54
  when Worklist::SuperSend
56
55
  if satisfied_super_send?(message_send) && !@worklist.message_send_handled?(message_send)
57
56
  handle_super_send(message_send)
58
- @worklist.mark_message_send_as_handled(message_send)
57
+ @worklist.mark_message_send_as_handled(message_send, nil)
59
58
  end
60
59
  else raise "Not handled message send"
61
60
  end
@@ -65,14 +64,11 @@ module Orbacle
65
64
  @worklist.message_sends.each do |message_send|
66
65
  case message_send
67
66
  when Worklist::MessageSend
68
- if !@worklist.message_send_handled?(message_send)
69
- handle_message_send(message_send)
70
- @worklist.mark_message_send_as_handled(message_send)
71
- end
67
+ handle_message_send(message_send)
72
68
  when Worklist::SuperSend
73
69
  if !@worklist.message_send_handled?(message_send)
74
70
  handle_super_send(message_send)
75
- @worklist.mark_message_send_as_handled(message_send)
71
+ @worklist.mark_message_send_as_handled(message_send, nil)
76
72
  end
77
73
  else raise "Not handled message send"
78
74
  end
@@ -144,6 +140,7 @@ module Orbacle
144
140
  when :formal_kwrestarg then handle_group(node, sources)
145
141
  when :formal_blockarg then handle_group(node, sources)
146
142
  when :block_result then handle_pass_lte1(node, sources)
143
+ when :caller then handle_group(node, sources)
147
144
 
148
145
  when :loop_operator then handle_bottom(node, sources)
149
146
 
@@ -214,7 +211,6 @@ module Orbacle
214
211
  build_union([
215
212
  handle_group(node, sources),
216
213
  NominalType.new("Boolean"),
217
- NominalType.new("Nil"),
218
214
  ])
219
215
  end
220
216
 
@@ -222,7 +218,6 @@ module Orbacle
222
218
  build_union([
223
219
  handle_group(node, sources),
224
220
  NominalType.new("Boolean"),
225
- NominalType.new("Nil"),
226
221
  ])
227
222
  end
228
223
 
@@ -410,15 +405,17 @@ module Orbacle
410
405
 
411
406
  def handle_message_send(message_send)
412
407
  @state.type_of(message_send.send_obj).each_possible_type do |possible_type|
408
+ next if @worklist.message_send_handled_by_type?(message_send, possible_type)
413
409
  if constructor_send?(possible_type, message_send.message_send)
414
- handle_constructor_send(possible_type.name, possible_type.name, message_send)
415
- elsif possible_type.instance_of?(ProcType) && message_send.message_send == "call"
410
+ handle_constructor_send(possible_type.name, message_send)
411
+ elsif possible_type.instance_of?(ProcType) && message_send.message_send == :call
416
412
  handle_proc_call(possible_type, message_send)
417
413
  elsif possible_type.is_a?(ClassType)
418
414
  handle_class_send(possible_type.name, message_send)
419
415
  else
420
416
  handle_instance_send(possible_type.name, message_send)
421
417
  end
418
+ @worklist.mark_message_send_as_handled(message_send, possible_type)
422
419
  end
423
420
  end
424
421
 
@@ -430,17 +427,13 @@ module Orbacle
430
427
  @worklist.enqueue_node(message_send.send_result)
431
428
  end
432
429
 
433
- def handle_constructor_send(original_class_name, class_name, message_send)
434
- found_method = @state.find_instance_method_from_class_name(class_name, "initialize")
430
+ def handle_constructor_send(class_name, message_send)
431
+ found_method = @state.find_deep_instance_method_from_class_name(class_name, :initialize)
435
432
  if found_method.nil?
436
- parent_name = @state.get_parent_of(class_name)
437
- if parent_name
438
- handle_constructor_send(original_class_name, parent_name, message_send)
439
- else
440
- connect_constructor_to_node(original_class_name, message_send.send_result)
441
- end
433
+ connect_constructor_to_node(class_name, message_send.send_result)
442
434
  else
443
- handle_custom_message_send(found_method, message_send)
435
+ found_method_nodes = @graph.get_metod_nodes(found_method.id)
436
+ handle_custom_message_send(found_method, message_send, found_method_nodes)
444
437
  connect_constructor_to_node(class_name, message_send.send_result)
445
438
  end
446
439
  end
@@ -452,33 +445,21 @@ module Orbacle
452
445
  @worklist.enqueue_node(constructor_node)
453
446
  end
454
447
 
455
- def handle_instance_nonprimitive_send(class_name, message_send)
456
- found_method = @state.find_instance_method_from_class_name(class_name, message_send.message_send)
457
- if found_method.nil?
458
- parent_name = @state.get_parent_of(class_name)
459
- if parent_name
460
- handle_instance_send(parent_name, message_send)
461
- else
462
- # logger.debug("Method #{message_send.message_send} not found in #{class_name} (location: #{message_send.location})\n")
463
- end
464
- else
465
- handle_custom_message_send(found_method, message_send)
466
- connect_method_result_to_node(found_method.id, message_send.send_result)
448
+ def handle_instance_send(class_name, message_send)
449
+ found_method = @state.find_deep_instance_method_from_class_name(class_name, message_send.message_send)
450
+ if found_method
451
+ found_method_nodes = @graph.get_metod_nodes(found_method.id)
452
+ handle_custom_message_send(found_method, message_send, found_method_nodes)
453
+ connect_method_result_to_node(found_method_nodes, message_send.send_result)
467
454
  end
468
455
  end
469
456
 
470
- def handle_class_nonprimitive_send(class_name, message_send)
471
- found_method = @state.find_class_method_from_class_name(class_name, message_send.message_send)
472
- if found_method.nil?
473
- parent_name = @state.get_parent_of(class_name)
474
- if parent_name
475
- handle_class_send(parent_name, message_send)
476
- else
477
- # logger.debug("Method #{message_send.message_send} not found in #{class_name} (location: #{message_send.location})\n")
478
- end
479
- else
480
- handle_custom_message_send(found_method, message_send)
481
- connect_method_result_to_node(found_method.id, message_send.send_result)
457
+ def handle_class_send(class_name, message_send)
458
+ found_method = @state.find_deep_class_method_from_class_name(class_name, message_send.message_send)
459
+ if found_method
460
+ found_method_nodes = @graph.get_metod_nodes(found_method.id)
461
+ handle_custom_message_send(found_method, message_send, found_method_nodes)
462
+ connect_method_result_to_node(found_method_nodes, message_send.send_result)
482
463
  end
483
464
  end
484
465
 
@@ -504,8 +485,12 @@ module Orbacle
504
485
  end
505
486
  end
506
487
 
507
- def handle_custom_message_send(found_method, message_send)
508
- found_method_nodes = @graph.get_metod_nodes(found_method.id)
488
+ def handle_custom_message_send(found_method, message_send, found_method_nodes)
489
+ if found_method_nodes.caller_node
490
+ @graph.add_edge(message_send.send_obj, found_method_nodes.caller_node)
491
+ @worklist.enqueue_node(found_method_nodes.caller_node)
492
+ end
493
+
509
494
  connect_actual_args_to_formal_args(found_method.args, found_method_nodes.args, message_send.send_args)
510
495
 
511
496
  found_method_nodes.zsupers.each do |zsuper_call|
@@ -519,10 +504,10 @@ module Orbacle
519
504
  else
520
505
  connect_yields_to_block_lambda(@graph.get_metod_nodes(super_method.id).yields, zsuper_call.block)
521
506
  end
522
- connect_method_result_to_node(super_method.id, zsuper_call.send_result)
507
+ connect_method_result_to_node(super_method_nodes, zsuper_call.send_result)
523
508
  end
524
509
 
525
- connect_yields_to_block_lambda(@graph.get_metod_nodes(found_method.id).yields, message_send.block)
510
+ connect_yields_to_block_lambda(found_method_nodes.yields, message_send.block)
526
511
  end
527
512
 
528
513
  def lambda_ids_of_block(block)
@@ -629,177 +614,27 @@ module Orbacle
629
614
  end
630
615
  end
631
616
 
632
- def handle_instance_send(class_name, message_send)
633
- if primitive_send?(class_name, message_send.message_send)
634
- handle_primitive(class_name, message_send)
635
- else
636
- handle_instance_nonprimitive_send(class_name, message_send)
637
- end
638
- end
639
-
640
- def handle_class_send(class_name, message_send)
641
- if primitive_class_send?(class_name, message_send.message_send)
642
- handle_class_primitive(class_name, message_send)
643
- else
644
- handle_class_nonprimitive_send(class_name, message_send)
645
- end
646
- end
647
-
648
617
  def handle_super_send(super_send)
649
618
  return if super_send.method_id.nil?
650
619
  super_method = @state.find_super_method(super_send.method_id)
651
620
  return if super_method.nil?
652
621
 
653
- handle_custom_message_send(super_method, super_send)
622
+ super_method_nodes = @graph.get_metod_nodes(super_method.id)
623
+ handle_custom_message_send(super_method, super_send, super_method_nodes)
654
624
 
655
- connect_method_result_to_node(super_method.id, super_send.send_result)
625
+ connect_method_result_to_node(super_method_nodes, super_send.send_result)
656
626
  end
657
627
 
658
- def connect_method_result_to_node(method_id, node)
659
- method_result_node = @graph.get_metod_nodes(method_id).result
628
+ def connect_method_result_to_node(method_nodes, node)
629
+ method_result_node = method_nodes.result
660
630
  if !@graph.has_edge?(method_result_node, node)
661
631
  @graph.add_edge(method_result_node, node)
662
632
  @worklist.enqueue_node(node)
663
633
  end
664
634
  end
665
635
 
666
- def primitive_mapping
667
- {
668
- "Array" => {
669
- "map" => method(:send_primitive_array_map),
670
- "each" => method(:send_primitive_array_each),
671
- },
672
- "Object" => {
673
- "class" => method(:send_primitive_object_class),
674
- "clone" => method(:send_primitive_object_freeze),
675
- "dup" => method(:send_primitive_object_freeze),
676
- "freeze" => method(:send_primitive_object_freeze),
677
- "itself" => method(:send_primitive_object_freeze),
678
- "taint" => method(:send_primitive_object_freeze),
679
- "trust" => method(:send_primitive_object_freeze),
680
- "untaint" => method(:send_primitive_object_freeze),
681
- "untrust" => method(:send_primitive_object_freeze),
682
- },
683
- }
684
- end
685
-
686
- def primitive_class_mapping
687
- {
688
- "Object" => {
689
- "class" => method(:send_class_primitive_object_class),
690
- },
691
- }
692
- end
693
-
694
- def primitive_send?(class_name, message_name)
695
- if primitive_mapping[class_name] && primitive_mapping[class_name][message_name]
696
- true
697
- else
698
- false
699
- end
700
- end
701
-
702
- def primitive_class_send?(class_name, message_name)
703
- if primitive_class_mapping[class_name] && primitive_class_mapping[class_name][message_name]
704
- true
705
- else
706
- false
707
- end
708
- end
709
-
710
636
  def constructor_send?(type, message_name)
711
- type.is_a?(ClassType) && message_name == "new"
712
- end
713
-
714
- def handle_primitive(class_name, message_send)
715
- message_name = message_send.message_send
716
- primitive_mapping[class_name][message_name].(class_name, message_send)
717
- end
718
-
719
- def handle_class_primitive(class_name, message_send)
720
- message_name = message_send.message_send
721
- primitive_class_mapping[class_name][message_name].(class_name, message_send)
722
- end
723
-
724
- def send_constructor(type, message_send)
725
- already_handled = @graph.adjacent_vertices(message_send.send_obj).any? do |adjacent_node|
726
- adjacent_node.type == :constructor
727
- end
728
- return if already_handled
729
-
730
- node = Node.new(:constructor, { name: type.name }, nil)
731
- @graph.add_vertex(node)
732
- @graph.add_edge(message_send.send_obj, node)
733
- @worklist.enqueue_node(node)
734
- @graph.add_edge(node, message_send.send_result)
735
- @worklist.enqueue_node(message_send.send_result)
736
- end
737
-
738
- def send_primitive_array_map(_class_name, message_send)
739
- unwrapping_node = Node.new(:unwrap_array, {}, nil)
740
- @graph.add_vertex(unwrapping_node)
741
- @graph.add_edge(message_send.send_obj, unwrapping_node)
742
- @worklist.enqueue_node(unwrapping_node)
743
-
744
- wrapping_node = Node.new(:wrap_array, {}, nil)
745
- @graph.add_vertex(wrapping_node)
746
- @graph.add_edge(wrapping_node, message_send.send_result)
747
- @worklist.enqueue_node(message_send.send_result)
748
-
749
- lambda_ids_of_block(message_send.block).each do |lambda_id|
750
- block_lambda_nodes = @graph.get_lambda_nodes(lambda_id)
751
- if !block_lambda_nodes.args.values.empty?
752
- arg_node = block_lambda_nodes.args.values.first
753
- @graph.add_edge(unwrapping_node, arg_node)
754
- @worklist.enqueue_node(arg_node)
755
- end
756
-
757
- @graph.add_edge(block_lambda_nodes.result, wrapping_node)
758
- @worklist.enqueue_node(wrapping_node)
759
- end
760
- end
761
-
762
- def send_primitive_array_each(_class_name, message_send)
763
- return unless Worklist::BlockLambda === message_send.block
764
-
765
- unwrapping_node = Node.new(:unwrap_array, {}, nil)
766
- @graph.add_vertex(unwrapping_node)
767
- @graph.add_edge(message_send.send_obj, unwrapping_node)
768
- @worklist.enqueue_node(unwrapping_node)
769
- block_lambda_nodes = @graph.get_lambda_nodes(message_send.block.lambda_id)
770
- if !block_lambda_nodes.args.values.empty?
771
- arg_node = block_lambda_nodes.args.values.first
772
- @graph.add_edge(unwrapping_node, arg_node)
773
- @worklist.enqueue_node(arg_node)
774
- end
775
-
776
- @graph.add_edge(message_send.send_obj, message_send.send_result)
777
- @worklist.enqueue_node(message_send.send_result)
778
- end
779
-
780
- def send_primitive_object_freeze(_class_name, message_send)
781
- @graph.add_edge(message_send.send_obj, message_send.send_result)
782
- @worklist.enqueue_node(message_send.send_result)
783
- end
784
-
785
- def send_primitive_object_class(_class_name, message_send)
786
- extract_class_node = Node.new(:extract_class, {}, nil)
787
- @graph.add_vertex(extract_class_node)
788
- @graph.add_edge(message_send.send_obj, extract_class_node)
789
- @worklist.enqueue_node(extract_class_node)
790
-
791
- @graph.add_edge(extract_class_node, message_send.send_result)
792
- @worklist.enqueue_node(message_send.send_result)
793
- end
794
-
795
- def send_class_primitive_object_class(_class_name, message_send)
796
- extract_class_node = Node.new(:extract_class, {}, nil)
797
- @graph.add_vertex(extract_class_node)
798
- @graph.add_edge(message_send.send_obj, extract_class_node)
799
- @worklist.enqueue_node(extract_class_node)
800
-
801
- @graph.add_edge(extract_class_node, message_send.send_result)
802
- @worklist.enqueue_node(message_send.send_result)
637
+ type.is_a?(ClassType) && message_name == :new
803
638
  end
804
639
 
805
640
  def handle_constructor(node, sources)
@@ -12,8 +12,9 @@ module Orbacle
12
12
  def initialize
13
13
  @message_sends = Set.new
14
14
  @nodes = FastContainers::PriorityQueue.new(:max)
15
- @handled_message_sends = Set.new
15
+ @handled_message_sends = Hash.new {|h,k| h[k] = [] }
16
16
  @nodes_counter = {}
17
+ @nodes_mapping = {}
17
18
  end
18
19
 
19
20
  attr_reader :message_sends, :nodes, :handled_message_sends
@@ -24,11 +25,16 @@ module Orbacle
24
25
  end
25
26
 
26
27
  def enqueue_node(v)
27
- @nodes.push(v, 1)
28
+ if !@nodes_mapping[v]
29
+ @nodes.push(v, 1)
30
+ @nodes_mapping[v] = true
31
+ end
28
32
  end
29
33
 
30
34
  def pop_node
31
- @nodes.pop
35
+ e = @nodes.pop
36
+ @nodes_mapping[e] = false
37
+ e
32
38
  end
33
39
 
34
40
  def count_node(node)
@@ -41,11 +47,15 @@ module Orbacle
41
47
  end
42
48
 
43
49
  def message_send_handled?(message_send)
44
- handled_message_sends.include?(message_send)
50
+ !handled_message_sends[message_send].empty?
45
51
  end
46
52
 
47
- def mark_message_send_as_handled(message_send)
48
- handled_message_sends << message_send
53
+ def mark_message_send_as_handled(message_send, handled_type)
54
+ handled_message_sends[message_send] << handled_type
55
+ end
56
+
57
+ def message_send_handled_by_type?(message_send, handled_type)
58
+ handled_message_sends[message_send].include?(handled_type)
49
59
  end
50
60
  end
51
61
  end
data/orbacle.gemspec CHANGED
@@ -4,13 +4,13 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = 'orbacle'
7
- spec.version = '0.1.0'
7
+ spec.version = '0.2.0'
8
8
  spec.licenses = ['MIT']
9
9
  spec.authors = ['Rafał Łasocha']
10
10
  spec.email = 'orbacle@swistak35.com'
11
11
 
12
12
  spec.summary = "Static analysis for Ruby"
13
- spec.description = "A simple hello world gem"
13
+ spec.description = "Language server using engine allowing for smart jump-to-definitions, understanding metaprogramming definitions, refactoring and more."
14
14
  spec.homepage = 'https://github.com/swistak35/orbacle'
15
15
 
16
16
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features|script)/}) }
@@ -19,7 +19,7 @@ Gem::Specification.new do |spec|
19
19
  spec.require_paths = ['lib']
20
20
 
21
21
  spec.add_dependency 'priority_queue_cxx'
22
- spec.add_dependency 'lsp-protocol', '>= 0.0.3'
22
+ spec.add_dependency 'lsp-protocol', '= 0.0.7'
23
23
  spec.add_dependency 'parser', '~> 2.4.0.2'
24
24
  spec.add_dependency 'rubytree', '~> 0.9.7'
25
25
  spec.add_dependency 'rgl', '~> 0.5.3'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: orbacle
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
  - Rafał Łasocha
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-07-28 00:00:00.000000000 Z
11
+ date: 2018-11-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: priority_queue_cxx
@@ -28,16 +28,16 @@ dependencies:
28
28
  name: lsp-protocol
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ">="
31
+ - - '='
32
32
  - !ruby/object:Gem::Version
33
- version: 0.0.3
33
+ version: 0.0.7
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ">="
38
+ - - '='
39
39
  - !ruby/object:Gem::Version
40
- version: 0.0.3
40
+ version: 0.0.7
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: parser
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -178,7 +178,8 @@ dependencies:
178
178
  - - ">="
179
179
  - !ruby/object:Gem::Version
180
180
  version: '0'
181
- description: A simple hello world gem
181
+ description: Language server using engine allowing for smart jump-to-definitions,
182
+ understanding metaprogramming definitions, refactoring and more.
182
183
  email: orbacle@swistak35.com
183
184
  executables:
184
185
  - orbaclerun
@@ -187,7 +188,6 @@ extra_rdoc_files: []
187
188
  files:
188
189
  - ".gitignore"
189
190
  - ".rspec"
190
- - ".ruby-version"
191
191
  - CHANGELOG.md
192
192
  - Gemfile
193
193
  - Gemfile.lock
@@ -210,6 +210,7 @@ files:
210
210
  - lib/orbacle/constants_tree.rb
211
211
  - lib/orbacle/define_builtins.rb
212
212
  - lib/orbacle/engine.rb
213
+ - lib/orbacle/find_call_under_position.rb
213
214
  - lib/orbacle/find_definition_under_position.rb
214
215
  - lib/orbacle/generic_type.rb
215
216
  - lib/orbacle/global_tree.rb