lowkey 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 3c9ed7172b4b3902649abd82140869b7d97bb285f12a81283548f2c38c1b15ce
4
+ data.tar.gz: 1d85f8da175513ebea0bc9ba487654f4b1b7275068ac5f1e1d4ae768c196849c
5
+ SHA512:
6
+ metadata.gz: 2192b79de007545b2f01e66967f171fb0aa19fcf1aa3253eb79505169d802c3f8bad2e122b7e393ee2829250dc1992482b5593434d4b20d899ea641bbeeb6705
7
+ data.tar.gz: 0c8e064e9a70f7b6580e3f94058a77371df69cbc744a871207fc466911cd607c9fc48f34f1bedab048a250da6ad1dc4228f553c4832a52edc27bdb5c3ae5a5af
data/lib/lowkey.rb ADDED
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'prism'
4
+
5
+ require_relative 'visitors/visitor'
6
+ require_relative 'proxies/file_proxy'
7
+
8
+ module Lowkey
9
+ class << self
10
+ def keys
11
+ @keys ||= {}
12
+ end
13
+
14
+ def [](key)
15
+ keys[key]
16
+ end
17
+
18
+ def load(file_path:)
19
+ root_node = Prism.parse_file(file_path).value
20
+ file_proxy = FileProxy.new(path: file_path, root_node:)
21
+
22
+ parent_map = ParentMap.new(root_node:)
23
+ visitor = Visitor.new(file_proxy:, parent_map:)
24
+ root_node.accept(visitor)
25
+
26
+ map_file_path(file_proxy:)
27
+ map_definitions(file_proxy:)
28
+
29
+ file_proxy
30
+ end
31
+
32
+ def clear
33
+ keys.clear
34
+ end
35
+
36
+ private
37
+
38
+ def map_file_path(file_proxy:)
39
+ keys[file_proxy.path] = file_proxy
40
+ end
41
+
42
+ def map_definitions(file_proxy:)
43
+ file_proxy.definitions.each_key do |namespace|
44
+ keys[namespace] ||= []
45
+ keys[namespace] << file_proxy
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Lowkey
4
+ class ParentMap
5
+ def initialize(root_node:)
6
+ @parent_map = {}
7
+ @current_parent = nil
8
+
9
+ map(root_node)
10
+ end
11
+
12
+ def [](node)
13
+ @parent_map[node]
14
+ end
15
+
16
+ private
17
+
18
+ def map(node)
19
+ @parent_map[node] = @current_parent
20
+
21
+ old_parent = @current_parent
22
+ @current_parent = node
23
+
24
+ node.compact_child_nodes.each do |n|
25
+ map(n)
26
+ end
27
+
28
+ @current_parent = old_parent
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'forwardable'
4
+
5
+ module Lowkey
6
+ class ClassProxy
7
+ attr_reader :namespace, :file_proxy, :start_line, :end_line
8
+ attr_accessor :private_start_line, :class_methods, :instance_methods, :method_calls
9
+
10
+ def initialize(node:, namespace:, file_proxy:)
11
+ @namespace = namespace
12
+ @file_proxy = file_proxy
13
+
14
+ @start_line = node.class_keyword_loc.start_line
15
+ @end_line = node.end_keyword_loc.end_line # class_keyword_loc ?
16
+ @private_start_line = nil
17
+
18
+ @class_methods = {}
19
+ @instance_methods = {}
20
+ @method_calls = []
21
+ end
22
+
23
+ private
24
+
25
+ def class_method?(node)
26
+ return true if node.is_a?(::Prism::DefNode) && node.receiver.instance_of?(Prism::SelfNode) # self.method_name
27
+ return true if node.is_a?(::Prism::SingletonClassNode) # class << self
28
+
29
+ if (parent_node = parent_map.parent(node:))
30
+ return class_method?(parent_node)
31
+ end
32
+
33
+ false
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../maps/parent_map'
4
+ require_relative '../proxies/class_proxy'
5
+
6
+ module Lowkey
7
+ class FileProxy
8
+ attr_reader :path, :start_line, :end_line
9
+ attr_accessor :definitions, :dependencies
10
+
11
+ def initialize(path:, root_node:)
12
+ @path = path
13
+ @start_line = 0
14
+ @end_line = root_node.respond_to?(:end_line) ? root_node.end_line : nil
15
+
16
+ @definitions = {}
17
+ @dependencies = []
18
+ end
19
+
20
+ def class_proxy(node:, parent_map:)
21
+ namespace = namespace(node:, parent_map:).reverse.join('::')
22
+ @definitions[namespace] ||= ClassProxy.new(node:, namespace:, file_proxy: self)
23
+ end
24
+
25
+ private
26
+
27
+ def namespace(node:, parent_map:, namespace: [])
28
+ return namespace if parent_map[node].nil?
29
+
30
+ namespace << node.constant_path.name.to_s if node.respond_to?(:constant_path)
31
+
32
+ namespace(node: parent_map[node], parent_map:, namespace:)
33
+ end
34
+ end
35
+ end
data/lib/version.rb ADDED
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Lowkey
4
+ VERSION = '0.1.0'
5
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ class MethodCallVisitor
4
+ attr_reader :parent_map
5
+
6
+ def initialize(file_proxy:, parent_map:)
7
+ @file_proxy = file_proxy
8
+ @parent_map = parent_map
9
+ end
10
+
11
+ def visit(node)
12
+ class_proxy = @file_proxy.class_proxy(node:, parent_map:)
13
+ class_proxy.method_calls << node
14
+
15
+ return unless node.name == :private && node.respond_to?(:start_line) && class_proxy.start_line && class_proxy.end_line
16
+ return unless node.start_line > class_proxy.start_line && node.start_line < class_proxy.end_line
17
+
18
+ class_proxy.private_start_line = node.start_line
19
+ end
20
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ class MethodClassVisitor
4
+ attr_reader :parent_map
5
+
6
+ def initialize(file_proxy:, parent_map:)
7
+ @file_proxy = file_proxy
8
+ @parent_map = parent_map
9
+ end
10
+
11
+ def visit(node)
12
+ @file_proxy.class_proxy(node:, parent_map:)
13
+ end
14
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ class MethodDefVisitor
4
+ attr_reader :parent_map
5
+
6
+ def initialize(file_proxy:, parent_map:)
7
+ @file_proxy = file_proxy
8
+ @parent_map = parent_map
9
+ end
10
+
11
+ def visit(node)
12
+ class_proxy = @file_proxy.class_proxy(node:, parent_map:)
13
+
14
+ if class_proxy.class_method?(node:, parent_map:)
15
+ class_proxy.class_methods[node.name] = node
16
+ else
17
+ class_proxy.instance_methods[node.name] = node
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'method_call_visitor'
4
+ require_relative 'method_class_visitor'
5
+ require_relative 'method_def_visitor'
6
+
7
+ module Lowkey
8
+ class Visitor < Prism::Visitor
9
+ def initialize(file_proxy:, parent_map:)
10
+ @method_call_visitor = MethodCallVisitor.new(file_proxy:, parent_map:)
11
+ @method_class_visitor = MethodClassVisitor.new(file_proxy:, parent_map:)
12
+ @method_def_visitor = MethodDefVisitor.new(file_proxy:, parent_map:)
13
+ end
14
+
15
+ def visit_call_node(node)
16
+ @method_call_visitor.visit(node)
17
+ super
18
+ end
19
+
20
+ def visit_class_node(node)
21
+ @method_class_visitor.visit(node)
22
+ super
23
+ end
24
+
25
+ def visit_def_node(node)
26
+ @method_def_visitor.visit(node)
27
+ super
28
+ end
29
+ end
30
+ end
metadata ADDED
@@ -0,0 +1,65 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lowkey
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - maedi
8
+ bindir: exe
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: prism
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '0'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: '0'
26
+ description: PRISM is amazing but we need to use it responsibly and only load the
27
+ AST once, do that with Lowkey!
28
+ email:
29
+ - maediprichard@gmail.com
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - lib/lowkey.rb
35
+ - lib/maps/parent_map.rb
36
+ - lib/proxies/class_proxy.rb
37
+ - lib/proxies/file_proxy.rb
38
+ - lib/version.rb
39
+ - lib/visitors/method_call_visitor.rb
40
+ - lib/visitors/method_class_visitor.rb
41
+ - lib/visitors/method_def_visitor.rb
42
+ - lib/visitors/visitor.rb
43
+ homepage: https://github.com/low-rb/lowkey
44
+ licenses: []
45
+ metadata:
46
+ homepage_uri: https://github.com/low-rb/lowkey
47
+ source_code_uri: https://github.com/low-rb/lowkey/src/branch/main
48
+ rdoc_options: []
49
+ require_paths:
50
+ - lib
51
+ required_ruby_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: 3.3.0
56
+ required_rubygems_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ requirements: []
62
+ rubygems_version: 3.7.2
63
+ specification_version: 4
64
+ summary: An API for accessing PRISM metadata easily and efficiently
65
+ test_files: []