lowkey 0.3.2 → 0.4.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 +4 -4
- data/lib/adapters/adapter_loader.rb +1 -1
- data/lib/adapters/sinatra_adapter.rb +15 -8
- data/lib/factories/proxy_factory.rb +34 -8
- data/lib/factories/source_factory.rb +77 -0
- data/lib/interfaces/proxy.rb +13 -5
- data/lib/lowkey.rb +6 -4
- data/lib/models/source.rb +39 -0
- data/lib/proxies/body_proxy.rb +11 -0
- data/lib/proxies/class_proxy.rb +6 -11
- data/lib/proxies/file_proxy.rb +11 -24
- data/lib/proxies/method_proxy.rb +6 -6
- data/lib/proxies/param_proxy.rb +4 -5
- data/lib/proxies/return_proxy.rb +3 -4
- data/lib/queries/query.rb +11 -0
- data/lib/version.rb +1 -1
- data/lib/visitors/method_call_visitor.rb +9 -2
- data/lib/visitors/method_class_visitor.rb +26 -2
- data/lib/visitors/method_def_visitor.rb +9 -13
- metadata +4 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 29b11d6aea2b779089fd087a90495983424bc601eed544dd05275067a6e4f42d
|
|
4
|
+
data.tar.gz: 0a712a5ff40e024de4b38c00899d9d63b899595e14a2a17e636241da9caf65ed
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ec78422aac7af3ec938be6e39a2bda2d2c85824d6060df0ceb655062abc8b539a2af1ed0c739043ee6820c1ef5e5395af89cc63383f4f42624692f138d105436
|
|
7
|
+
data.tar.gz: cd35dcf2ffe61ff07568e8aeb0db5632da57c6927bb7946118f31f98ee942e3dbeff58c537a6654f2b195edc9d2ef9eda06956c4af8f67958cbf09018d257bbd
|
|
@@ -9,7 +9,7 @@ module Lowkey
|
|
|
9
9
|
def load(file_proxy:)
|
|
10
10
|
class_proxies = file_proxy.definitions.values.filter { |definition| definition.instance_of?(ClassProxy) }
|
|
11
11
|
class_proxies.each do |class_proxy|
|
|
12
|
-
SinatraAdapter.new(class_proxy:).load
|
|
12
|
+
SinatraAdapter.new(file_proxy:, class_proxy:).load
|
|
13
13
|
end
|
|
14
14
|
end
|
|
15
15
|
end
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative '../factories/source_factory'
|
|
3
4
|
require_relative '../interfaces/adapter'
|
|
4
5
|
|
|
5
6
|
module Lowkey
|
|
6
7
|
class SinatraAdapter < Adapter
|
|
7
|
-
def initialize(class_proxy:)
|
|
8
|
+
def initialize(file_proxy:, class_proxy:)
|
|
9
|
+
@file_proxy = file_proxy
|
|
8
10
|
@class_proxy = class_proxy
|
|
9
|
-
@file_path = class_proxy.file_path
|
|
10
11
|
end
|
|
11
12
|
|
|
12
13
|
def load # rubocop:disable Metrics/AbcSize
|
|
@@ -20,19 +21,25 @@ module Lowkey
|
|
|
20
21
|
pattern = arguments_node.arguments.first.content
|
|
21
22
|
route = "#{method_call_node.name.upcase} #{pattern}"
|
|
22
23
|
name = route
|
|
23
|
-
|
|
24
|
-
start_line = method_call_node.start_line
|
|
24
|
+
source = SourceFactory.method_call_source(method_call_node:, arguments_node:, file_path:, lines:)
|
|
25
25
|
|
|
26
|
-
next unless (return_proxy = ProxyFactory.return_proxy(method_node: method_call_node, name:,
|
|
26
|
+
next unless (return_proxy = ProxyFactory.return_proxy(method_node: method_call_node, name:, source:))
|
|
27
27
|
|
|
28
|
-
param_proxies = [ParamProxy.new(
|
|
28
|
+
param_proxies = [ParamProxy.new(source:, name:, type: :pos_req, position: 0)]
|
|
29
|
+
method_proxy = MethodProxy.new(source:, name:, param_proxies:, return_proxy:)
|
|
29
30
|
|
|
30
|
-
@class_proxy.keyed_methods[route] =
|
|
31
|
+
@class_proxy.keyed_methods[route] = method_proxy
|
|
31
32
|
end
|
|
32
33
|
end
|
|
33
34
|
|
|
34
35
|
private
|
|
35
36
|
|
|
36
|
-
|
|
37
|
+
def file_path
|
|
38
|
+
@file_proxy.file_path
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def lines
|
|
42
|
+
@file_proxy.lines
|
|
43
|
+
end
|
|
37
44
|
end
|
|
38
45
|
end
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative '../factories/source_factory'
|
|
4
|
+
require_relative '../proxies/body_proxy'
|
|
5
|
+
require_relative '../proxies/class_proxy'
|
|
6
|
+
require_relative '../proxies/file_proxy'
|
|
3
7
|
require_relative '../proxies/method_proxy'
|
|
4
8
|
require_relative '../proxies/param_proxy'
|
|
5
9
|
require_relative '../proxies/return_proxy'
|
|
@@ -7,7 +11,31 @@ require_relative '../proxies/return_proxy'
|
|
|
7
11
|
module Lowkey
|
|
8
12
|
class ProxyFactory
|
|
9
13
|
class << self
|
|
10
|
-
def
|
|
14
|
+
def file_proxy(root_node:, file_path:)
|
|
15
|
+
source = SourceFactory.file_source(root_node:, file_path:)
|
|
16
|
+
FileProxy.new(root_node:, source:)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def class_proxy(node:, namespace:, file_path:, lines:)
|
|
20
|
+
source = SourceFactory.class_source(node:, namespace:, file_path:, lines:)
|
|
21
|
+
name = node.respond_to?(:name) ? node.name : 'Object'
|
|
22
|
+
ClassProxy.new(node:, name:, namespace:, source:)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def method_proxy(method_node:, file_proxy:)
|
|
26
|
+
name = method_node.name
|
|
27
|
+
|
|
28
|
+
method_source = SourceFactory.method_source(method_node:, file_path: file_proxy.file_path, lines: file_proxy.lines)
|
|
29
|
+
body_source = SourceFactory.body_source(method_source:)
|
|
30
|
+
|
|
31
|
+
param_proxies = param_proxies(parameters_node: method_node.parameters, file_path: file_proxy.file_path, source: method_source)
|
|
32
|
+
body_proxy = BodyProxy.new(name:, source: body_source)
|
|
33
|
+
return_proxy = return_proxy(name:, method_node:, source: method_source)
|
|
34
|
+
|
|
35
|
+
MethodProxy.new(name:, source: method_source, param_proxies:, body_proxy:, return_proxy:)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def param_proxies(parameters_node:, source:, file_path:)
|
|
11
39
|
return [] if parameters_node.nil?
|
|
12
40
|
|
|
13
41
|
param_types = {
|
|
@@ -19,24 +47,22 @@ module Lowkey
|
|
|
19
47
|
|
|
20
48
|
params = [*parameters_node.requireds, *parameters_node.optionals, *parameters_node.keywords]
|
|
21
49
|
params.map.with_index do |param, position|
|
|
22
|
-
type = param_types[param.class]
|
|
23
50
|
name = param.name
|
|
24
|
-
|
|
25
|
-
|
|
51
|
+
source = SourceFactory.param_source(param_node: param, file_path:, lines: source.lines)
|
|
52
|
+
type = param_types[param.class]
|
|
26
53
|
value = param.respond_to?(:value) ? param.value.slice : ':LOWKEY_UNDEFINED'
|
|
27
54
|
|
|
28
|
-
ParamProxy.new(
|
|
55
|
+
ParamProxy.new(name:, source:, type:, position:, value:)
|
|
29
56
|
end
|
|
30
57
|
end
|
|
31
58
|
|
|
32
|
-
def return_proxy(method_node:, name:,
|
|
59
|
+
def return_proxy(method_node:, name:, source:)
|
|
33
60
|
return_node = find_return_node(method_node:)
|
|
34
61
|
return nil if return_node.nil?
|
|
35
62
|
|
|
36
|
-
start_line = return_node.start_line
|
|
37
63
|
value = return_node.body.slice
|
|
38
64
|
|
|
39
|
-
ReturnProxy.new(name:,
|
|
65
|
+
ReturnProxy.new(name:, source:, value:)
|
|
40
66
|
end
|
|
41
67
|
|
|
42
68
|
private
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../models/source'
|
|
4
|
+
|
|
5
|
+
module Lowkey
|
|
6
|
+
class SourceFactory
|
|
7
|
+
class << self
|
|
8
|
+
def file_source(root_node:, file_path:)
|
|
9
|
+
end_line = root_node.respond_to?(:end_line) ? root_node.end_line : nil
|
|
10
|
+
|
|
11
|
+
Source.new(file_path:, scope: 'file', lines: root_node.script_lines, start_line: 0, end_line:)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# @param node: Either the class node or the main object node.
|
|
15
|
+
def class_source(node:, namespace:, file_path:, lines:)
|
|
16
|
+
start_line = node.respond_to?(:class_keyword_loc) ? node.class_keyword_loc.start_line : 0
|
|
17
|
+
end_line = node.respond_to?(:end_keyword_loc) ? node.end_keyword_loc.end_line : start_line
|
|
18
|
+
end_line = node.end_line if namespace == 'Object'
|
|
19
|
+
scope = node.respond_to?(:name) ? node.name : 'Object'
|
|
20
|
+
|
|
21
|
+
Source.new(file_path:, scope:, lines:, start_line:, end_line:)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def method_source(method_node:, file_path:, lines:)
|
|
25
|
+
scope = method_node.name
|
|
26
|
+
start_line = method_node.start_line
|
|
27
|
+
end_line = method_node.end_line
|
|
28
|
+
end_line = end_line_from_indent(method_node:, lines:) if end_line > lines.count
|
|
29
|
+
|
|
30
|
+
Source.new(file_path:, scope:, lines:, start_line:, end_line:)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def param_source(param_node:, file_path:, lines:)
|
|
34
|
+
scope = param_node.name
|
|
35
|
+
start_line = param_node.start_line
|
|
36
|
+
end_line = param_node.end_line
|
|
37
|
+
|
|
38
|
+
Source.new(file_path:, scope:, lines:, start_line:, end_line:)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def body_source(method_source:)
|
|
42
|
+
# TODO: Handle multi-line return proxy which increases body start line.
|
|
43
|
+
start_line = method_source.start_line + 1
|
|
44
|
+
end_line = method_source.end_line - 1
|
|
45
|
+
|
|
46
|
+
Source.new(file_path: method_source.file_path, scope: method_source.scope, lines: method_source.lines, start_line:, end_line:)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def method_call_source(method_call_node:, arguments_node:, file_path:, lines:)
|
|
50
|
+
pattern = arguments_node.arguments.first.content
|
|
51
|
+
scope = "#{method_call_node.name.upcase} #{pattern}"
|
|
52
|
+
start_line = method_call_node.start_line
|
|
53
|
+
end_line = method_call_node.end_line
|
|
54
|
+
|
|
55
|
+
Source.new(file_path:, scope:, lines:, start_line:, end_line:)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
private
|
|
59
|
+
|
|
60
|
+
# TODO: end_line = start_line if it's an endless method like "def method = expression".
|
|
61
|
+
def end_line_from_indent(method_node:, lines:)
|
|
62
|
+
end_index = nil
|
|
63
|
+
|
|
64
|
+
index = method_node.start_line - 1
|
|
65
|
+
indent = lines[index].split('def').first
|
|
66
|
+
|
|
67
|
+
while end_index.nil?
|
|
68
|
+
end_index = index if lines[index].nil?
|
|
69
|
+
end_index = index if lines[index].start_with?("#{indent}end")
|
|
70
|
+
index += 1
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
end_index + 1
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
data/lib/interfaces/proxy.rb
CHANGED
|
@@ -1,13 +1,21 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'forwardable'
|
|
4
|
+
|
|
3
5
|
module Lowkey
|
|
6
|
+
# Proxy and Source abstract away nodes and avoid referencing the node on the proxy itself. Will this change?
|
|
7
|
+
# The goal is to make an API that's indiependent of the AST, that can manipulate source code line by line.
|
|
4
8
|
class Proxy
|
|
5
|
-
|
|
9
|
+
extend Forwardable
|
|
10
|
+
|
|
11
|
+
attr_reader :name
|
|
12
|
+
|
|
13
|
+
def_delegators :@source, :file_path, :lines, :start_line, :scope
|
|
14
|
+
def_delegators :@source, :wrap, :export
|
|
6
15
|
|
|
7
|
-
def initialize(
|
|
8
|
-
@
|
|
9
|
-
@
|
|
10
|
-
@scope = scope
|
|
16
|
+
def initialize(name:, source:)
|
|
17
|
+
@name = name
|
|
18
|
+
@source = source
|
|
11
19
|
end
|
|
12
20
|
end
|
|
13
21
|
end
|
data/lib/lowkey.rb
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
require 'prism'
|
|
4
4
|
|
|
5
5
|
require_relative 'adapters/adapter_loader'
|
|
6
|
+
require_relative 'factories/proxy_factory'
|
|
7
|
+
require_relative 'maps/parent_map'
|
|
6
8
|
require_relative 'visitors/visitor'
|
|
7
9
|
require_relative 'proxies/file_proxy'
|
|
8
10
|
|
|
@@ -18,7 +20,7 @@ module Lowkey
|
|
|
18
20
|
|
|
19
21
|
def load(file_path)
|
|
20
22
|
root_node = Prism.parse_file(file_path).value
|
|
21
|
-
file_proxy =
|
|
23
|
+
file_proxy = ProxyFactory.file_proxy(root_node:, file_path:)
|
|
22
24
|
|
|
23
25
|
parent_map = ParentMap.new(root_node:)
|
|
24
26
|
visitor = Visitor.new(file_proxy:, parent_map:)
|
|
@@ -50,11 +52,11 @@ module Lowkey
|
|
|
50
52
|
private
|
|
51
53
|
|
|
52
54
|
def map_file_path(file_proxy:)
|
|
53
|
-
keys[file_proxy.
|
|
55
|
+
keys[file_proxy.file_path] = file_proxy
|
|
54
56
|
|
|
55
57
|
# Map absolute paths to project root/relative paths.
|
|
56
|
-
project_path = file_proxy.
|
|
57
|
-
keys[project_path] = file_proxy if project_path != file_proxy.
|
|
58
|
+
project_path = file_proxy.file_path.delete_prefix(Dir.pwd).delete_prefix('/')
|
|
59
|
+
keys[project_path] = file_proxy if project_path != file_proxy.file_path
|
|
58
60
|
end
|
|
59
61
|
|
|
60
62
|
def map_definitions(file_proxy:)
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Lowkey
|
|
4
|
+
class Source
|
|
5
|
+
attr_reader :file_path, :scope
|
|
6
|
+
attr_accessor :lines, :start_line, :end_line
|
|
7
|
+
|
|
8
|
+
def initialize(file_path:, scope:, lines:, start_line:, end_line: nil)
|
|
9
|
+
@file_path = file_path
|
|
10
|
+
@scope = scope
|
|
11
|
+
|
|
12
|
+
@start_line = start_line
|
|
13
|
+
@end_line = end_line
|
|
14
|
+
@lines = lines
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def wrap(prefix:, suffix:)
|
|
18
|
+
start_line = lines[start_index]
|
|
19
|
+
indent = start_line[/^\s+/]
|
|
20
|
+
lines[start_index] = indent + prefix.to_s + start_line.lstrip
|
|
21
|
+
|
|
22
|
+
lines[end_index] = lines[end_index] + suffix.to_s
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def export
|
|
26
|
+
lines.join
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
def start_index
|
|
32
|
+
start_line - 1
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def end_index
|
|
36
|
+
end_line - 1
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
data/lib/proxies/class_proxy.rb
CHANGED
|
@@ -1,22 +1,21 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative '../interfaces/proxy'
|
|
3
4
|
require_relative '../queries/query'
|
|
4
5
|
|
|
5
6
|
module Lowkey
|
|
6
|
-
class ClassProxy
|
|
7
|
+
class ClassProxy < Proxy
|
|
7
8
|
include Query
|
|
8
9
|
|
|
9
|
-
attr_reader :namespace
|
|
10
|
+
attr_reader :namespace
|
|
10
11
|
attr_accessor :private_start_line, :keyed_methods, :class_methods, :instance_methods, :method_calls
|
|
11
12
|
|
|
12
|
-
def initialize(node:, namespace:,
|
|
13
|
+
def initialize(node:, name:, namespace:, source:)
|
|
14
|
+
super(name:, source:)
|
|
15
|
+
|
|
13
16
|
@node = node
|
|
14
17
|
@namespace = namespace
|
|
15
|
-
@file_proxy = file_proxy
|
|
16
18
|
|
|
17
|
-
@start_line = node.respond_to?(:class_keyword_loc) ? node.class_keyword_loc.start_line : 0
|
|
18
|
-
@end_line = node.respond_to?(:end_keyword_loc) ? node.end_keyword_loc.end_line : @start_line
|
|
19
|
-
@end_line = file_proxy.end_line if namespace == 'Object'
|
|
20
19
|
@private_start_line = nil
|
|
21
20
|
|
|
22
21
|
@keyed_methods = {}
|
|
@@ -30,10 +29,6 @@ module Lowkey
|
|
|
30
29
|
key.start_with?('.') ? query(node: @node, namespace: nil, name: key.delete_prefix('.')) : @keyed_methods[key]
|
|
31
30
|
end
|
|
32
31
|
|
|
33
|
-
def file_path
|
|
34
|
-
@file_proxy.path
|
|
35
|
-
end
|
|
36
|
-
|
|
37
32
|
class << self
|
|
38
33
|
def class_method?(method_node:, parent_map:)
|
|
39
34
|
return true if method_node.is_a?(::Prism::DefNode) && method_node.receiver.instance_of?(Prism::SelfNode) # self.method_name
|
data/lib/proxies/file_proxy.rb
CHANGED
|
@@ -1,50 +1,37 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative '../
|
|
3
|
+
require_relative '../interfaces/proxy'
|
|
4
4
|
require_relative '../proxies/class_proxy'
|
|
5
5
|
require_relative '../queries/query'
|
|
6
6
|
|
|
7
7
|
module Lowkey
|
|
8
|
-
class FileProxy
|
|
8
|
+
class FileProxy < Proxy
|
|
9
9
|
include Query
|
|
10
10
|
|
|
11
|
-
attr_reader :
|
|
11
|
+
attr_reader :root_node
|
|
12
12
|
attr_accessor :definitions, :dependencies
|
|
13
13
|
|
|
14
|
-
def initialize(
|
|
15
|
-
|
|
16
|
-
@root_node = root_node
|
|
14
|
+
def initialize(root_node:, source:)
|
|
15
|
+
super(name: nil, source:)
|
|
17
16
|
|
|
18
|
-
@
|
|
19
|
-
@end_line = root_node.respond_to?(:end_line) ? root_node.end_line : nil
|
|
17
|
+
@root_node = root_node
|
|
20
18
|
|
|
21
19
|
@definitions = {}
|
|
22
20
|
@dependencies = []
|
|
23
21
|
end
|
|
24
22
|
|
|
25
23
|
def [](keypath)
|
|
26
|
-
namespace, *
|
|
27
|
-
|
|
24
|
+
namespace, *file_path = keypath.split('.')
|
|
25
|
+
file_path.empty? ? @definitions[namespace] : query(node: @root_node, namespace:, name: file_path.join)
|
|
28
26
|
end
|
|
29
27
|
|
|
30
28
|
def []=(keypath, value)
|
|
31
29
|
# TODO: Slice the lines in a file and replace with the output of the class proxy.
|
|
32
30
|
end
|
|
33
31
|
|
|
34
|
-
def upsert_class_proxy(
|
|
35
|
-
|
|
36
|
-
namespace
|
|
37
|
-
@definitions[namespace] ||= ClassProxy.new(node:, namespace:, file_proxy: self)
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
private
|
|
41
|
-
|
|
42
|
-
def namespace(node:, parent_map:, namespace: [])
|
|
43
|
-
return namespace if parent_map[node].nil?
|
|
44
|
-
|
|
45
|
-
namespace << node.constant_path.name.to_s if node.respond_to?(:constant_path)
|
|
46
|
-
|
|
47
|
-
namespace(node: parent_map[node], parent_map:, namespace:)
|
|
32
|
+
def upsert_class_proxy(class_proxy:)
|
|
33
|
+
# TODO: Merge duplicate class with existing class.
|
|
34
|
+
@definitions[class_proxy.namespace] ||= class_proxy
|
|
48
35
|
end
|
|
49
36
|
end
|
|
50
37
|
end
|
data/lib/proxies/method_proxy.rb
CHANGED
|
@@ -7,17 +7,17 @@ module Lowkey
|
|
|
7
7
|
class MethodProxy < Proxy
|
|
8
8
|
include Query
|
|
9
9
|
|
|
10
|
-
attr_reader :
|
|
10
|
+
attr_reader :params, :body, :return_proxy
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
super(file_path:, start_line:, scope:)
|
|
12
|
+
def initialize(name:, source:, param_proxies: [], body_proxy: nil, return_proxy: nil)
|
|
13
|
+
super(name:, source:)
|
|
15
14
|
|
|
16
|
-
@name = name
|
|
17
15
|
@params = param_proxies
|
|
16
|
+
@body = body_proxy
|
|
17
|
+
@return_proxy = return_proxy
|
|
18
|
+
|
|
18
19
|
@named_params = name_params
|
|
19
20
|
@tagged_params = tag_params
|
|
20
|
-
@return_proxy = return_proxy
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
def [](key)
|
data/lib/proxies/param_proxy.rb
CHANGED
|
@@ -4,17 +4,16 @@ require_relative '../interfaces/proxy'
|
|
|
4
4
|
|
|
5
5
|
module Lowkey
|
|
6
6
|
class ParamProxy < Proxy
|
|
7
|
-
attr_reader :
|
|
7
|
+
attr_reader :type, :position, :value
|
|
8
8
|
attr_accessor :expression
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
super(file_path:, start_line:, scope:)
|
|
10
|
+
def initialize(name:, source:, type:, position: nil, value: :LOWKEY_UNDEFINED, expression: nil) # rubocop:disable Metrics/ParameterLists
|
|
11
|
+
super(name:, source:)
|
|
13
12
|
|
|
14
|
-
@name = name
|
|
15
13
|
@type = type
|
|
16
14
|
@position = position
|
|
17
15
|
@value = value
|
|
16
|
+
|
|
18
17
|
@expression = expression
|
|
19
18
|
end
|
|
20
19
|
|
data/lib/proxies/return_proxy.rb
CHANGED
|
@@ -4,13 +4,12 @@ require_relative '../interfaces/proxy'
|
|
|
4
4
|
|
|
5
5
|
module Lowkey
|
|
6
6
|
class ReturnProxy < Proxy
|
|
7
|
-
attr_reader :
|
|
7
|
+
attr_reader :value
|
|
8
8
|
attr_accessor :expression
|
|
9
9
|
|
|
10
|
-
def initialize(
|
|
11
|
-
super(
|
|
10
|
+
def initialize(name:, source:, value: :LOWKEY_UNDEFINED, expression: nil)
|
|
11
|
+
super(name:, source:)
|
|
12
12
|
|
|
13
|
-
@name = name
|
|
14
13
|
@value = value
|
|
15
14
|
@expression = expression
|
|
16
15
|
end
|
data/lib/queries/query.rb
CHANGED
|
@@ -8,5 +8,16 @@ module Lowkey
|
|
|
8
8
|
n.respond_to?(:name) && n.name == name.to_sym
|
|
9
9
|
end
|
|
10
10
|
end
|
|
11
|
+
|
|
12
|
+
def namespace(node:, parent_map:, namespace: [])
|
|
13
|
+
if parent_map[node].nil?
|
|
14
|
+
namespace << 'Object' if namespace.empty?
|
|
15
|
+
return namespace.reverse.join('::')
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
namespace << node.constant_path.name.to_s if node.respond_to?(:constant_path)
|
|
19
|
+
|
|
20
|
+
namespace(node: parent_map[node], parent_map:, namespace:)
|
|
21
|
+
end
|
|
11
22
|
end
|
|
12
23
|
end
|
data/lib/version.rb
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative '../queries/query'
|
|
4
|
+
|
|
3
5
|
module Lowkey
|
|
4
6
|
class MethodCallVisitor
|
|
5
|
-
|
|
7
|
+
include Query
|
|
6
8
|
|
|
7
9
|
def initialize(file_proxy:, parent_map:)
|
|
8
10
|
@file_proxy = file_proxy
|
|
@@ -10,7 +12,8 @@ module Lowkey
|
|
|
10
12
|
end
|
|
11
13
|
|
|
12
14
|
def visit(node)
|
|
13
|
-
|
|
15
|
+
namespace = namespace(node:, parent_map:)
|
|
16
|
+
class_proxy = @file_proxy[namespace]
|
|
14
17
|
class_proxy.method_calls << node
|
|
15
18
|
|
|
16
19
|
return unless node.name == :private && node.respond_to?(:start_line) && class_proxy.start_line && class_proxy.end_line
|
|
@@ -18,5 +21,9 @@ module Lowkey
|
|
|
18
21
|
|
|
19
22
|
class_proxy.private_start_line = node.start_line
|
|
20
23
|
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
attr_reader :parent_map
|
|
21
28
|
end
|
|
22
29
|
end
|
|
@@ -1,16 +1,40 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative '../factories/proxy_factory'
|
|
4
|
+
require_relative '../queries/query'
|
|
5
|
+
|
|
3
6
|
module Lowkey
|
|
4
7
|
class MethodClassVisitor
|
|
5
|
-
|
|
8
|
+
include Query
|
|
6
9
|
|
|
7
10
|
def initialize(file_proxy:, parent_map:)
|
|
8
11
|
@file_proxy = file_proxy
|
|
9
12
|
@parent_map = parent_map
|
|
13
|
+
|
|
14
|
+
create_root_class
|
|
10
15
|
end
|
|
11
16
|
|
|
12
17
|
def visit(node)
|
|
13
|
-
|
|
18
|
+
namespace = namespace(node:, parent_map:)
|
|
19
|
+
class_proxy = ProxyFactory.class_proxy(node:, namespace:, file_path:, lines:)
|
|
20
|
+
@file_proxy.upsert_class_proxy(class_proxy:)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
def create_root_class
|
|
26
|
+
class_proxy = ProxyFactory.class_proxy(node: @file_proxy.root_node, namespace: 'Object', file_path:, lines:)
|
|
27
|
+
@file_proxy.upsert_class_proxy(class_proxy:)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
attr_reader :parent_map
|
|
31
|
+
|
|
32
|
+
def file_path
|
|
33
|
+
@file_proxy.file_path
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def lines
|
|
37
|
+
@file_proxy.lines
|
|
14
38
|
end
|
|
15
39
|
end
|
|
16
40
|
end
|
|
@@ -1,28 +1,26 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative '../factories/source_factory'
|
|
3
4
|
require_relative '../factories/proxy_factory'
|
|
5
|
+
require_relative '../queries/query'
|
|
4
6
|
|
|
5
7
|
module Lowkey
|
|
6
8
|
class MethodDefVisitor
|
|
7
|
-
|
|
9
|
+
include Query
|
|
8
10
|
|
|
9
11
|
def initialize(file_proxy:, parent_map:)
|
|
10
12
|
@file_proxy = file_proxy
|
|
11
13
|
@parent_map = parent_map
|
|
12
14
|
end
|
|
13
15
|
|
|
14
|
-
def visit(method_node)
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
param_proxies = ProxyFactory.param_proxies(parameters_node: method_node.parameters, file_path:, scope:)
|
|
20
|
-
return_proxy = ProxyFactory.return_proxy(name:, method_node:, file_path:, scope:)
|
|
21
|
-
method_proxy = MethodProxy.new(file_path:, start_line: method_node.start_line, scope:, name:, param_proxies:, return_proxy:)
|
|
16
|
+
def visit(method_node)
|
|
17
|
+
namespace = namespace(node: method_node, parent_map:)
|
|
18
|
+
class_proxy = file_proxy[namespace]
|
|
19
|
+
method_proxy = ProxyFactory.method_proxy(method_node:, file_proxy:)
|
|
22
20
|
|
|
23
21
|
class_proxy.keyed_methods[method_node.name] = method_proxy
|
|
24
22
|
|
|
25
|
-
# TODO: Implemented as
|
|
23
|
+
# TODO: Implemented as tagged methods similar to tagged params.
|
|
26
24
|
if ClassProxy.class_method?(method_node:, parent_map:)
|
|
27
25
|
class_proxy.class_methods[method_node.name] = method_proxy
|
|
28
26
|
else
|
|
@@ -32,8 +30,6 @@ module Lowkey
|
|
|
32
30
|
|
|
33
31
|
private
|
|
34
32
|
|
|
35
|
-
|
|
36
|
-
@file_proxy.path
|
|
37
|
-
end
|
|
33
|
+
attr_reader :file_proxy, :parent_map
|
|
38
34
|
end
|
|
39
35
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: lowkey
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- maedi
|
|
@@ -34,10 +34,13 @@ files:
|
|
|
34
34
|
- lib/adapters/adapter_loader.rb
|
|
35
35
|
- lib/adapters/sinatra_adapter.rb
|
|
36
36
|
- lib/factories/proxy_factory.rb
|
|
37
|
+
- lib/factories/source_factory.rb
|
|
37
38
|
- lib/interfaces/adapter.rb
|
|
38
39
|
- lib/interfaces/proxy.rb
|
|
39
40
|
- lib/lowkey.rb
|
|
40
41
|
- lib/maps/parent_map.rb
|
|
42
|
+
- lib/models/source.rb
|
|
43
|
+
- lib/proxies/body_proxy.rb
|
|
41
44
|
- lib/proxies/class_proxy.rb
|
|
42
45
|
- lib/proxies/file_proxy.rb
|
|
43
46
|
- lib/proxies/method_proxy.rb
|