Skip to content

Commit 03af1de

Browse files
leblocksSasha Gurevich
andauthored
feat(update_database): improvements and preparations before further development
* doc(init_database): added todos with plans * feat(init_database): pulled methods to utils and added stubs for future * feat(update_database): added path_id to inheritance table * feat(drop_by_path): for future implementation of update_database * fix: lint and style * chore(halt): cancelling for now further development * fix(ci): double test execution --------- Co-authored-by: Sasha Gurevich <sagurevich@microsoft.com>
1 parent a9d0aca commit 03af1de

File tree

10 files changed

+251
-98
lines changed

10 files changed

+251
-98
lines changed

.github/workflows/lint.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: Linting and style checking
22

3-
on: [push, pull_request]
3+
on: [push]
44

55
jobs:
66
luacheck:

lua/hopcsharp/database/buffer.lua

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
local BufferedWriter = {}
22
BufferedWriter.__index = BufferedWriter
33

4-
-- Constructor
4+
---@class BufferedWriter
5+
---TODO finish
6+
57
---@param db sqlite_db db object
68
---@param buffer_size number size of the buffer
79
function BufferedWriter:new(db, buffer_size)

lua/hopcsharp/database/init.lua

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ M.__init_db = function()
2323
column = 'integer',
2424
},
2525
inheritance = {
26+
path_id = { type = 'integer', reference = 'files.id' },
2627
name = 'text',
2728
base = 'text',
2829
},
@@ -51,4 +52,26 @@ M.__drop_db = function()
5152
db:eval('vacuum')
5253
end
5354

55+
M.__drop_by_path = function(paths)
56+
if paths == nil or #paths == 0 then
57+
return
58+
end
59+
60+
local db = M.__get_db()
61+
local files = db:select('files', { where = { path = paths } })
62+
63+
if #files == 0 then
64+
return
65+
end
66+
67+
local ids = {}
68+
for _, file in ipairs(files) do
69+
table.insert(ids, file.id)
70+
end
71+
72+
db:delete('files', { where = { id = ids } })
73+
db:delete('inheritance', { where = { path_id = ids } })
74+
db:delete('definitions', { where = { path_id = ids } })
75+
end
76+
5477
return M

lua/hopcsharp/init.lua

Lines changed: 66 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -12,36 +12,19 @@ local BufferedWriter = require('hopcsharp.database.buffer')
1212

1313
local M = {}
1414

15-
local PROCESSING_ERROR_MESSAGE = 'init_database is running, try again later. '
16-
.. 'If init_database failed - restart or manually set vim.g.hopcsharp_processing to false'
17-
1815
vim.g.hopcsharp_processing = false
1916

20-
local function log(message, prefix)
21-
prefix = prefix or 'hopcsharp: '
22-
print(prefix .. message)
23-
end
24-
25-
local function scheduled_iteration(i, iterable, callback)
26-
if i > #iterable then
27-
return
28-
end
29-
30-
callback(i, iterable)
31-
32-
vim.schedule(function()
33-
scheduled_iteration(i + 1, iterable, callback)
34-
end)
35-
end
36-
3717
M.__init_database = function()
3818
-- drop existing schema
3919
database.__drop_db()
4020
local writer = BufferedWriter:new(database.__get_db(), 1000)
4121

