mirror of
				https://github.com/neovim/neovim.git
				synced 2025-10-26 12:27:24 +00:00 
			
		
		
		
	perf(filetype): optimize internal data structures
This changes the type for the sorted pattern table from
`vim.filetype.mapping[]` to `vim.filetype.mapping.sorted[]`
E.g. instead of:
```lua
{
  { ['/debian/changelog$'] = {'debchangelog', { parent = '/debian/' } },
  { ['%.git/']             = { detect.git   , { parent = 'git/', priority = -1 } },
}
```
It is now:
```lua
{
  { '/debian/, '/debian/changelog$', 'debchangelog' },
  { 'git/'   , '%.git/'            , detect.git    , -1 },
}
```
Overall this should roughly cut the amount of tables used by 3, and
replaces lots of hash indexes with array indexes.
			
			
This commit is contained in:
		 Lewis Russell
					Lewis Russell
				
			
				
					committed by
					
						 Lewis Russell
						Lewis Russell
					
				
			
			
				
	
			
			
			 Lewis Russell
						Lewis Russell
					
				
			
						parent
						
							d0e78b5871
						
					
				
				
					commit
					ff575b3886
				
			| @@ -4,15 +4,22 @@ local fn = vim.fn | |||||||
| local M = {} | local M = {} | ||||||
|  |  | ||||||
| --- @alias vim.filetype.mapfn fun(path:string,bufnr:integer, ...):string?, fun(b:integer)? | --- @alias vim.filetype.mapfn fun(path:string,bufnr:integer, ...):string?, fun(b:integer)? | ||||||
| --- @alias vim.filetype.mapopts { parent: string, priority: number } | --- @alias vim.filetype.mapopts { priority: number } | ||||||
| --- @alias vim.filetype.maptbl [string|vim.filetype.mapfn, vim.filetype.mapopts] | --- @alias vim.filetype.maptbl [string|vim.filetype.mapfn, vim.filetype.mapopts] | ||||||
| --- @alias vim.filetype.mapping.value string|vim.filetype.mapfn|vim.filetype.maptbl | --- @alias vim.filetype.mapping.value string|vim.filetype.mapfn|vim.filetype.maptbl | ||||||
| --- @alias vim.filetype.mapping table<string,vim.filetype.mapping.value> | --- @alias vim.filetype.mapping table<string,vim.filetype.mapping.value> | ||||||
|  |  | ||||||
|  | --- @class vim.filetype.mapping.sorted | ||||||
|  | --- @nodoc | ||||||
|  | --- @field [1] string parent pattern | ||||||
|  | --- @field [2] string pattern | ||||||
|  | --- @field [3] string|vim.filetype.mapfn | ||||||
|  | --- @field [4] integer priority | ||||||
|  |  | ||||||
| --- @param ft string|vim.filetype.mapfn | --- @param ft string|vim.filetype.mapfn | ||||||
| --- @param opts? vim.filetype.mapopts | --- @param priority? integer | ||||||
| --- @return vim.filetype.maptbl | --- @return vim.filetype.maptbl | ||||||
| local function starsetf(ft, opts) | local function starsetf(ft, priority) | ||||||
|   return { |   return { | ||||||
|     function(path, bufnr) |     function(path, bufnr) | ||||||
|       -- Note: when `ft` is a function its return value may be nil. |       -- Note: when `ft` is a function its return value may be nil. | ||||||
| @@ -27,11 +34,8 @@ local function starsetf(ft, opts) | |||||||
|       end |       end | ||||||
|     end, |     end, | ||||||
|     { |     { | ||||||
|       -- Allow setting "parent" to be reused in closures, but don't have default as it will be |  | ||||||
|       -- assigned later from grouping |  | ||||||
|       parent = opts and opts.parent, |  | ||||||
|       -- Starset matches should have lowest priority by default |       -- Starset matches should have lowest priority by default | ||||||
|       priority = (opts and opts.priority) or -math.huge, |       priority = priority or -math.huge, | ||||||
|     }, |     }, | ||||||
|   } |   } | ||||||
| end | end | ||||||
| @@ -1874,11 +1878,10 @@ local filename = { | |||||||
| } | } | ||||||
|  |  | ||||||
| -- Re-use closures as much as possible | -- Re-use closures as much as possible | ||||||
| local detect_apache_diretc = starsetf('apache', { parent = '/etc/' }) | local detect_apache = starsetf('apache') | ||||||
| local detect_apache_dotconf = starsetf('apache', { parent = '%.conf' }) | local detect_muttrc = starsetf('muttrc') | ||||||
| local detect_muttrc = starsetf('muttrc', { parent = 'utt' }) | local detect_neomuttrc = starsetf('neomuttrc') | ||||||
| local detect_neomuttrc = starsetf('neomuttrc', { parent = 'utt' }) | local detect_xkb = starsetf('xkb') | ||||||
| local detect_xkb = starsetf('xkb', { parent = '/usr/' }) |  | ||||||
|  |  | ||||||
| ---@type table<string,vim.filetype.mapping> | ---@type table<string,vim.filetype.mapping> | ||||||
| local pattern = { | local pattern = { | ||||||
| @@ -1895,14 +1898,14 @@ local pattern = { | |||||||
|     ['/etc/asound%.conf$'] = 'alsaconf', |     ['/etc/asound%.conf$'] = 'alsaconf', | ||||||
|     ['/etc/apache2/sites%-.*/.*%.com$'] = 'apache', |     ['/etc/apache2/sites%-.*/.*%.com$'] = 'apache', | ||||||
|     ['/etc/httpd/.*%.conf$'] = 'apache', |     ['/etc/httpd/.*%.conf$'] = 'apache', | ||||||
|     ['/etc/apache2/.*%.conf'] = detect_apache_diretc, |     ['/etc/apache2/.*%.conf'] = detect_apache, | ||||||
|     ['/etc/apache2/conf%..*/'] = detect_apache_diretc, |     ['/etc/apache2/conf%..*/'] = detect_apache, | ||||||
|     ['/etc/apache2/mods%-.*/'] = detect_apache_diretc, |     ['/etc/apache2/mods%-.*/'] = detect_apache, | ||||||
|     ['/etc/apache2/sites%-.*/'] = detect_apache_diretc, |     ['/etc/apache2/sites%-.*/'] = detect_apache, | ||||||
|     ['/etc/httpd/conf%..*/'] = detect_apache_diretc, |     ['/etc/httpd/conf%..*/'] = detect_apache, | ||||||
|     ['/etc/httpd/conf%.d/.*%.conf'] = detect_apache_diretc, |     ['/etc/httpd/conf%.d/.*%.conf'] = detect_apache, | ||||||
|     ['/etc/httpd/mods%-.*/'] = detect_apache_diretc, |     ['/etc/httpd/mods%-.*/'] = detect_apache, | ||||||
|     ['/etc/httpd/sites%-.*/'] = detect_apache_diretc, |     ['/etc/httpd/sites%-.*/'] = detect_apache, | ||||||
|     ['/etc/proftpd/.*%.conf'] = starsetf('apachestyle'), |     ['/etc/proftpd/.*%.conf'] = starsetf('apachestyle'), | ||||||
|     ['/etc/proftpd/conf%..*/'] = starsetf('apachestyle'), |     ['/etc/proftpd/conf%..*/'] = starsetf('apachestyle'), | ||||||
|     ['/etc/cdrdao%.conf$'] = 'cdrdaoconf', |     ['/etc/cdrdao%.conf$'] = 'cdrdaoconf', | ||||||
| @@ -2193,13 +2196,13 @@ local pattern = { | |||||||
|   }, |   }, | ||||||
|   ['%.conf'] = { |   ['%.conf'] = { | ||||||
|     ['^proftpd%.conf'] = starsetf('apachestyle'), |     ['^proftpd%.conf'] = starsetf('apachestyle'), | ||||||
|     ['^access%.conf'] = detect_apache_dotconf, |     ['^access%.conf'] = detect_apache, | ||||||
|     ['^apache%.conf'] = detect_apache_dotconf, |     ['^apache%.conf'] = detect_apache, | ||||||
|     ['^apache2%.conf'] = detect_apache_dotconf, |     ['^apache2%.conf'] = detect_apache, | ||||||
|     ['^httpd%.conf'] = detect_apache_dotconf, |     ['^httpd%.conf'] = detect_apache, | ||||||
|     ['^httpd%-.*%.conf'] = detect_apache_dotconf, |     ['^httpd%-.*%.conf'] = detect_apache, | ||||||
|     ['^proxy%-html%.conf'] = detect_apache_dotconf, |     ['^proxy%-html%.conf'] = detect_apache, | ||||||
|     ['^srm%.conf'] = detect_apache_dotconf, |     ['^srm%.conf'] = detect_apache, | ||||||
|     ['asterisk/.*%.conf'] = starsetf('asterisk'), |     ['asterisk/.*%.conf'] = starsetf('asterisk'), | ||||||
|     ['asterisk.*/.*voicemail%.conf'] = starsetf('asteriskvm'), |     ['asterisk.*/.*voicemail%.conf'] = starsetf('asteriskvm'), | ||||||
|     ['^dictd.*%.conf$'] = 'dictdconf', |     ['^dictd.*%.conf$'] = 'dictdconf', | ||||||
| @@ -2372,7 +2375,7 @@ local pattern = { | |||||||
|     ['/app%-defaults/'] = starsetf('xdefaults'), |     ['/app%-defaults/'] = starsetf('xdefaults'), | ||||||
|     ['^Xresources'] = starsetf('xdefaults'), |     ['^Xresources'] = starsetf('xdefaults'), | ||||||
|     -- Increase priority to run before the pattern below |     -- Increase priority to run before the pattern below | ||||||
|     ['^XF86Config%-4'] = starsetf(detect.xfree86_v4, { priority = -math.huge + 1 }), |     ['^XF86Config%-4'] = starsetf(detect.xfree86_v4, -math.huge + 1), | ||||||
|     ['^XF86Config'] = starsetf(detect.xfree86_v3), |     ['^XF86Config'] = starsetf(detect.xfree86_v3), | ||||||
|     ['Xmodmap$'] = 'xmodmap', |     ['Xmodmap$'] = 'xmodmap', | ||||||
|     ['xmodmap'] = starsetf('xmodmap'), |     ['xmodmap'] = starsetf('xmodmap'), | ||||||
| @@ -2398,8 +2401,10 @@ local pattern = { | |||||||
| --- @type table<string,vim.filetype.pattern_cache> | --- @type table<string,vim.filetype.pattern_cache> | ||||||
| local pattern_lookup = {} | local pattern_lookup = {} | ||||||
|  |  | ||||||
|  | --- @param a vim.filetype.mapping.sorted | ||||||
|  | --- @param b vim.filetype.mapping.sorted | ||||||
| local function compare_by_priority(a, b) | local function compare_by_priority(a, b) | ||||||
|   return a[next(a)][2].priority > b[next(b)][2].priority |   return a[4] > b[4] | ||||||
| end | end | ||||||
|  |  | ||||||
| --- @param pat string | --- @param pat string | ||||||
| @@ -2409,30 +2414,30 @@ local function parse_pattern(pat) | |||||||
| end | end | ||||||
|  |  | ||||||
| --- @param t table<string,vim.filetype.mapping> | --- @param t table<string,vim.filetype.mapping> | ||||||
| --- @return vim.filetype.mapping[] | --- @return vim.filetype.mapping.sorted[] | ||||||
| --- @return vim.filetype.mapping[] | --- @return vim.filetype.mapping.sorted[] | ||||||
| local function sort_by_priority(t) | local function sort_by_priority(t) | ||||||
|   -- Separate patterns with non-negative and negative priority because they |   -- Separate patterns with non-negative and negative priority because they | ||||||
|   -- will be processed separately |   -- will be processed separately | ||||||
|   local pos = {} --- @type vim.filetype.mapping[] |   local pos = {} --- @type vim.filetype.mapping.sorted[] | ||||||
|   local neg = {} --- @type vim.filetype.mapping[] |   local neg = {} --- @type vim.filetype.mapping.sorted[] | ||||||
|   for parent, ft_map in pairs(t) do |   for parent, ft_map in pairs(t) do | ||||||
|     pattern_lookup[parent] = pattern_lookup[parent] or parse_pattern(parent) |     pattern_lookup[parent] = pattern_lookup[parent] or parse_pattern(parent) | ||||||
|     for pat, maptbl in pairs(ft_map) do |     for pat, maptbl in pairs(ft_map) do | ||||||
|       local ft = type(maptbl) == 'table' and maptbl[1] or maptbl |       local ft_or_fun = type(maptbl) == 'table' and maptbl[1] or maptbl | ||||||
|       assert( |       assert( | ||||||
|         type(ft) == 'string' or type(ft) == 'function', |         type(ft_or_fun) == 'string' or type(ft_or_fun) == 'function', | ||||||
|         'Expected string or function for filetype' |         'Expected string or function for filetype' | ||||||
|       ) |       ) | ||||||
|  |  | ||||||
|       -- Parse pattern for common data and cache it once |       -- Parse pattern for common data and cache it once | ||||||
|       pattern_lookup[pat] = pattern_lookup[pat] or parse_pattern(pat) |       pattern_lookup[pat] = pattern_lookup[pat] or parse_pattern(pat) | ||||||
|  |  | ||||||
|       local opts = (type(maptbl) == 'table' and type(maptbl[2]) == 'table') and maptbl[2] or {} |       --- @type vim.filetype.mapopts? | ||||||
|       opts.parent = opts.parent or parent |       local opts = (type(maptbl) == 'table' and type(maptbl[2]) == 'table') and maptbl[2] or nil | ||||||
|       opts.priority = opts.priority or 0 |       local priority = opts and opts.priority or 0 | ||||||
|  |  | ||||||
|       table.insert(opts.priority >= 0 and pos or neg, { [pat] = { ft, opts } }) |       table.insert(priority >= 0 and pos or neg, { parent, pat, ft_or_fun, priority }) | ||||||
|     end |     end | ||||||
|   end |   end | ||||||
|  |  | ||||||
| @@ -2643,7 +2648,8 @@ local function match_pattern(name, path, tail, pat, try_all_candidates) | |||||||
|     if some_env_missing then |     if some_env_missing then | ||||||
|       return nil |       return nil | ||||||
|     end |     end | ||||||
|     pat, has_slash = expanded, expanded:find('/') ~= nil |     pat = expanded | ||||||
|  |     has_slash = has_slash or expanded:find('/') ~= nil | ||||||
|   end |   end | ||||||
|  |  | ||||||
|   -- Try all possible candidates to make parent patterns not depend on slash presence |   -- Try all possible candidates to make parent patterns not depend on slash presence | ||||||
| @@ -2665,14 +2671,13 @@ end | |||||||
| --- @param name string | --- @param name string | ||||||
| --- @param path string | --- @param path string | ||||||
| --- @param tail string | --- @param tail string | ||||||
| --- @param pattern_sorted vim.filetype.mapping[] | --- @param pattern_sorted vim.filetype.mapping.sorted[] | ||||||
| --- @param parent_matches table<string,boolean> | --- @param parent_matches table<string,boolean> | ||||||
| --- @param bufnr integer? | --- @param bufnr integer? | ||||||
| local function match_pattern_sorted(name, path, tail, pattern_sorted, parent_matches, bufnr) | local function match_pattern_sorted(name, path, tail, pattern_sorted, parent_matches, bufnr) | ||||||
|   for i = 1, #pattern_sorted do |   for _, p in ipairs(pattern_sorted) do | ||||||
|     local pat, ft_data = next(pattern_sorted[i]) |     local parent, pat, ft_or_fn = p[1], p[2], p[3] | ||||||
|  |  | ||||||
|     local parent = ft_data[2].parent |  | ||||||
|     local parent_is_matched = parent_matches[parent] |     local parent_is_matched = parent_matches[parent] | ||||||
|     if parent_is_matched == nil then |     if parent_is_matched == nil then | ||||||
|       parent_matches[parent] = match_pattern(name, path, tail, parent, true) ~= nil |       parent_matches[parent] = match_pattern(name, path, tail, parent, true) ~= nil | ||||||
| @@ -2682,7 +2687,7 @@ local function match_pattern_sorted(name, path, tail, pattern_sorted, parent_mat | |||||||
|     if parent_is_matched then |     if parent_is_matched then | ||||||
|       local matches = match_pattern(name, path, tail, pat, false) |       local matches = match_pattern(name, path, tail, pat, false) | ||||||
|       if matches then |       if matches then | ||||||
|         local ft, on_detect = dispatch(ft_data[1], path, bufnr, matches) |         local ft, on_detect = dispatch(ft_or_fn, path, bufnr, matches) | ||||||
|         if ft then |         if ft then | ||||||
|           return ft, on_detect |           return ft, on_detect | ||||||
|         end |         end | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user