yoda-language-server 0.7.0 → 0.7.1
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/yoda/store.rb +1 -0
- data/lib/yoda/store/objects/merger.rb +90 -7
- data/lib/yoda/store/objects/patch.rb +3 -2
- data/lib/yoda/store/objects/patch_set.rb +58 -26
- data/lib/yoda/store/registry.rb +15 -7
- data/lib/yoda/store/registry_cache.rb +40 -0
- data/lib/yoda/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a1135858460f719a79d288fd6210011d1380f39ecedf817b06277aa400277e79
|
4
|
+
data.tar.gz: 5fa3c98c453be13419c9e3225d5cbeea81ee1103e77812a1097f251f29c4a39d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6dffa44d4bb6dbe751fdb34c0f47ea2b371deae46e22b85da27dc0c2c57938d8203f593b0990cea379dc708d34c060173dff6c512e2603edc98808d9131b9026
|
7
|
+
data.tar.gz: 2df74769182891b2ef9926a89abf8e8487e4a734a87719ead05374c3bc6b52db53ec4b3f01186de03af60bbf5f54bb1a323a3803a908d78f106fbd3a3d874b90
|
data/lib/yoda/store.rb
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
require 'set'
|
2
|
+
require 'forwardable'
|
3
|
+
|
1
4
|
module Yoda
|
2
5
|
module Store
|
3
6
|
module Objects
|
@@ -36,7 +39,7 @@ module Yoda
|
|
36
39
|
|
37
40
|
# @return [Hash{ Symbol => Object }]
|
38
41
|
def attributes
|
39
|
-
@attributes ||= instances.map { |i| default_attributes.merge(i.to_h) }.reduce { |a, b| merge_attributes(a, b) }
|
42
|
+
@attributes ||= normalize_attributes(instances.map { |i| default_attributes.merge(i.to_h) }.reduce { |a, b| merge_attributes(a, b) })
|
40
43
|
end
|
41
44
|
|
42
45
|
# @param one [Hash{ Symbol => Object }]
|
@@ -45,15 +48,15 @@ module Yoda
|
|
45
48
|
{
|
46
49
|
path: one[:path] || another[:path],
|
47
50
|
document: one[:document] + (one[:document].empty? || another[:document].empty? ? '' : "\n") + another[:document],
|
48
|
-
tag_list: one[:tag_list]
|
49
|
-
sources: one[:sources]
|
51
|
+
tag_list: PendingArray.append(one[:tag_list], another[:tag_list]),
|
52
|
+
sources: PendingSet.merge(one[:sources], another[:sources]),
|
50
53
|
primary_source: one[:primary_source] || another[:primary_source],
|
51
|
-
instance_method_addresses: (one[:instance_method_addresses]
|
52
|
-
mixin_addresses: (one[:mixin_addresses]
|
53
|
-
constant_addresses: (one[:constant_addresses]
|
54
|
+
instance_method_addresses: PendingSet.merge(one[:instance_method_addresses], another[:instance_method_addresses]),
|
55
|
+
mixin_addresses: PendingSet.merge(one[:mixin_addresses], another[:mixin_addresses]),
|
56
|
+
constant_addresses: PendingSet.merge(one[:constant_addresses], another[:constant_addresses]),
|
54
57
|
visibility: one[:visibility] || another[:visibility],
|
55
58
|
parameters: one[:parameters].empty? ? another[:parameters] : one[:parameters],
|
56
|
-
overloads: one[:overloads]
|
59
|
+
overloads: PendingArray.append(one[:overloads], another[:overloads]),
|
57
60
|
superclass_path: select_superclass(one, another),
|
58
61
|
value: one[:value] || another[:value],
|
59
62
|
}
|
@@ -78,6 +81,26 @@ module Yoda
|
|
78
81
|
}
|
79
82
|
end
|
80
83
|
|
84
|
+
# @param attrs [Hash{ Symbol => Object }]
|
85
|
+
# @return [Hash{ Symbol => Object }]
|
86
|
+
def normalize_attributes(attrs)
|
87
|
+
{
|
88
|
+
path: attrs[:path],
|
89
|
+
document: attrs[:document],
|
90
|
+
tag_list: attrs[:tag_list].to_a,
|
91
|
+
sources: attrs[:sources].to_a,
|
92
|
+
primary_source: attrs[:primary_source],
|
93
|
+
instance_method_addresses: attrs[:instance_method_addresses].to_a,
|
94
|
+
mixin_addresses: attrs[:mixin_addresses].to_a,
|
95
|
+
constant_addresses: attrs[:constant_addresses].to_a,
|
96
|
+
visibility: attrs[:visibility],
|
97
|
+
parameters: attrs[:parameters].to_a,
|
98
|
+
overloads: attrs[:overloads].to_a,
|
99
|
+
superclass_path: attrs[:superclass_path],
|
100
|
+
value: attrs[:value],
|
101
|
+
}
|
102
|
+
end
|
103
|
+
|
81
104
|
# @param one [Hash{ Symbol => Object }]
|
82
105
|
# @param another [Hash{ Symbol => Object }]
|
83
106
|
# @return [ScopedPath]
|
@@ -88,6 +111,66 @@ module Yoda
|
|
88
111
|
another[:superclass_path] || one[:superclass_path]
|
89
112
|
end
|
90
113
|
end
|
114
|
+
|
115
|
+
class PendingArray
|
116
|
+
extend Forwardable
|
117
|
+
|
118
|
+
# @param els1 [Array<Object>, PendingArray]
|
119
|
+
# @param others [Array<Array<Object>, PendingArray>]
|
120
|
+
def self.append(els, *others)
|
121
|
+
if els.is_a?(PendingArray)
|
122
|
+
others.reduce(els) { |array, item| array.append(item) }
|
123
|
+
else
|
124
|
+
append(PendingArray.new(els), *others)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
# @return [Array<Object>]
|
129
|
+
attr_reader :array
|
130
|
+
|
131
|
+
delegate %i(to_a each) => :array
|
132
|
+
|
133
|
+
# @param els [Array<Object>]
|
134
|
+
def initialize(els)
|
135
|
+
@array = els.dup
|
136
|
+
end
|
137
|
+
|
138
|
+
# @param els [Array<Object>]
|
139
|
+
def append(els)
|
140
|
+
array.push(*els)
|
141
|
+
self
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
class PendingSet
|
146
|
+
extend Forwardable
|
147
|
+
|
148
|
+
# @param els1 [Array<Object>, PendingSet]
|
149
|
+
# @param els2 [Array<Object>, PendingSet]
|
150
|
+
def self.merge(els1, els2)
|
151
|
+
if els1.is_a?(PendingSet)
|
152
|
+
els1.merge(els2)
|
153
|
+
else
|
154
|
+
PendingSet.new(els1).merge(els2)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
# @return [Set<Object>]
|
159
|
+
attr_reader :set
|
160
|
+
|
161
|
+
delegate %i(to_a each) => :set
|
162
|
+
|
163
|
+
# @param els [Array<Object>]
|
164
|
+
def initialize(els)
|
165
|
+
@set = Set.new(els)
|
166
|
+
end
|
167
|
+
|
168
|
+
# @param els [Array<Object>]
|
169
|
+
def merge(els)
|
170
|
+
set.merge(els)
|
171
|
+
self
|
172
|
+
end
|
173
|
+
end
|
91
174
|
end
|
92
175
|
end
|
93
176
|
end
|
@@ -9,9 +9,10 @@ module Yoda
|
|
9
9
|
attr_reader :registry
|
10
10
|
|
11
11
|
# @param id [String]
|
12
|
-
|
12
|
+
# @param [Array[Addressable], nil]
|
13
|
+
def initialize(id, contents = nil)
|
13
14
|
@id = id
|
14
|
-
@registry =
|
15
|
+
@registry = (contents || []).map { |content| [content.address.to_sym, content] }.to_h
|
15
16
|
end
|
16
17
|
|
17
18
|
# @param addressable [Addressable]
|
@@ -1,78 +1,110 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
1
3
|
module Yoda
|
2
4
|
module Store
|
3
5
|
module Objects
|
4
6
|
# PatchSet manages patch updates and patch outdates.
|
5
7
|
# Besides, this class provides api to modify objects by using owning patches.
|
6
8
|
class PatchSet
|
7
|
-
|
8
|
-
|
9
|
+
class AddressIndex
|
10
|
+
def initialize
|
11
|
+
@index = Hash.new
|
12
|
+
end
|
9
13
|
|
10
|
-
|
11
|
-
|
14
|
+
# @param address [Symbol]
|
15
|
+
# @return [Set<Symbol>]
|
16
|
+
def get(address)
|
17
|
+
index[address] ||= Set.new
|
18
|
+
end
|
19
|
+
|
20
|
+
# @return [Set<Symbol>]
|
21
|
+
def keys
|
22
|
+
index.keys
|
23
|
+
end
|
24
|
+
|
25
|
+
# @param patch [Patch]
|
26
|
+
# @return [void]
|
27
|
+
def register(patch)
|
28
|
+
patch.keys.each do |key|
|
29
|
+
index[key.to_sym] ||= Set.new
|
30
|
+
index[key.to_sym].add(patch.id.to_sym)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# @param patch [Patch]
|
35
|
+
# @return [void]
|
36
|
+
def delete(patch)
|
37
|
+
patch.keys.each do |key|
|
38
|
+
(index[key.to_sym] || []).delete(patch.id.to_sym)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
# @return [{ Symbol => Array<Symbol> }]
|
44
|
+
attr_reader :index
|
45
|
+
end
|
12
46
|
|
13
47
|
def initialize
|
14
48
|
@patches = Hash.new
|
15
|
-
@address_index =
|
49
|
+
@address_index = AddressIndex.new
|
16
50
|
end
|
17
51
|
|
18
52
|
# @param patch [Patch]
|
19
53
|
# @return [void]
|
20
54
|
def register(patch)
|
21
|
-
|
55
|
+
address_index.register(patch)
|
22
56
|
patches[patch.id.to_sym] = patch
|
23
57
|
end
|
24
58
|
|
25
59
|
# @param id [String, Symbol]
|
26
60
|
def delete(id)
|
61
|
+
if patch = patches[id.to_sym]
|
62
|
+
address_index.delete(patch)
|
63
|
+
end
|
27
64
|
patches.delete(id.to_sym)
|
28
65
|
end
|
29
66
|
|
30
67
|
# @param object [Addressable]
|
31
68
|
# @return [Addressable]
|
32
69
|
def patch(object)
|
33
|
-
|
34
|
-
objects_in_patch = (address_index[object.address.to_sym] || []).map { |patch_id| patches[patch_id].find(object.address.to_sym) }
|
70
|
+
objects_in_patch = get_patches(object.address)
|
35
71
|
Merger.new([object, *objects_in_patch]).merged_instance
|
36
72
|
end
|
37
73
|
|
38
74
|
# @param address [String, Symbol]
|
39
75
|
# @return [Addressable, nil]
|
40
76
|
def find(address)
|
41
|
-
|
42
|
-
if (patch_ids = address_index[address.to_sym] || []).empty?
|
77
|
+
if (patches = get_patches(address)).empty?
|
43
78
|
nil
|
44
79
|
else
|
45
|
-
|
46
|
-
Merger.new(objects).merged_instance
|
80
|
+
Merger.new(patches).merged_instance
|
47
81
|
end
|
48
82
|
end
|
49
83
|
|
50
84
|
# @return [Array<Symbol>]
|
51
85
|
def keys
|
52
|
-
address_index.keys
|
86
|
+
address_index.keys.to_a
|
53
87
|
end
|
54
88
|
|
55
89
|
# @param address [String, Symbol]
|
56
90
|
# @return [true, false]
|
57
91
|
def has_key?(address)
|
58
|
-
|
59
|
-
address_index[address.to_sym] && !address_index[address.to_sym].empty?
|
92
|
+
!address_index.get(address.to_sym).empty?
|
60
93
|
end
|
61
94
|
|
62
95
|
private
|
63
96
|
|
64
|
-
# @
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
address_index[key.to_sym].push(patch.id.to_sym)
|
70
|
-
end
|
71
|
-
end
|
97
|
+
# @return [AddressIndex]
|
98
|
+
attr_reader :address_index
|
99
|
+
|
100
|
+
# @return [{ Symbol => Patch }]
|
101
|
+
attr_reader :patches
|
72
102
|
|
73
|
-
# @param address [Symbol]
|
74
|
-
|
75
|
-
|
103
|
+
# @param address [String, Symbol]
|
104
|
+
# @return [Array<Patch>]
|
105
|
+
def get_patches(address)
|
106
|
+
patch_ids = address_index.get(address.to_sym)
|
107
|
+
patch_ids.map { |id| patches[id].find(address.to_sym) }
|
76
108
|
end
|
77
109
|
end
|
78
110
|
end
|
data/lib/yoda/store/registry.rb
CHANGED
@@ -12,6 +12,8 @@ module Yoda
|
|
12
12
|
def initialize(adapter = nil)
|
13
13
|
@patch_set = Objects::PatchSet.new
|
14
14
|
@adapter = adapter
|
15
|
+
@registry_cache = RegistryCache.new
|
16
|
+
@lock = Concurrent::ReentrantReadWriteLock.new
|
15
17
|
end
|
16
18
|
|
17
19
|
# @return [Objects::ProjectStatus, nil]
|
@@ -32,10 +34,12 @@ module Yoda
|
|
32
34
|
# @return [Objects::Base, nil]
|
33
35
|
def find(path)
|
34
36
|
lock.with_read_lock do
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
37
|
+
registry_cache.fetch_or_calc(path) do
|
38
|
+
if adapter&.exist?(path)
|
39
|
+
patch_set.patch(adapter.get(path))
|
40
|
+
else
|
41
|
+
patch_set.find(path)
|
42
|
+
end
|
39
43
|
end
|
40
44
|
end
|
41
45
|
end
|
@@ -43,6 +47,7 @@ module Yoda
|
|
43
47
|
# @param patch [Patch]
|
44
48
|
def add_patch(patch)
|
45
49
|
lock.with_write_lock do
|
50
|
+
registry_cache.clear_from_patch(patch)
|
46
51
|
patch_set.register(patch)
|
47
52
|
end
|
48
53
|
end
|
@@ -57,6 +62,7 @@ module Yoda
|
|
57
62
|
|
58
63
|
def clear
|
59
64
|
lock.with_write_lock do
|
65
|
+
registry_cache.delete_all
|
60
66
|
adapter.clear
|
61
67
|
end
|
62
68
|
end
|
@@ -77,6 +83,7 @@ module Yoda
|
|
77
83
|
adapter.sync
|
78
84
|
Logger.info "saved #{el_keys.length} keys."
|
79
85
|
@patch_set = Objects::PatchSet.new
|
86
|
+
registry_cache.delete_all
|
80
87
|
end
|
81
88
|
end
|
82
89
|
|
@@ -88,10 +95,11 @@ module Yoda
|
|
88
95
|
# @return [Objects::PatchSet]
|
89
96
|
attr_reader :patch_set
|
90
97
|
|
98
|
+
# @return [RegistryCache]
|
99
|
+
attr_reader :registry_cache
|
100
|
+
|
91
101
|
# @return [Concurrent::ReentrantReadWriteLock]
|
92
|
-
|
93
|
-
@lock ||= Concurrent::ReentrantReadWriteLock.new
|
94
|
-
end
|
102
|
+
attr_reader :lock
|
95
103
|
|
96
104
|
def keys
|
97
105
|
Set.new(adapter&.keys.map(&:to_s) || []).union(patch_set.keys)
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'concurrent'
|
2
|
+
|
3
|
+
module Yoda
|
4
|
+
module Store
|
5
|
+
# Registry Cache is a cache layer for {Registry}.
|
6
|
+
# This class intended to reduce patch calculations of {PatchSet#patch}.
|
7
|
+
class RegistryCache
|
8
|
+
def initialize
|
9
|
+
@data = Concurrent::Map.new
|
10
|
+
end
|
11
|
+
|
12
|
+
# @param key [String, Symbol]
|
13
|
+
def fetch_or_calc(key)
|
14
|
+
if cache = data.get(key.to_sym)
|
15
|
+
return cache
|
16
|
+
end
|
17
|
+
yield.tap { |value| data.put_if_absent(key.to_sym, value) }
|
18
|
+
end
|
19
|
+
|
20
|
+
# @param key [String, Symbol]
|
21
|
+
def delete(key)
|
22
|
+
data.delete(key.to_sym)
|
23
|
+
end
|
24
|
+
|
25
|
+
def delete_all
|
26
|
+
data.clear
|
27
|
+
end
|
28
|
+
|
29
|
+
# @param patch [Objects::Patch]
|
30
|
+
def clear_from_patch(patch)
|
31
|
+
patch.keys.each { |key| delete(key) }
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
# @return [Concurrent::Map]
|
37
|
+
attr_reader :data
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/lib/yoda/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: yoda-language-server
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.7.
|
4
|
+
version: 0.7.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tomoya Chiba
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-09-
|
11
|
+
date: 2018-09-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: yard
|
@@ -446,6 +446,7 @@ files:
|
|
446
446
|
- lib/yoda/store/query/find_method.rb
|
447
447
|
- lib/yoda/store/query/find_signature.rb
|
448
448
|
- lib/yoda/store/registry.rb
|
449
|
+
- lib/yoda/store/registry_cache.rb
|
449
450
|
- lib/yoda/store/yard_importer.rb
|
450
451
|
- lib/yoda/typing.rb
|
451
452
|
- lib/yoda/typing/context.rb
|