yoda-language-server 0.7.0 → 0.7.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|