22+
local files = parse.__get_source_files()
23+
4224
local counter = 0
43-
scheduled_iteration(1, parse.__get_source_files(), function(i, items)
44-
parse.__parse_tree(items[i], function(tree, file_path_id, file_content, wr)
25+
26+
utils.__scheduled_iteration(files, function(i, item, items)
27+
parse.__parse_tree(item, function(tree, file_path_id, file_content, wr)
4528
local root = tree:root()
4629
definition.__parse_definitions(root, file_path_id, file_content, wr)
4730
inheritance.__parse_inheritance(root, file_path_id, file_content, wr)
@@ -50,7 +33,7 @@ M.__init_database = function()
5033
counter = counter + 1
5134

5235
if counter % 100 == 0 then
53-
log(string.format('processed %s/%s of files', counter, #items), '')
36+
utils.__log(string.format('processed %s/%s of files', counter, #items), '')
5437
end
5538

5639
if counter == #items then
@@ -60,93 +43,82 @@ M.__init_database = function()
6043
end
6144

6245
M.init_database = function()
63-
if vim.g.hopcsharp_processing then
64-
vim.notify(PROCESSING_ERROR_MESSAGE)
65-
return
66-
end
67-
68-
vim.g.hopcsharp_processing = true
69-
70-
local command = {
71-
'nvim',
72-
'--headless',
73-
'-c',
74-
'lua require("hopcsharp").__init_database()',
75-
'-c',
76-
'qa',
77-
}
78-
79-
local line_buffer = {}
80-
-- using table here, for quirks of different OS's
81-
-- to add different line separators
82-
local line_separators = { '\r\r', '\r' }
83-
84-
local function flush_line_buffer()
85-
if #line_buffer > 0 then
86-
log(table.concat(line_buffer, ''))
87-
line_buffer = {}
46+
utils.__block_on_processing(function()
47+
vim.g.hopcsharp_processing = true
48+
49+
local command = {
50+
'nvim',
51+
'--headless',
52+
'-c',
53+
'lua require("hopcsharp").__init_database()',
54+
'-c',
55+
'qa',
56+
}
57+
58+
local line_buffer = {}
59+
-- using table here, for quirks of different OS's
60+
-- to add different line separators
61+
local line_separators = { '\r\r', '\r' }
62+
63+
local function flush_line_buffer()
64+
if #line_buffer > 0 then
65+
utils.__log(table.concat(line_buffer, ''))
66+
line_buffer = {}
67+
end
8868
end
89-
end
90-
91-
local start = os.time()
92-
local on_stdout = function(_, data)
93-
for _, entry in ipairs(data) do
94-
if utils.__contains(line_separators, entry) then
95-
flush_line_buffer()
96-
else
97-
table.insert(line_buffer, entry)
69+
70+
local start = os.time()
71+
local on_stdout = function(_, data)
72+
for _, entry in ipairs(data) do
73+
if utils.__contains(line_separators, entry) then
74+
flush_line_buffer()
75+
else
76+
table.insert(line_buffer, entry)
77+
end
9878
end
9979
end
100-
end
101-
102-
local on_exit = function(_)
103-
flush_line_buffer()
104-
vim.g.hopcsharp_processing = false
105-
local elapsed = os.difftime(os.time(), start)
106-
log('finished processing files ' .. elapsed .. 's elapsed')
107-
end
108-
109-
-- spawn actual parsing in a separate instance of neovim
110-
vim.fn.jobstart(command, {
111-
cwd = vim.fn.getcwd(),
112-
on_stdout = on_stdout,
113-
on_exit = on_exit,
114-
pty = true,
115-
stdin = nil,
116-
})
80+
81+
local on_exit = function(_)
82+
flush_line_buffer()
83+
vim.g.hopcsharp_processing = false
84+
local elapsed = os.difftime(os.time(), start)
85+
utils.__log('finished processing files ' .. elapsed .. 's elapsed')
86+
end
87+
88+
-- spawn actual parsing in a separate instance of neovim
89+
vim.fn.jobstart(command, {
90+
cwd = vim.fn.getcwd(),
91+
on_stdout = on_stdout,
92+
on_exit = on_exit,
93+
pty = true,
94+
stdin = nil,
95+
})
96+
end)
11797
end
11898

11999
M.hop_to_definition = function(config)
120-
if vim.g.hopcsharp_processing then
121-
vim.notify(PROCESSING_ERROR_MESSAGE)
122-
return
123-
end
124-
hop.__hop_to_definition(config)
100+
utils.__block_on_processing(function()
101+
hop.__hop_to_definition(config)
102+
end)
125103
end
126104

127105
M.hop_to_implementation = function(config)
128-
if vim.g.hopcsharp_processing then
129-
vim.notify(PROCESSING_ERROR_MESSAGE)
130-
return
131-
end
132-
hop.__hop_to_implementation(config)
106+
utils.__block_on_processing(function()
107+
hop.__hop_to_implementation(config)
108+
end)
133109
end
134110

135111
M.get_type_hierarchy = function()
136-
if vim.g.hopcsharp_processing then
137-
vim.notify(PROCESSING_ERROR_MESSAGE)
138-
return
139-
end
140-
hierarchy.__get_type_hierarchy()
112+
utils.__block_on_processing(function()
113+
hierarchy.__get_type_hierarchy()
114+
end)
141115
end
142116

143117
---@return sqlite_db
144118
M.get_db = function()
145-
if vim.g.hopcsharp_processing then
146-
vim.notify(PROCESSING_ERROR_MESSAGE)
147-
return
148-
end
149-
return database.__get_db()
119+
return utils.__block_on_processing(function()
120+
return database.__get_db()
121+
end)
150122
end
151123

152124
return M

lua/hopcsharp/parse/inheritance.lua

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,15 @@ local query = require('hopcsharp.parse.query')
44
local M = {}
55

66
---@param tree TSNode under which the search will occur
7+
---@param path_id number file path id
78
---@param file_content string file content
89
---@param writer BufferedWriter buffered database writer
9-
M.__parse_inheritance = function(tree, _, file_content, writer)
10+
M.__parse_inheritance = function(tree, path_id, file_content, writer)
1011
for _, match, _ in query.base_identifier:iter_matches(tree, file_content, 0, -1) do
11-
local entry = {}
12+
local entry = {
13+
path_id = path_id,
14+
}
15+
1216
for id, nodes in pairs(match) do
1317
local name = query.base_identifier.captures[id]
1418
for _, node in ipairs(nodes) do

lua/hopcsharp/utils.lua

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,44 @@ M.__trim_spaces = function(word)
3131
return string.gsub(word, '%s+', '')
3232
end
3333

34+
M.__block_on_processing = function(callback)
35+
local message = 'init_database is running, try again later. '
36+
.. 'If init_database failed - restart or manually set vim.g.hopcsharp_processing to false'
37+
38+
if vim.g.hopcsharp_processing then
39+
vim.notify(message)
40+
return
41+
end
42+
43+
return callback()
44+
end
45+
46+
M.__log = function(message, prefix)
47+
prefix = prefix or 'hopcsharp: '
48+
print(prefix .. message)
49+
end
50+
51+
---@param entries table to iterate on
52+
---@param callback function will be called on each entry in entries via vim.schedule
53+
M.__scheduled_iteration = function(entries, callback)
54+
if not entries then
55+
return
56+
end
57+
58+
local function iterate(i)
59+
if i > #entries then
60+
-- finished iteration
61+
return
62+
end
63+
64+
callback(i, entries[i], entries)
65+
66+
vim.schedule(function()
67+
iterate(i + 1)
68+
end)
69+
end
70+
71+
iterate(1)
72+
end
73+
3474
return M

test/database/database_spec.lua

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
local database = require('hopcsharp.database')
2+
local utils = require('test.utils')
23

34
describe('database', function()
45
it('__init_db returns db object', function()
@@ -9,4 +10,46 @@ describe('database', function()
910
it('__drop_db can be called', function()
1011
database.__drop_db()
1112
end)
13+
14+
it('__drop_by_path - empty path', function()
15+
utils.init_test_database()
16+
database.__drop_by_path({})
17+
end)
18+
19+
it('__drop_by_path - nil path', function()
20+
utils.init_test_database()
21+
database.__drop_by_path(nil)
22+
end)
23+
24+
it('__drop_by_path - non existing paths', function()
25+
utils.init_test_database()
26+
database.__drop_by_path({
27+
vim.fs.normalize('meow//woof'),
28+
vim.fs.normalize('woofs//meow'),
29+
})
30+
end)
31+
32+
it('__drop_by_path - happy path', function()
33+
utils.init_test_database()
34+
35+
local paths = {
36+
vim.fs.normalize('test\\sources\\get_type_hierarchy.cs'),
37+
vim.fs.normalize('test\\sources\\hop_to_definition.cs'),
38+
}
39+
40+
local db = database.__get_db()
41+
local files = db:select('files', { where = { path = paths } })
42+
43+
database.__drop_by_path(paths)
44+
for _, file in ipairs(files) do
45+
local count = db:eval([[SELECT COUNT(1) FROM files WHERE id = :id ]], { id = file.id })
46+
assert(count[1]['COUNT(1)'] == 0)
47+
48+
count = db:eval([[SELECT COUNT(1) FROM inheritance WHERE path_id = :id ]], { id = file.id })
49+
assert(count[1]['COUNT(1)'] == 0)
50+
51+
count = db:eval([[SELECT COUNT(1) FROM definitions WHERE path_id = :id ]], { id = file.id })
52+
assert(count[1]['COUNT(1)'] == 0)
53+
end
54+
end)
1255
end)

test/parse/inheritance_spec.lua

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,12 @@ describe('parse.inheritance', function()
1717
local rows = db:eval([[select * from inheritance i where i.base = :name ]], { name = 'Interface1' })
1818
assert(#rows == 1)
1919
assert(rows[1].name == 'Class1')
20+
assert(rows[1].path_id ~= nil)
2021

2122
rows = db:eval([[select * from inheritance i where i.base = :name ]], { name = 'Attribute' })
2223
assert(#rows == 1)
2324
assert(rows[1].name == 'Attributed1Attribute')
25+
assert(rows[1].path_id ~= nil)
2426
end, writer)
2527
end)
2628
end)

0 commit comments

Comments
 (0)