From d891ba4f2e3627ab95575385c016c3448a525d0f Mon Sep 17 00:00:00 2001 From: TJ DeVries Date: Fri, 18 Sep 2020 00:11:19 -0400 Subject: [PATCH] feat: add some tests and improve perf --- lua/telescope/builtin.lua | 2 +- lua/telescope/pickers.lua | 26 ++++++- lua/tests/automated/find_and_sort_spec.lua | 87 ++++++++++++++++++++++ lua/tests/automated/resolver_spec.lua | 71 ++++++++++++++++++ lua/tests/automated/telescope_spec.lua | 4 +- 5 files changed, 183 insertions(+), 7 deletions(-) create mode 100644 lua/tests/automated/find_and_sort_spec.lua create mode 100644 lua/tests/automated/resolver_spec.lua diff --git a/lua/telescope/builtin.lua b/lua/telescope/builtin.lua index bd8e5d5..02bc0db 100644 --- a/lua/telescope/builtin.lua +++ b/lua/telescope/builtin.lua @@ -118,7 +118,7 @@ builtin.live_grep = function(opts) return flatten { conf.vimgrep_arguments, prompt } end, opts.entry_maker or make_entry.gen_from_vimgrep(opts), - opts.max_results or 1000 + opts.max_results ) pickers.new(opts, { diff --git a/lua/telescope/pickers.lua b/lua/telescope/pickers.lua index cc9eb14..e9c2cab 100644 --- a/lua/telescope/pickers.lua +++ b/lua/telescope/pickers.lua @@ -656,9 +656,12 @@ end -- TODO: We should consider adding `process_bulk` or `bulk_entry_manager` for things -- that we always know the items and can score quickly, so as to avoid drawing so much. -pickers.entry_manager = function(max_results, set_entry) +pickers.entry_manager = function(max_results, set_entry, info) log.debug("Creating entry_manager...") + info = info or {} + info.items_looped = 0 + -- state contains list of -- { -- score = ... @@ -669,11 +672,19 @@ pickers.entry_manager = function(max_results, set_entry) set_entry = set_entry or function() end + local worst_acceptable_score = math.huge + return setmetatable({ add_entry = function(self, score, entry) score = score or 0 + if score >= worst_acceptable_score then + return + end + for index, item in ipairs(entry_state) do + info.items_looped = info.items_looped + 1 + if item.score > score then return self:insert(index, { score = score, @@ -683,7 +694,7 @@ pickers.entry_manager = function(max_results, set_entry) -- Don't add results that are too bad. if index >= max_results then - return self + return end end @@ -701,16 +712,23 @@ pickers.entry_manager = function(max_results, set_entry) -- To insert something, we place at the next available index (or specified index) -- and then shift all the corresponding items one place. - local next_entry + local next_entry, last_score repeat next_entry = entry_state[index] set_entry(index, entry.entry) entry_state[index] = entry + last_score = entry.score + index = index + 1 entry = next_entry - until not next_entry + + until not next_entry or index > max_results + + if index > max_results then + worst_acceptable_score = last_score + end end, num_results = function() diff --git a/lua/tests/automated/find_and_sort_spec.lua b/lua/tests/automated/find_and_sort_spec.lua new file mode 100644 index 0000000..f168b08 --- /dev/null +++ b/lua/tests/automated/find_and_sort_spec.lua @@ -0,0 +1,87 @@ +require('plenary.reload').reload_module('telescope') + +--[[ + +Goals: +1. Easily test a sorter and finder to make sure we get all the results we need. + +--]] + +local finders = require('telescope.finders') +local make_entry = require('telescope.make_entry') +local pickers = require('telescope.pickers') +local sorters = require('telescope.sorters') + +local find_and_sort_test = function(prompt, f, s) + local info = {} + + info.start = vim.loop.hrtime() + + info.filtered = 0 + info.added = 0 + info.scoring_time = 0 + info.set_entry = 0 + + local entry_manager = pickers.entry_manager(25, function() + info.set_entry = info.set_entry + 1 + end, info) + + local completed = false + + local process_result = function(entry) + local score_start = vim.loop.hrtime() + local score = s:score(prompt, entry) + info.scoring_time = info.scoring_time + (vim.loop.hrtime() - score_start) / 1e9 + + -- Filter these out here. + if score == -1 then + info.filtered = info.filtered + 1 + return + end + + info.added = info.added + 1 + entry_manager:add_entry( + s:score(prompt, entry), + entry + ) + end + + local process_complete = function() + info.finish = vim.loop.hrtime() + info.time = (info.finish - info.start) / 1e9 + + info.total = info.filtered + info.added + completed = true + end + + f(prompt, process_result, process_complete) + + -- Wait until we're done to return + vim.wait(5000, function() return completed end, 10) + + return entry_manager, info +end + +local cwd = vim.fn.expand("~/") + +local finder = finders.new_oneshot_job( + {"fdfind"}, + { + cwd = cwd, + entry_maker = make_entry.gen_from_file {cwd = cwd}, + -- disable_devicons = true, + -- maximum_results = 1000, + } +) + +local res, info = find_and_sort_test( + "pickers.lua", + finder, + sorters.get_generic_fuzzy_sorter() +) + +print(vim.inspect(res:get_entry(1))) +print(vim.inspect(info)) + +-- No skip: 2,206,186 +-- Ya skip: 2,133 diff --git a/lua/tests/automated/resolver_spec.lua b/lua/tests/automated/resolver_spec.lua new file mode 100644 index 0000000..9c4822a --- /dev/null +++ b/lua/tests/automated/resolver_spec.lua @@ -0,0 +1,71 @@ +require('plenary.test_harness'):setup_busted() + +local eq = function(a, b) + assert.are.same(a, b) +end + +local resolve = require('telescope.config.resolve') + + +describe('telescope.config.resolve', function() + describe('win_option', function() + it('should resolve for percentages', function() + local height_config = 0.8 + local opt = resolve.win_option(height_config) + + eq(height_config, opt.preview) + eq(height_config, opt.prompt) + eq(height_config, opt.results) + end) + + it('should resolve for percetnages with default', function() + local height_config = 0.8 + local opt = resolve.win_option(nil, height_config) + + eq(height_config, opt.preview) + eq(height_config, opt.prompt) + eq(height_config, opt.results) + end) + + it('should resolve table values', function() + local table_val = {'a'} + local opt = resolve.win_option(nil, table_val) + + eq(table_val, opt.preview) + eq(table_val, opt.prompt) + eq(table_val, opt.results) + end) + + it('should allow overrides for different wins', function() + local prompt_override = {'a', prompt = 'b'} + local opt = resolve.win_option(prompt_override) + eq('a', opt.preview) + eq('a', opt.results) + eq('b', opt.prompt) + end) + + it('should allow overrides for all wins', function() + local all_specified = {preview = 'a', prompt = 'b', results = 'c'} + local opt = resolve.win_option(all_specified) + eq('a', opt.preview) + eq('b', opt.prompt) + eq('c', opt.results) + end) + + it('should allow some specified with a simple default', function() + local some_specified = {prompt = 'b', results = 'c'} + local opt = resolve.win_option(some_specified, 'a') + eq('a', opt.preview) + eq('b', opt.prompt) + eq('c', opt.results) + end) + end) + + describe('resolve_height/width', function() + eq(10, resolve.resolve_height(0.1)(nil, 24, 100)) + eq(2, resolve.resolve_width(0.1)(nil, 24, 100)) + + eq(10, resolve.resolve_width(10)(nil, 24, 100)) + eq(24, resolve.resolve_width(50)(nil, 24, 100)) + end) +end) diff --git a/lua/tests/automated/telescope_spec.lua b/lua/tests/automated/telescope_spec.lua index 8decb50..3589a22 100644 --- a/lua/tests/automated/telescope_spec.lua +++ b/lua/tests/automated/telescope_spec.lua @@ -10,7 +10,7 @@ local pickers = require('telescope.pickers') local utils = require('telescope.utils') --[[ -require("plenary.test_harness"):test_directory("busted", "./tests/") +lua RELOAD('plenary'); require("plenary.test_harness"):test_directory("busted", "./tests/automated") --]] describe('Picker', function() @@ -263,7 +263,7 @@ describe('Sorters', function() assert(better_match < worse_match, "Final match should be stronger") end) - it('sorts multiple finds better', function() + pending('sorts multiple finds better', function() local sorter = require('telescope.sorters').get_fuzzy_file() local multi_match = sorter:score('generics', 'exercises/generics/generics2.rs')