orbacle 0.1.0 → 0.2.0

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