diagnostic_spec.lua 120 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712
  1. local t = require('test.testutil')
  2. local n = require('test.functional.testnvim')()
  3. local command = n.command
  4. local clear = n.clear
  5. local exec_lua = n.exec_lua
  6. local eq = t.eq
  7. local neq = t.neq
  8. local matches = t.matches
  9. local api = n.api
  10. local pcall_err = t.pcall_err
  11. local fn = n.fn
  12. describe('vim.diagnostic', function()
  13. before_each(function()
  14. clear()
  15. exec_lua(function()
  16. require('vim.diagnostic')
  17. local function make_diagnostic(msg, lnum, col, end_lnum, end_col, severity, source, code)
  18. return {
  19. lnum = lnum,
  20. col = col,
  21. end_lnum = end_lnum,
  22. end_col = end_col,
  23. message = msg,
  24. severity = severity,
  25. source = source,
  26. code = code,
  27. }
  28. end
  29. function _G.make_error(msg, lnum, col, end_lnum, end_col, source, code)
  30. return make_diagnostic(
  31. msg,
  32. lnum,
  33. col,
  34. end_lnum,
  35. end_col,
  36. vim.diagnostic.severity.ERROR,
  37. source,
  38. code
  39. )
  40. end
  41. function _G.make_warning(msg, lnum, col, end_lnum, end_col, source, code)
  42. return make_diagnostic(
  43. msg,
  44. lnum,
  45. col,
  46. end_lnum,
  47. end_col,
  48. vim.diagnostic.severity.WARN,
  49. source,
  50. code
  51. )
  52. end
  53. function _G.make_info(msg, lnum, col, end_lnum, end_col, source, code)
  54. return make_diagnostic(
  55. msg,
  56. lnum,
  57. col,
  58. end_lnum,
  59. end_col,
  60. vim.diagnostic.severity.INFO,
  61. source,
  62. code
  63. )
  64. end
  65. function _G.make_hint(msg, lnum, col, end_lnum, end_col, source, code)
  66. return make_diagnostic(
  67. msg,
  68. lnum,
  69. col,
  70. end_lnum,
  71. end_col,
  72. vim.diagnostic.severity.HINT,
  73. source,
  74. code
  75. )
  76. end
  77. function _G.count_diagnostics(bufnr, severity, namespace)
  78. return #vim.diagnostic.get(bufnr, { severity = severity, namespace = namespace })
  79. end
  80. function _G.count_extmarks(bufnr, namespace)
  81. local ns = vim.diagnostic.get_namespace(namespace)
  82. local extmarks = 0
  83. if ns.user_data.virt_text_ns then
  84. extmarks = extmarks
  85. + #vim.api.nvim_buf_get_extmarks(bufnr, ns.user_data.virt_text_ns, 0, -1, {})
  86. end
  87. if ns.user_data.underline_ns then
  88. extmarks = extmarks
  89. + #vim.api.nvim_buf_get_extmarks(bufnr, ns.user_data.underline_ns, 0, -1, {})
  90. end
  91. return extmarks
  92. end
  93. function _G.get_virt_text_extmarks(ns)
  94. ns = vim.diagnostic.get_namespace(ns)
  95. local virt_text_ns = ns.user_data.virt_text_ns
  96. return vim.api.nvim_buf_get_extmarks(
  97. _G.diagnostic_bufnr,
  98. virt_text_ns,
  99. 0,
  100. -1,
  101. { details = true }
  102. )
  103. end
  104. function _G.get_virt_lines_extmarks(ns)
  105. ns = vim.diagnostic.get_namespace(ns)
  106. local virt_lines_ns = ns.user_data.virt_lines_ns
  107. return vim.api.nvim_buf_get_extmarks(
  108. _G.diagnostic_bufnr,
  109. virt_lines_ns,
  110. 0,
  111. -1,
  112. { details = true }
  113. )
  114. end
  115. ---@param ns integer
  116. function _G.get_underline_extmarks(ns)
  117. ---@type integer
  118. local underline_ns = vim.diagnostic.get_namespace(ns).user_data.underline_ns
  119. return vim.api.nvim_buf_get_extmarks(
  120. _G.diagnostic_bufnr,
  121. underline_ns,
  122. 0,
  123. -1,
  124. { details = true }
  125. )
  126. end
  127. end)
  128. exec_lua(function()
  129. _G.diagnostic_ns = vim.api.nvim_create_namespace('diagnostic_spec')
  130. _G.other_ns = vim.api.nvim_create_namespace('other_namespace')
  131. _G.diagnostic_bufnr = vim.api.nvim_create_buf(true, false)
  132. local lines = { '1st line of text', '2nd line of text', 'wow', 'cool', 'more', 'lines' }
  133. vim.fn.bufload(_G.diagnostic_bufnr)
  134. vim.api.nvim_buf_set_lines(_G.diagnostic_bufnr, 0, 1, false, lines)
  135. end)
  136. end)
  137. it('creates highlight groups', function()
  138. command('runtime plugin/diagnostic.vim')
  139. eq({
  140. 'DiagnosticDeprecated',
  141. 'DiagnosticError',
  142. 'DiagnosticFloatingError',
  143. 'DiagnosticFloatingHint',
  144. 'DiagnosticFloatingInfo',
  145. 'DiagnosticFloatingOk',
  146. 'DiagnosticFloatingWarn',
  147. 'DiagnosticHint',
  148. 'DiagnosticInfo',
  149. 'DiagnosticOk',
  150. 'DiagnosticSignError',
  151. 'DiagnosticSignHint',
  152. 'DiagnosticSignInfo',
  153. 'DiagnosticSignOk',
  154. 'DiagnosticSignWarn',
  155. 'DiagnosticUnderlineError',
  156. 'DiagnosticUnderlineHint',
  157. 'DiagnosticUnderlineInfo',
  158. 'DiagnosticUnderlineOk',
  159. 'DiagnosticUnderlineWarn',
  160. 'DiagnosticUnnecessary',
  161. 'DiagnosticVirtualLinesError',
  162. 'DiagnosticVirtualLinesHint',
  163. 'DiagnosticVirtualLinesInfo',
  164. 'DiagnosticVirtualLinesOk',
  165. 'DiagnosticVirtualLinesWarn',
  166. 'DiagnosticVirtualTextError',
  167. 'DiagnosticVirtualTextHint',
  168. 'DiagnosticVirtualTextInfo',
  169. 'DiagnosticVirtualTextOk',
  170. 'DiagnosticVirtualTextWarn',
  171. 'DiagnosticWarn',
  172. }, fn.getcompletion('Diagnostic', 'highlight'))
  173. end)
  174. it('retrieves diagnostics from all buffers and namespaces', function()
  175. local result = exec_lua(function()
  176. local other_bufnr = vim.api.nvim_create_buf(true, false)
  177. local lines = vim.api.nvim_buf_get_lines(_G.diagnostic_bufnr, 0, -1, true)
  178. vim.api.nvim_buf_set_lines(other_bufnr, 0, 1, false, lines)
  179. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  180. _G.make_error('Diagnostic #1', 1, 1, 1, 1),
  181. _G.make_error('Diagnostic #2', 2, 1, 2, 1),
  182. })
  183. vim.diagnostic.set(_G.other_ns, other_bufnr, {
  184. _G.make_error('Diagnostic #3', 3, 1, 3, 1),
  185. })
  186. return vim.diagnostic.get()
  187. end)
  188. eq(3, #result)
  189. eq(
  190. 2,
  191. exec_lua(function()
  192. return #vim.tbl_filter(function(d)
  193. return d.bufnr == _G.diagnostic_bufnr
  194. end, result)
  195. end)
  196. )
  197. eq('Diagnostic #1', result[1].message)
  198. end)
  199. it('removes diagnostics from the cache when a buffer is removed', function()
  200. eq(
  201. 2,
  202. exec_lua(function()
  203. vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)
  204. local other_bufnr = vim.fn.bufadd('test | test')
  205. local lines = vim.api.nvim_buf_get_lines(_G.diagnostic_bufnr, 0, -1, true)
  206. vim.api.nvim_buf_set_lines(other_bufnr, 0, 1, false, lines)
  207. vim.cmd('bunload! ' .. other_bufnr)
  208. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  209. _G.make_error('Diagnostic #1', 1, 1, 1, 1),
  210. _G.make_error('Diagnostic #2', 2, 1, 2, 1),
  211. })
  212. vim.diagnostic.set(_G.diagnostic_ns, other_bufnr, {
  213. _G.make_error('Diagnostic #3', 3, 1, 3, 1),
  214. })
  215. vim.api.nvim_set_current_buf(other_bufnr)
  216. vim.opt_local.buflisted = true
  217. vim.cmd('bwipeout!')
  218. return #vim.diagnostic.get()
  219. end)
  220. )
  221. eq(
  222. 2,
  223. exec_lua(function()
  224. vim.api.nvim_set_current_buf(_G.diagnostic_bufnr)
  225. vim.opt_local.buflisted = false
  226. return #vim.diagnostic.get()
  227. end)
  228. )
  229. eq(
  230. 0,
  231. exec_lua(function()
  232. vim.cmd('bwipeout!')
  233. return #vim.diagnostic.get()
  234. end)
  235. )
  236. end)
  237. it('removes diagnostic from stale cache on reset', function()
  238. local diagnostics = exec_lua(function()
  239. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  240. _G.make_error('Diagnostic #1', 1, 1, 1, 1),
  241. _G.make_error('Diagnostic #2', 2, 1, 2, 1),
  242. })
  243. vim.fn.bufadd('test | test')
  244. vim.cmd('noautocmd bwipeout! ' .. _G.diagnostic_bufnr)
  245. return vim.diagnostic.get(_G.diagnostic_bufnr)
  246. end)
  247. eq(2, #diagnostics)
  248. diagnostics = exec_lua(function()
  249. vim.diagnostic.reset()
  250. return vim.diagnostic.get()
  251. end)
  252. eq(0, #diagnostics)
  253. end)
  254. it('always returns a copy of diagnostic tables', function()
  255. local result = exec_lua(function()
  256. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  257. _G.make_error('Diagnostic #1', 1, 1, 1, 1),
  258. })
  259. local diag = vim.diagnostic.get()
  260. diag[1].col = 10000
  261. return vim.diagnostic.get()[1].col == 10000
  262. end)
  263. eq(false, result)
  264. end)
  265. it('resolves buffer number 0 to the current buffer', function()
  266. eq(
  267. 2,
  268. exec_lua(function()
  269. vim.api.nvim_set_current_buf(_G.diagnostic_bufnr)
  270. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  271. _G.make_error('Diagnostic #1', 1, 1, 1, 1),
  272. _G.make_error('Diagnostic #2', 2, 1, 2, 1),
  273. })
  274. return #vim.diagnostic.get(0)
  275. end)
  276. )
  277. end)
  278. it('saves and count a single error', function()
  279. eq(
  280. 1,
  281. exec_lua(function()
  282. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  283. _G.make_error('Diagnostic #1', 1, 1, 1, 1),
  284. })
  285. return _G.count_diagnostics(
  286. _G.diagnostic_bufnr,
  287. vim.diagnostic.severity.ERROR,
  288. _G.diagnostic_ns
  289. )
  290. end)
  291. )
  292. end)
  293. it('saves and count multiple errors', function()
  294. eq(
  295. 2,
  296. exec_lua(function()
  297. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  298. _G.make_error('Diagnostic #1', 1, 1, 1, 1),
  299. _G.make_error('Diagnostic #2', 2, 1, 2, 1),
  300. })
  301. return _G.count_diagnostics(
  302. _G.diagnostic_bufnr,
  303. vim.diagnostic.severity.ERROR,
  304. _G.diagnostic_ns
  305. )
  306. end)
  307. )
  308. end)
  309. it('saves and count from multiple namespaces', function()
  310. eq(
  311. { 1, 1, 2 },
  312. exec_lua(function()
  313. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  314. _G.make_error('Diagnostic From Server 1', 1, 1, 1, 1),
  315. })
  316. vim.diagnostic.set(_G.other_ns, _G.diagnostic_bufnr, {
  317. _G.make_error('Diagnostic From Server 2', 1, 1, 1, 1),
  318. })
  319. return {
  320. -- First namespace
  321. _G.count_diagnostics(
  322. _G.diagnostic_bufnr,
  323. vim.diagnostic.severity.ERROR,
  324. _G.diagnostic_ns
  325. ),
  326. -- Second namespace
  327. _G.count_diagnostics(_G.diagnostic_bufnr, vim.diagnostic.severity.ERROR, _G.other_ns),
  328. -- All namespaces
  329. _G.count_diagnostics(_G.diagnostic_bufnr, vim.diagnostic.severity.ERROR),
  330. }
  331. end)
  332. )
  333. end)
  334. it('saves and count from multiple namespaces with respect to severity', function()
  335. eq(
  336. { 3, 0, 3 },
  337. exec_lua(function()
  338. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  339. _G.make_error('Diagnostic From Server 1:1', 1, 1, 1, 1),
  340. _G.make_error('Diagnostic From Server 1:2', 2, 2, 2, 2),
  341. _G.make_error('Diagnostic From Server 1:3', 2, 3, 3, 2),
  342. })
  343. vim.diagnostic.set(_G.other_ns, _G.diagnostic_bufnr, {
  344. _G.make_warning('Warning From Server 2', 3, 3, 3, 3),
  345. })
  346. return {
  347. -- Namespace 1
  348. _G.count_diagnostics(
  349. _G.diagnostic_bufnr,
  350. vim.diagnostic.severity.ERROR,
  351. _G.diagnostic_ns
  352. ),
  353. -- Namespace 2
  354. _G.count_diagnostics(_G.diagnostic_bufnr, vim.diagnostic.severity.ERROR, _G.other_ns),
  355. -- All namespaces
  356. _G.count_diagnostics(_G.diagnostic_bufnr, vim.diagnostic.severity.ERROR),
  357. }
  358. end)
  359. )
  360. end)
  361. it('handles one namespace clearing highlights while the other still has highlights', function()
  362. exec_lua(function()
  363. vim.diagnostic.config({ virtual_text = true })
  364. end)
  365. -- 1 Error (1)
  366. -- 1 Warning (2)
  367. -- 1 Warning (2) + 1 Warning (1)
  368. -- 2 highlights and 2 underlines (since error)
  369. -- 1 highlight + 1 underline
  370. local all_highlights = { 1, 1, 2, 4, 2 }
  371. eq(
  372. all_highlights,
  373. exec_lua(function()
  374. local ns_1_diags = {
  375. _G.make_error('Error 1', 1, 1, 1, 5),
  376. _G.make_warning('Warning on Server 1', 2, 1, 2, 3),
  377. }
  378. local ns_2_diags = {
  379. _G.make_warning('Warning 1', 2, 1, 2, 3),
  380. }
  381. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, ns_1_diags)
  382. vim.diagnostic.set(_G.other_ns, _G.diagnostic_bufnr, ns_2_diags)
  383. return {
  384. _G.count_diagnostics(
  385. _G.diagnostic_bufnr,
  386. vim.diagnostic.severity.ERROR,
  387. _G.diagnostic_ns
  388. ),
  389. _G.count_diagnostics(_G.diagnostic_bufnr, vim.diagnostic.severity.WARN, _G.other_ns),
  390. _G.count_diagnostics(_G.diagnostic_bufnr, vim.diagnostic.severity.WARN),
  391. _G.count_extmarks(_G.diagnostic_bufnr, _G.diagnostic_ns),
  392. _G.count_extmarks(_G.diagnostic_bufnr, _G.other_ns),
  393. }
  394. end)
  395. )
  396. -- Clear diagnostics from namespace 1, and make sure we have the right amount of stuff for namespace 2
  397. eq(
  398. { 1, 1, 2, 0, 2 },
  399. exec_lua(function()
  400. vim.diagnostic.enable(false, { bufnr = _G.diagnostic_bufnr, ns_id = _G.diagnostic_ns })
  401. return {
  402. _G.count_diagnostics(
  403. _G.diagnostic_bufnr,
  404. vim.diagnostic.severity.ERROR,
  405. _G.diagnostic_ns
  406. ),
  407. _G.count_diagnostics(_G.diagnostic_bufnr, vim.diagnostic.severity.WARN, _G.other_ns),
  408. _G.count_diagnostics(_G.diagnostic_bufnr, vim.diagnostic.severity.WARN),
  409. _G.count_extmarks(_G.diagnostic_bufnr, _G.diagnostic_ns),
  410. _G.count_extmarks(_G.diagnostic_bufnr, _G.other_ns),
  411. }
  412. end)
  413. )
  414. -- Show diagnostics from namespace 1 again
  415. eq(
  416. all_highlights,
  417. exec_lua(function()
  418. vim.diagnostic.enable(true, { bufnr = _G.diagnostic_bufnr, ns_id = _G.diagnostic_ns })
  419. return {
  420. _G.count_diagnostics(
  421. _G.diagnostic_bufnr,
  422. vim.diagnostic.severity.ERROR,
  423. _G.diagnostic_ns
  424. ),
  425. _G.count_diagnostics(_G.diagnostic_bufnr, vim.diagnostic.severity.WARN, _G.other_ns),
  426. _G.count_diagnostics(_G.diagnostic_bufnr, vim.diagnostic.severity.WARN),
  427. _G.count_extmarks(_G.diagnostic_bufnr, _G.diagnostic_ns),
  428. _G.count_extmarks(_G.diagnostic_bufnr, _G.other_ns),
  429. }
  430. end)
  431. )
  432. end)
  433. it('does not display diagnostics when disabled', function()
  434. exec_lua(function()
  435. vim.diagnostic.config({ virtual_text = true })
  436. end)
  437. eq(
  438. { 0, 2 },
  439. exec_lua(function()
  440. local ns_1_diags = {
  441. _G.make_error('Error 1', 1, 1, 1, 5),
  442. _G.make_warning('Warning on Server 1', 2, 1, 2, 3),
  443. }
  444. local ns_2_diags = {
  445. _G.make_warning('Warning 1', 2, 1, 2, 3),
  446. }
  447. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, ns_1_diags)
  448. vim.diagnostic.set(_G.other_ns, _G.diagnostic_bufnr, ns_2_diags)
  449. vim.diagnostic.enable(false, { bufnr = _G.diagnostic_bufnr, ns_id = _G.diagnostic_ns })
  450. return {
  451. _G.count_extmarks(_G.diagnostic_bufnr, _G.diagnostic_ns),
  452. _G.count_extmarks(_G.diagnostic_bufnr, _G.other_ns),
  453. }
  454. end)
  455. )
  456. eq(
  457. { 4, 0 },
  458. exec_lua(function()
  459. vim.diagnostic.enable(true, { bufnr = _G.diagnostic_bufnr, ns_id = _G.diagnostic_ns })
  460. vim.diagnostic.enable(false, { bufnr = _G.diagnostic_bufnr, ns_id = _G.other_ns })
  461. return {
  462. _G.count_extmarks(_G.diagnostic_bufnr, _G.diagnostic_ns),
  463. _G.count_extmarks(_G.diagnostic_bufnr, _G.other_ns),
  464. }
  465. end)
  466. )
  467. end)
  468. describe('show() and hide()', function()
  469. it('works', function()
  470. local result = exec_lua(function()
  471. local other_bufnr = vim.api.nvim_create_buf(true, false)
  472. vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)
  473. local result = {}
  474. vim.diagnostic.config({ underline = false, virtual_text = true })
  475. local ns_1_diags = {
  476. _G.make_error('Error 1', 1, 1, 1, 5),
  477. _G.make_warning('Warning on Server 1', 2, 1, 2, 5),
  478. }
  479. local ns_2_diags = {
  480. _G.make_warning('Warning 1', 2, 1, 2, 5),
  481. }
  482. local other_buffer_diags = {
  483. _G.make_info('This is interesting', 0, 0, 0, 0),
  484. }
  485. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, ns_1_diags)
  486. vim.diagnostic.set(_G.other_ns, _G.diagnostic_bufnr, ns_2_diags)
  487. vim.diagnostic.set(_G.diagnostic_ns, other_bufnr, other_buffer_diags)
  488. -- All buffers and namespaces
  489. table.insert(
  490. result,
  491. _G.count_extmarks(_G.diagnostic_bufnr, _G.diagnostic_ns)
  492. + _G.count_extmarks(_G.diagnostic_bufnr, _G.other_ns)
  493. + _G.count_extmarks(other_bufnr, _G.diagnostic_ns)
  494. )
  495. -- Hide one namespace
  496. vim.diagnostic.hide(_G.diagnostic_ns)
  497. table.insert(
  498. result,
  499. _G.count_extmarks(_G.diagnostic_bufnr, _G.diagnostic_ns)
  500. + _G.count_extmarks(_G.diagnostic_bufnr, _G.other_ns)
  501. + _G.count_extmarks(other_bufnr, _G.diagnostic_ns)
  502. )
  503. -- Show one namespace
  504. vim.diagnostic.show(_G.diagnostic_ns)
  505. table.insert(
  506. result,
  507. _G.count_extmarks(_G.diagnostic_bufnr, _G.diagnostic_ns)
  508. + _G.count_extmarks(_G.diagnostic_bufnr, _G.other_ns)
  509. + _G.count_extmarks(other_bufnr, _G.diagnostic_ns)
  510. )
  511. -- Hide one buffer
  512. vim.diagnostic.hide(nil, other_bufnr)
  513. table.insert(
  514. result,
  515. _G.count_extmarks(_G.diagnostic_bufnr, _G.diagnostic_ns)
  516. + _G.count_extmarks(_G.diagnostic_bufnr, _G.other_ns)
  517. + _G.count_extmarks(other_bufnr, _G.diagnostic_ns)
  518. )
  519. -- Hide everything
  520. vim.diagnostic.hide()
  521. table.insert(
  522. result,
  523. _G.count_extmarks(_G.diagnostic_bufnr, _G.diagnostic_ns)
  524. + _G.count_extmarks(_G.diagnostic_bufnr, _G.other_ns)
  525. + _G.count_extmarks(other_bufnr, _G.diagnostic_ns)
  526. )
  527. -- Show one buffer
  528. vim.diagnostic.show(nil, _G.diagnostic_bufnr)
  529. table.insert(
  530. result,
  531. _G.count_extmarks(_G.diagnostic_bufnr, _G.diagnostic_ns)
  532. + _G.count_extmarks(_G.diagnostic_bufnr, _G.other_ns)
  533. + _G.count_extmarks(other_bufnr, _G.diagnostic_ns)
  534. )
  535. return result
  536. end)
  537. eq(4, result[1])
  538. eq(1, result[2])
  539. eq(4, result[3])
  540. eq(3, result[4])
  541. eq(0, result[5])
  542. eq(3, result[6])
  543. end)
  544. it("doesn't error after bwipeout on buffer", function()
  545. exec_lua(function()
  546. vim.diagnostic.set(
  547. _G.diagnostic_ns,
  548. _G.diagnostic_bufnr,
  549. { { message = '', lnum = 0, end_lnum = 0, col = 0, end_col = 0 } }
  550. )
  551. vim.cmd('bwipeout! ' .. _G.diagnostic_bufnr)
  552. vim.diagnostic.show(_G.diagnostic_ns)
  553. vim.diagnostic.hide(_G.diagnostic_ns)
  554. end)
  555. end)
  556. end)
  557. describe('enable() and disable()', function()
  558. it('validation', function()
  559. matches('expected boolean, got table', pcall_err(exec_lua, [[vim.diagnostic.enable({})]]))
  560. matches(
  561. 'filter: expected table, got string',
  562. pcall_err(exec_lua, [[vim.diagnostic.enable(false, '')]])
  563. )
  564. matches(
  565. 'Invalid buffer id: 42',
  566. pcall_err(exec_lua, [[vim.diagnostic.enable(true, { bufnr = 42 })]])
  567. )
  568. matches(
  569. 'expected boolean, got number',
  570. pcall_err(exec_lua, [[vim.diagnostic.enable(42, {})]])
  571. )
  572. matches('expected boolean, got table', pcall_err(exec_lua, [[vim.diagnostic.enable({}, 42)]]))
  573. -- Deprecated signature.
  574. matches('Invalid buffer id: 42', pcall_err(exec_lua, [[vim.diagnostic.enable(42)]]))
  575. -- Deprecated signature.
  576. matches(
  577. 'namespace does not exist or is anonymous',
  578. pcall_err(exec_lua, [[vim.diagnostic.enable(nil, 42)]])
  579. )
  580. end)
  581. it('without arguments', function()
  582. local result = exec_lua(function()
  583. vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)
  584. local result = {}
  585. vim.diagnostic.config({ underline = false, virtual_text = true })
  586. local ns_1_diags = {
  587. _G.make_error('Error 1', 1, 1, 1, 5),
  588. _G.make_warning('Warning on Server 1', 2, 1, 2, 5),
  589. }
  590. local ns_2_diags = {
  591. _G.make_warning('Warning 1', 2, 1, 2, 5),
  592. }
  593. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, ns_1_diags)
  594. vim.diagnostic.set(_G.other_ns, _G.diagnostic_bufnr, ns_2_diags)
  595. table.insert(
  596. result,
  597. _G.count_extmarks(_G.diagnostic_bufnr, _G.diagnostic_ns)
  598. + _G.count_extmarks(_G.diagnostic_bufnr, _G.other_ns)
  599. )
  600. vim.diagnostic.enable(false)
  601. table.insert(
  602. result,
  603. _G.count_extmarks(_G.diagnostic_bufnr, _G.diagnostic_ns)
  604. + _G.count_extmarks(_G.diagnostic_bufnr, _G.other_ns)
  605. )
  606. -- Create a new buffer
  607. local other_bufnr = vim.api.nvim_create_buf(true, false)
  608. local other_buffer_diags = {
  609. _G.make_info('This is interesting', 0, 0, 0, 0),
  610. }
  611. vim.diagnostic.set(_G.diagnostic_ns, other_bufnr, other_buffer_diags)
  612. table.insert(
  613. result,
  614. _G.count_extmarks(_G.diagnostic_bufnr, _G.diagnostic_ns)
  615. + _G.count_extmarks(_G.diagnostic_bufnr, _G.other_ns)
  616. + _G.count_extmarks(other_bufnr, _G.diagnostic_ns)
  617. )
  618. vim.diagnostic.enable()
  619. table.insert(
  620. result,
  621. _G.count_extmarks(_G.diagnostic_bufnr, _G.diagnostic_ns)
  622. + _G.count_extmarks(_G.diagnostic_bufnr, _G.other_ns)
  623. + _G.count_extmarks(other_bufnr, _G.diagnostic_ns)
  624. )
  625. return result
  626. end)
  627. eq(3, result[1])
  628. eq(0, result[2])
  629. eq(0, result[3])
  630. eq(4, result[4])
  631. end)
  632. it('with buffer argument', function()
  633. local result = exec_lua(function()
  634. local other_bufnr = vim.api.nvim_create_buf(true, false)
  635. vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)
  636. local result = {}
  637. vim.diagnostic.config({ underline = false, virtual_text = true })
  638. local ns_1_diags = {
  639. _G.make_error('Error 1', 1, 1, 1, 5),
  640. _G.make_warning('Warning on Server 1', 2, 1, 2, 5),
  641. }
  642. local ns_2_diags = {
  643. _G.make_warning('Warning 1', 2, 1, 2, 5),
  644. }
  645. local other_buffer_diags = {
  646. _G.make_info('This is interesting', 0, 0, 0, 0),
  647. }
  648. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, ns_1_diags)
  649. vim.diagnostic.set(_G.other_ns, _G.diagnostic_bufnr, ns_2_diags)
  650. vim.diagnostic.set(_G.diagnostic_ns, other_bufnr, other_buffer_diags)
  651. table.insert(
  652. result,
  653. _G.count_extmarks(_G.diagnostic_bufnr, _G.diagnostic_ns)
  654. + _G.count_extmarks(_G.diagnostic_bufnr, _G.other_ns)
  655. + _G.count_extmarks(other_bufnr, _G.diagnostic_ns)
  656. )
  657. vim.diagnostic.enable(false, { bufnr = _G.diagnostic_bufnr })
  658. table.insert(
  659. result,
  660. _G.count_extmarks(_G.diagnostic_bufnr, _G.diagnostic_ns)
  661. + _G.count_extmarks(_G.diagnostic_bufnr, _G.other_ns)
  662. + _G.count_extmarks(other_bufnr, _G.diagnostic_ns)
  663. )
  664. vim.diagnostic.enable(true, { bufnr = _G.diagnostic_bufnr })
  665. table.insert(
  666. result,
  667. _G.count_extmarks(_G.diagnostic_bufnr, _G.diagnostic_ns)
  668. + _G.count_extmarks(_G.diagnostic_bufnr, _G.other_ns)
  669. + _G.count_extmarks(other_bufnr, _G.diagnostic_ns)
  670. )
  671. vim.diagnostic.enable(false, { bufnr = other_bufnr })
  672. table.insert(
  673. result,
  674. _G.count_extmarks(_G.diagnostic_bufnr, _G.diagnostic_ns)
  675. + _G.count_extmarks(_G.diagnostic_bufnr, _G.other_ns)
  676. + _G.count_extmarks(other_bufnr, _G.diagnostic_ns)
  677. )
  678. return result
  679. end)
  680. eq(4, result[1])
  681. eq(1, result[2])
  682. eq(4, result[3])
  683. eq(3, result[4])
  684. end)
  685. it('with a namespace argument', function()
  686. local result = exec_lua(function()
  687. vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)
  688. local result = {}
  689. vim.diagnostic.config({ underline = false, virtual_text = true })
  690. local ns_1_diags = {
  691. _G.make_error('Error 1', 1, 1, 1, 5),
  692. _G.make_warning('Warning on Server 1', 2, 1, 2, 5),
  693. }
  694. local ns_2_diags = {
  695. _G.make_warning('Warning 1', 2, 1, 2, 5),
  696. }
  697. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, ns_1_diags)
  698. vim.diagnostic.set(_G.other_ns, _G.diagnostic_bufnr, ns_2_diags)
  699. table.insert(
  700. result,
  701. _G.count_extmarks(_G.diagnostic_bufnr, _G.diagnostic_ns)
  702. + _G.count_extmarks(_G.diagnostic_bufnr, _G.other_ns)
  703. )
  704. vim.diagnostic.enable(false, { ns_id = _G.diagnostic_ns })
  705. table.insert(
  706. result,
  707. _G.count_extmarks(_G.diagnostic_bufnr, _G.diagnostic_ns)
  708. + _G.count_extmarks(_G.diagnostic_bufnr, _G.other_ns)
  709. )
  710. vim.diagnostic.enable(true, { ns_id = _G.diagnostic_ns })
  711. table.insert(
  712. result,
  713. _G.count_extmarks(_G.diagnostic_bufnr, _G.diagnostic_ns)
  714. + _G.count_extmarks(_G.diagnostic_bufnr, _G.other_ns)
  715. )
  716. vim.diagnostic.enable(false, { ns_id = _G.other_ns })
  717. table.insert(
  718. result,
  719. _G.count_extmarks(_G.diagnostic_bufnr, _G.diagnostic_ns)
  720. + _G.count_extmarks(_G.diagnostic_bufnr, _G.other_ns)
  721. )
  722. return result
  723. end)
  724. eq(3, result[1])
  725. eq(1, result[2])
  726. eq(3, result[3])
  727. eq(2, result[4])
  728. end)
  729. --- @return table
  730. local function test_enable(legacy)
  731. return exec_lua(function()
  732. local other_bufnr = vim.api.nvim_create_buf(true, false)
  733. vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)
  734. local result = {}
  735. vim.diagnostic.config({ underline = false, virtual_text = true })
  736. local ns_1_diags = {
  737. _G.make_error('Error 1', 1, 1, 1, 5),
  738. _G.make_warning('Warning on Server 1', 2, 1, 2, 5),
  739. }
  740. local ns_2_diags = {
  741. _G.make_warning('Warning 1', 2, 1, 2, 5),
  742. }
  743. local other_buffer_diags = {
  744. _G.make_info('This is interesting', 0, 0, 0, 0),
  745. }
  746. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, ns_1_diags)
  747. vim.diagnostic.set(_G.other_ns, _G.diagnostic_bufnr, ns_2_diags)
  748. vim.diagnostic.set(_G.diagnostic_ns, other_bufnr, other_buffer_diags)
  749. table.insert(
  750. result,
  751. _G.count_extmarks(_G.diagnostic_bufnr, _G.diagnostic_ns)
  752. + _G.count_extmarks(_G.diagnostic_bufnr, _G.other_ns)
  753. + _G.count_extmarks(other_bufnr, _G.diagnostic_ns)
  754. )
  755. if legacy then
  756. vim.diagnostic.disable(_G.diagnostic_bufnr, _G.diagnostic_ns)
  757. else
  758. vim.diagnostic.enable(false, { bufnr = _G.diagnostic_bufnr, ns_id = _G.diagnostic_ns })
  759. end
  760. table.insert(
  761. result,
  762. _G.count_extmarks(_G.diagnostic_bufnr, _G.diagnostic_ns)
  763. + _G.count_extmarks(_G.diagnostic_bufnr, _G.other_ns)
  764. + _G.count_extmarks(other_bufnr, _G.diagnostic_ns)
  765. )
  766. if legacy then
  767. vim.diagnostic.disable(_G.diagnostic_bufnr, _G.other_ns)
  768. else
  769. vim.diagnostic.enable(false, { bufnr = _G.diagnostic_bufnr, ns_id = _G.other_ns })
  770. end
  771. table.insert(
  772. result,
  773. _G.count_extmarks(_G.diagnostic_bufnr, _G.diagnostic_ns)
  774. + _G.count_extmarks(_G.diagnostic_bufnr, _G.other_ns)
  775. + _G.count_extmarks(other_bufnr, _G.diagnostic_ns)
  776. )
  777. if legacy then
  778. vim.diagnostic.enable(_G.diagnostic_bufnr, _G.diagnostic_ns)
  779. else
  780. vim.diagnostic.enable(true, { bufnr = _G.diagnostic_bufnr, ns_id = _G.diagnostic_ns })
  781. end
  782. table.insert(
  783. result,
  784. _G.count_extmarks(_G.diagnostic_bufnr, _G.diagnostic_ns)
  785. + _G.count_extmarks(_G.diagnostic_bufnr, _G.other_ns)
  786. + _G.count_extmarks(other_bufnr, _G.diagnostic_ns)
  787. )
  788. if legacy then
  789. -- Should have no effect
  790. vim.diagnostic.disable(other_bufnr, _G.other_ns)
  791. else
  792. -- Should have no effect
  793. vim.diagnostic.enable(false, { bufnr = other_bufnr, ns_id = _G.other_ns })
  794. end
  795. table.insert(
  796. result,
  797. _G.count_extmarks(_G.diagnostic_bufnr, _G.diagnostic_ns)
  798. + _G.count_extmarks(_G.diagnostic_bufnr, _G.other_ns)
  799. + _G.count_extmarks(other_bufnr, _G.diagnostic_ns)
  800. )
  801. return result
  802. end)
  803. end
  804. it('with both buffer and namespace arguments', function()
  805. local result = test_enable(false)
  806. eq(4, result[1])
  807. eq(2, result[2])
  808. eq(1, result[3])
  809. eq(3, result[4])
  810. eq(3, result[5])
  811. end)
  812. it('with both buffer and namespace arguments (deprecated signature)', function()
  813. -- Exercise the legacy/deprecated signature.
  814. local result = test_enable(true)
  815. eq(4, result[1])
  816. eq(2, result[2])
  817. eq(1, result[3])
  818. eq(3, result[4])
  819. eq(3, result[5])
  820. end)
  821. end)
  822. describe('reset()', function()
  823. it('diagnostic count is 0 and displayed diagnostics are 0 after call', function()
  824. exec_lua(function()
  825. vim.diagnostic.config({ virtual_text = true })
  826. end)
  827. -- 1 Error (1)
  828. -- 1 Warning (2)
  829. -- 1 Warning (2) + 1 Warning (1)
  830. -- 2 highlights and 2 underlines (since error)
  831. -- 1 highlight + 1 underline
  832. local all_highlights = { 1, 1, 2, 4, 2 }
  833. eq(
  834. all_highlights,
  835. exec_lua(function()
  836. local ns_1_diags = {
  837. _G.make_error('Error 1', 1, 1, 1, 5),
  838. _G.make_warning('Warning on Server 1', 2, 1, 2, 3),
  839. }
  840. local ns_2_diags = {
  841. _G.make_warning('Warning 1', 2, 1, 2, 3),
  842. }
  843. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, ns_1_diags)
  844. vim.diagnostic.set(_G.other_ns, _G.diagnostic_bufnr, ns_2_diags)
  845. return {
  846. _G.count_diagnostics(
  847. _G.diagnostic_bufnr,
  848. vim.diagnostic.severity.ERROR,
  849. _G.diagnostic_ns
  850. ),
  851. _G.count_diagnostics(_G.diagnostic_bufnr, vim.diagnostic.severity.WARN, _G.other_ns),
  852. _G.count_diagnostics(_G.diagnostic_bufnr, vim.diagnostic.severity.WARN),
  853. _G.count_extmarks(_G.diagnostic_bufnr, _G.diagnostic_ns),
  854. _G.count_extmarks(_G.diagnostic_bufnr, _G.other_ns),
  855. }
  856. end)
  857. )
  858. -- Reset diagnostics from namespace 1
  859. exec_lua([[ vim.diagnostic.reset( _G.diagnostic_ns) ]])
  860. -- Make sure we have the right diagnostic count
  861. eq(
  862. { 0, 1, 1, 0, 2 },
  863. exec_lua(function()
  864. local diagnostic_count = {}
  865. vim.wait(100, function()
  866. diagnostic_count = {
  867. _G.count_diagnostics(
  868. _G.diagnostic_bufnr,
  869. vim.diagnostic.severity.ERROR,
  870. _G.diagnostic_ns
  871. ),
  872. _G.count_diagnostics(_G.diagnostic_bufnr, vim.diagnostic.severity.WARN, _G.other_ns),
  873. _G.count_diagnostics(_G.diagnostic_bufnr, vim.diagnostic.severity.WARN),
  874. _G.count_extmarks(_G.diagnostic_bufnr, _G.diagnostic_ns),
  875. _G.count_extmarks(_G.diagnostic_bufnr, _G.other_ns),
  876. }
  877. end)
  878. return diagnostic_count
  879. end)
  880. )
  881. -- Reset diagnostics from namespace 2
  882. exec_lua([[ vim.diagnostic.reset(_G.other_ns) ]])
  883. -- Make sure we have the right diagnostic count
  884. eq(
  885. { 0, 0, 0, 0, 0 },
  886. exec_lua(function()
  887. local diagnostic_count = {}
  888. vim.wait(100, function()
  889. diagnostic_count = {
  890. _G.count_diagnostics(
  891. _G.diagnostic_bufnr,
  892. vim.diagnostic.severity.ERROR,
  893. _G.diagnostic_ns
  894. ),
  895. _G.count_diagnostics(_G.diagnostic_bufnr, vim.diagnostic.severity.WARN, _G.other_ns),
  896. _G.count_diagnostics(_G.diagnostic_bufnr, vim.diagnostic.severity.WARN),
  897. _G.count_extmarks(_G.diagnostic_bufnr, _G.diagnostic_ns),
  898. _G.count_extmarks(_G.diagnostic_bufnr, _G.other_ns),
  899. }
  900. end)
  901. return diagnostic_count
  902. end)
  903. )
  904. end)
  905. it("doesn't error after bwipeout called on buffer", function()
  906. exec_lua(function()
  907. vim.diagnostic.set(
  908. _G.diagnostic_ns,
  909. _G.diagnostic_bufnr,
  910. { { message = '', lnum = 0, end_lnum = 0, col = 0, end_col = 0 } }
  911. )
  912. vim.cmd('bwipeout! ' .. _G.diagnostic_bufnr)
  913. vim.diagnostic.reset(_G.diagnostic_ns)
  914. end)
  915. end)
  916. end)
  917. describe('get_next()', function()
  918. it('can find the next pos with only one namespace', function()
  919. eq(
  920. { 1, 1 },
  921. exec_lua(function()
  922. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  923. _G.make_error('Diagnostic #1', 1, 1, 1, 1),
  924. })
  925. vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)
  926. local next = vim.diagnostic.get_next()
  927. return { next.lnum, next.col }
  928. end)
  929. )
  930. end)
  931. it('can find next pos with two errors', function()
  932. eq(
  933. { 4, 4 },
  934. exec_lua(function()
  935. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  936. _G.make_error('Diagnostic #1', 1, 1, 1, 1),
  937. _G.make_error('Diagnostic #2', 4, 4, 4, 4),
  938. })
  939. vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)
  940. vim.api.nvim_win_set_cursor(0, { 3, 1 })
  941. local next = vim.diagnostic.get_next({ namespace = _G.diagnostic_ns })
  942. return { next.lnum, next.col }
  943. end)
  944. )
  945. end)
  946. it('can cycle when position is past error', function()
  947. eq(
  948. { 1, 1 },
  949. exec_lua(function()
  950. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  951. _G.make_error('Diagnostic #1', 1, 1, 1, 1),
  952. })
  953. vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)
  954. vim.api.nvim_win_set_cursor(0, { 3, 1 })
  955. local next = vim.diagnostic.get_next({ namespace = _G.diagnostic_ns })
  956. return { next.lnum, next.col }
  957. end)
  958. )
  959. end)
  960. it('will not cycle when wrap is off', function()
  961. eq(
  962. nil,
  963. exec_lua(function()
  964. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  965. _G.make_error('Diagnostic #1', 1, 1, 1, 1),
  966. })
  967. vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)
  968. vim.api.nvim_win_set_cursor(0, { 3, 1 })
  969. local next = vim.diagnostic.get_next({ namespace = _G.diagnostic_ns, wrap = false })
  970. return next
  971. end)
  972. )
  973. end)
  974. it('can cycle even from the last line', function()
  975. eq(
  976. { 4, 4 },
  977. exec_lua(function()
  978. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  979. _G.make_error('Diagnostic #2', 4, 4, 4, 4),
  980. })
  981. vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)
  982. vim.api.nvim_win_set_cursor(0, { vim.api.nvim_buf_line_count(0), 1 })
  983. local prev = vim.diagnostic.get_prev({ namespace = _G.diagnostic_ns })
  984. return { prev.lnum, prev.col }
  985. end)
  986. )
  987. end)
  988. it('works with diagnostics past the end of the line #16349', function()
  989. eq(
  990. { 4, 0 },
  991. exec_lua(function()
  992. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  993. _G.make_error('Diagnostic #1', 3, 9001, 3, 9001),
  994. _G.make_error('Diagnostic #2', 4, 0, 4, 0),
  995. })
  996. vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)
  997. vim.api.nvim_win_set_cursor(0, { 1, 1 })
  998. vim.diagnostic.jump({ count = 1, float = false })
  999. local next = vim.diagnostic.get_next({ namespace = _G.diagnostic_ns })
  1000. return { next.lnum, next.col }
  1001. end)
  1002. )
  1003. end)
  1004. it('works with diagnostics before the start of the line', function()
  1005. eq(
  1006. { 4, 0 },
  1007. exec_lua(function()
  1008. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  1009. _G.make_error('Diagnostic #1', 3, 9001, 3, 9001),
  1010. _G.make_error('Diagnostic #2', 4, -1, 4, -1),
  1011. })
  1012. vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)
  1013. vim.api.nvim_win_set_cursor(0, { 1, 1 })
  1014. vim.diagnostic.jump({ count = 1, float = false })
  1015. local next = vim.diagnostic.get_next({ namespace = _G.diagnostic_ns })
  1016. return { next.lnum, next.col }
  1017. end)
  1018. )
  1019. end)
  1020. it('jumps to diagnostic with highest severity', function()
  1021. exec_lua(function()
  1022. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  1023. _G.make_info('Info', 1, 0, 1, 1),
  1024. _G.make_error('Error', 2, 0, 2, 1),
  1025. _G.make_warning('Warning', 3, 0, 3, 1),
  1026. _G.make_error('Error', 4, 0, 4, 1),
  1027. })
  1028. vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)
  1029. vim.api.nvim_win_set_cursor(0, { 1, 0 })
  1030. end)
  1031. eq(
  1032. { 3, 0 },
  1033. exec_lua(function()
  1034. vim.diagnostic.jump({ count = 1, _highest = true })
  1035. return vim.api.nvim_win_get_cursor(0)
  1036. end)
  1037. )
  1038. eq(
  1039. { 5, 0 },
  1040. exec_lua(function()
  1041. vim.diagnostic.jump({ count = 1, _highest = true })
  1042. return vim.api.nvim_win_get_cursor(0)
  1043. end)
  1044. )
  1045. exec_lua(function()
  1046. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  1047. _G.make_info('Info', 1, 0, 1, 1),
  1048. _G.make_hint('Hint', 2, 0, 2, 1),
  1049. _G.make_warning('Warning', 3, 0, 3, 1),
  1050. _G.make_hint('Hint', 4, 0, 4, 1),
  1051. _G.make_warning('Warning', 5, 0, 5, 1),
  1052. })
  1053. vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)
  1054. vim.api.nvim_win_set_cursor(0, { 1, 0 })
  1055. end)
  1056. eq(
  1057. { 4, 0 },
  1058. exec_lua(function()
  1059. vim.diagnostic.jump({ count = 1, _highest = true })
  1060. return vim.api.nvim_win_get_cursor(0)
  1061. end)
  1062. )
  1063. eq(
  1064. { 6, 0 },
  1065. exec_lua(function()
  1066. vim.diagnostic.jump({ count = 1, _highest = true })
  1067. return vim.api.nvim_win_get_cursor(0)
  1068. end)
  1069. )
  1070. end)
  1071. it('jumps to next diagnostic if severity is non-nil', function()
  1072. exec_lua(function()
  1073. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  1074. _G.make_info('Info', 1, 0, 1, 1),
  1075. _G.make_error('Error', 2, 0, 2, 1),
  1076. _G.make_warning('Warning', 3, 0, 3, 1),
  1077. _G.make_error('Error', 4, 0, 4, 1),
  1078. })
  1079. vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)
  1080. vim.api.nvim_win_set_cursor(0, { 1, 0 })
  1081. end)
  1082. eq(
  1083. { 2, 0 },
  1084. exec_lua(function()
  1085. vim.diagnostic.jump({ count = 1 })
  1086. return vim.api.nvim_win_get_cursor(0)
  1087. end)
  1088. )
  1089. eq(
  1090. { 3, 0 },
  1091. exec_lua(function()
  1092. vim.diagnostic.jump({ count = 1 })
  1093. return vim.api.nvim_win_get_cursor(0)
  1094. end)
  1095. )
  1096. eq(
  1097. { 4, 0 },
  1098. exec_lua(function()
  1099. vim.diagnostic.jump({ count = 1 })
  1100. return vim.api.nvim_win_get_cursor(0)
  1101. end)
  1102. )
  1103. end)
  1104. end)
  1105. describe('get_prev()', function()
  1106. it('can find the previous diagnostic with only one namespace', function()
  1107. eq(
  1108. { 1, 1 },
  1109. exec_lua(function()
  1110. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  1111. _G.make_error('Diagnostic #1', 1, 1, 1, 1),
  1112. })
  1113. vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)
  1114. vim.api.nvim_win_set_cursor(0, { 3, 1 })
  1115. local prev = vim.diagnostic.get_prev()
  1116. return { prev.lnum, prev.col }
  1117. end)
  1118. )
  1119. end)
  1120. it('can find the previous diagnostic with two errors', function()
  1121. eq(
  1122. { 1, 1 },
  1123. exec_lua(function()
  1124. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  1125. _G.make_error('Diagnostic #1', 1, 1, 1, 1),
  1126. _G.make_error('Diagnostic #2', 4, 4, 4, 4),
  1127. })
  1128. vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)
  1129. vim.api.nvim_win_set_cursor(0, { 3, 1 })
  1130. local prev = vim.diagnostic.get_prev({ namespace = _G.diagnostic_ns })
  1131. return { prev.lnum, prev.col }
  1132. end)
  1133. )
  1134. end)
  1135. it('can cycle when position is past error', function()
  1136. eq(
  1137. { 4, 4 },
  1138. exec_lua(function()
  1139. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  1140. _G.make_error('Diagnostic #2', 4, 4, 4, 4),
  1141. })
  1142. vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)
  1143. vim.api.nvim_win_set_cursor(0, { 3, 1 })
  1144. local prev = vim.diagnostic.get_prev({ namespace = _G.diagnostic_ns })
  1145. return { prev.lnum, prev.col }
  1146. end)
  1147. )
  1148. end)
  1149. it('respects wrap parameter', function()
  1150. eq(
  1151. nil,
  1152. exec_lua(function()
  1153. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  1154. _G.make_error('Diagnostic #2', 4, 4, 4, 4),
  1155. })
  1156. vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)
  1157. vim.api.nvim_win_set_cursor(0, { 3, 1 })
  1158. local prev = vim.diagnostic.get_prev({ namespace = _G.diagnostic_ns, wrap = false })
  1159. return prev
  1160. end)
  1161. )
  1162. end)
  1163. it('works on blank line #28397', function()
  1164. eq(
  1165. { 0, 2 },
  1166. exec_lua(function()
  1167. local test_bufnr = vim.api.nvim_create_buf(true, false)
  1168. vim.api.nvim_buf_set_lines(test_bufnr, 0, -1, false, {
  1169. 'first line',
  1170. '',
  1171. '',
  1172. 'end line',
  1173. })
  1174. vim.diagnostic.set(_G.diagnostic_ns, test_bufnr, {
  1175. _G.make_info('Diagnostic #1', 0, 2, 0, 2),
  1176. _G.make_info('Diagnostic #2', 2, 0, 2, 0),
  1177. _G.make_info('Diagnostic #3', 2, 0, 2, 0),
  1178. })
  1179. vim.api.nvim_win_set_buf(0, test_bufnr)
  1180. vim.api.nvim_win_set_cursor(0, { 3, 0 })
  1181. return vim.diagnostic.get_prev_pos { namespace = _G.diagnostic_ns }
  1182. end)
  1183. )
  1184. end)
  1185. end)
  1186. describe('jump()', function()
  1187. before_each(function()
  1188. exec_lua(function()
  1189. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  1190. _G.make_error('Diagnostic #1', 0, 0, 0, 2),
  1191. _G.make_error('Diagnostic #2', 1, 1, 1, 4),
  1192. _G.make_warning('Diagnostic #3', 2, -1, 2, -1),
  1193. _G.make_info('Diagnostic #4', 3, 0, 3, 3),
  1194. })
  1195. vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)
  1196. end)
  1197. end)
  1198. it('can move forward', function()
  1199. eq(
  1200. { 2, 1 },
  1201. exec_lua(function()
  1202. vim.api.nvim_win_set_cursor(0, { 1, 0 })
  1203. vim.diagnostic.jump({ count = 1 })
  1204. return vim.api.nvim_win_get_cursor(0)
  1205. end)
  1206. )
  1207. eq(
  1208. { 4, 0 },
  1209. exec_lua(function()
  1210. vim.api.nvim_win_set_cursor(0, { 1, 0 })
  1211. vim.diagnostic.jump({ count = 3 })
  1212. return vim.api.nvim_win_get_cursor(0)
  1213. end)
  1214. )
  1215. eq(
  1216. { 4, 0 },
  1217. exec_lua(function()
  1218. vim.api.nvim_win_set_cursor(0, { 1, 0 })
  1219. vim.diagnostic.jump({ count = math.huge, wrap = false })
  1220. return vim.api.nvim_win_get_cursor(0)
  1221. end)
  1222. )
  1223. end)
  1224. it('can move backward', function()
  1225. eq(
  1226. { 3, 0 },
  1227. exec_lua(function()
  1228. vim.api.nvim_win_set_cursor(0, { 4, 0 })
  1229. vim.diagnostic.jump({ count = -1 })
  1230. return vim.api.nvim_win_get_cursor(0)
  1231. end)
  1232. )
  1233. eq(
  1234. { 1, 0 },
  1235. exec_lua(function()
  1236. vim.api.nvim_win_set_cursor(0, { 4, 0 })
  1237. vim.diagnostic.jump({ count = -3 })
  1238. return vim.api.nvim_win_get_cursor(0)
  1239. end)
  1240. )
  1241. eq(
  1242. { 1, 0 },
  1243. exec_lua(function()
  1244. vim.api.nvim_win_set_cursor(0, { 4, 0 })
  1245. vim.diagnostic.jump({ count = -math.huge, wrap = false })
  1246. return vim.api.nvim_win_get_cursor(0)
  1247. end)
  1248. )
  1249. end)
  1250. it('can filter by severity', function()
  1251. eq(
  1252. { 3, 0 },
  1253. exec_lua(function()
  1254. vim.api.nvim_win_set_cursor(0, { 1, 0 })
  1255. vim.diagnostic.jump({ count = 1, severity = vim.diagnostic.severity.WARN })
  1256. return vim.api.nvim_win_get_cursor(0)
  1257. end)
  1258. )
  1259. eq(
  1260. { 3, 0 },
  1261. exec_lua(function()
  1262. vim.api.nvim_win_set_cursor(0, { 1, 0 })
  1263. vim.diagnostic.jump({ count = 9999, severity = vim.diagnostic.severity.WARN })
  1264. return vim.api.nvim_win_get_cursor(0)
  1265. end)
  1266. )
  1267. end)
  1268. it('can wrap', function()
  1269. eq(
  1270. { 1, 0 },
  1271. exec_lua(function()
  1272. vim.api.nvim_win_set_cursor(0, { 4, 0 })
  1273. vim.diagnostic.jump({ count = 1, wrap = true })
  1274. return vim.api.nvim_win_get_cursor(0)
  1275. end)
  1276. )
  1277. eq(
  1278. { 4, 0 },
  1279. exec_lua(function()
  1280. vim.api.nvim_win_set_cursor(0, { 1, 0 })
  1281. vim.diagnostic.jump({ count = -1, wrap = true })
  1282. return vim.api.nvim_win_get_cursor(0)
  1283. end)
  1284. )
  1285. end)
  1286. end)
  1287. describe('get()', function()
  1288. it('returns an empty table when no diagnostics are present', function()
  1289. eq(
  1290. {},
  1291. exec_lua [[return vim.diagnostic.get( _G.diagnostic_bufnr, {namespace=diagnostic_ns})]]
  1292. )
  1293. end)
  1294. it('returns all diagnostics when no severity is supplied', function()
  1295. eq(
  1296. 2,
  1297. exec_lua(function()
  1298. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  1299. _G.make_error('Error 1', 1, 1, 1, 5),
  1300. _G.make_warning('Warning on Server 1', 1, 1, 2, 3),
  1301. })
  1302. return #vim.diagnostic.get(_G.diagnostic_bufnr)
  1303. end)
  1304. )
  1305. end)
  1306. it('returns only requested diagnostics when severity range is supplied', function()
  1307. eq(
  1308. { 2, 3, 2 },
  1309. exec_lua(function()
  1310. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  1311. _G.make_error('Error 1', 1, 1, 1, 5),
  1312. _G.make_warning('Warning on Server 1', 1, 1, 2, 3),
  1313. _G.make_info('Ignored information', 1, 1, 2, 3),
  1314. _G.make_hint("Here's a hint", 1, 1, 2, 3),
  1315. })
  1316. return {
  1317. #vim.diagnostic.get(
  1318. _G.diagnostic_bufnr,
  1319. { severity = { min = vim.diagnostic.severity.WARN } }
  1320. ),
  1321. #vim.diagnostic.get(
  1322. _G.diagnostic_bufnr,
  1323. { severity = { max = vim.diagnostic.severity.WARN } }
  1324. ),
  1325. #vim.diagnostic.get(_G.diagnostic_bufnr, {
  1326. severity = {
  1327. min = vim.diagnostic.severity.INFO,
  1328. max = vim.diagnostic.severity.WARN,
  1329. },
  1330. }),
  1331. }
  1332. end)
  1333. )
  1334. end)
  1335. it('returns only requested diagnostics when severities are supplied', function()
  1336. eq(
  1337. { 1, 1, 2 },
  1338. exec_lua(function()
  1339. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  1340. _G.make_error('Error 1', 1, 1, 1, 5),
  1341. _G.make_warning('Warning on Server 1', 1, 1, 2, 3),
  1342. _G.make_info('Ignored information', 1, 1, 2, 3),
  1343. _G.make_hint("Here's a hint", 1, 1, 2, 3),
  1344. })
  1345. return {
  1346. #vim.diagnostic.get(
  1347. _G.diagnostic_bufnr,
  1348. { severity = { vim.diagnostic.severity.WARN } }
  1349. ),
  1350. #vim.diagnostic.get(
  1351. _G.diagnostic_bufnr,
  1352. { severity = { vim.diagnostic.severity.ERROR } }
  1353. ),
  1354. #vim.diagnostic.get(_G.diagnostic_bufnr, {
  1355. severity = {
  1356. vim.diagnostic.severity.INFO,
  1357. vim.diagnostic.severity.WARN,
  1358. },
  1359. }),
  1360. }
  1361. end)
  1362. )
  1363. end)
  1364. it('allows filtering by line', function()
  1365. eq(
  1366. 2,
  1367. exec_lua(function()
  1368. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  1369. _G.make_error('Error 1', 1, 1, 1, 5),
  1370. _G.make_warning('Warning on Server 1', 1, 1, 2, 3),
  1371. _G.make_info('Ignored information', 1, 1, 2, 3),
  1372. _G.make_error('Error On Other Line', 3, 1, 3, 5),
  1373. })
  1374. return #vim.diagnostic.get(_G.diagnostic_bufnr, { lnum = 2 })
  1375. end)
  1376. )
  1377. end)
  1378. end)
  1379. describe('count', function()
  1380. it('returns actually present severity counts', function()
  1381. eq(
  1382. exec_lua(function()
  1383. return {
  1384. [vim.diagnostic.severity.ERROR] = 4,
  1385. [vim.diagnostic.severity.WARN] = 3,
  1386. [vim.diagnostic.severity.INFO] = 2,
  1387. [vim.diagnostic.severity.HINT] = 1,
  1388. }
  1389. end),
  1390. exec_lua(function()
  1391. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  1392. _G.make_error('Error 1', 1, 1, 1, 2),
  1393. _G.make_error('Error 2', 1, 3, 1, 4),
  1394. _G.make_error('Error 3', 1, 5, 1, 6),
  1395. _G.make_error('Error 4', 1, 7, 1, 8),
  1396. _G.make_warning('Warning 1', 2, 1, 2, 2),
  1397. _G.make_warning('Warning 2', 2, 3, 2, 4),
  1398. _G.make_warning('Warning 3', 2, 5, 2, 6),
  1399. _G.make_info('Info 1', 3, 1, 3, 2),
  1400. _G.make_info('Info 2', 3, 3, 3, 4),
  1401. _G.make_hint('Hint 1', 4, 1, 4, 2),
  1402. })
  1403. return vim.diagnostic.count(_G.diagnostic_bufnr)
  1404. end)
  1405. )
  1406. eq(
  1407. exec_lua(function()
  1408. return {
  1409. [vim.diagnostic.severity.ERROR] = 2,
  1410. [vim.diagnostic.severity.INFO] = 1,
  1411. }
  1412. end),
  1413. exec_lua(function()
  1414. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  1415. _G.make_error('Error 1', 1, 1, 1, 2),
  1416. _G.make_error('Error 2', 1, 3, 1, 4),
  1417. _G.make_info('Info 1', 3, 1, 3, 2),
  1418. })
  1419. return vim.diagnostic.count(_G.diagnostic_bufnr)
  1420. end)
  1421. )
  1422. end)
  1423. it('returns only requested diagnostics count when severity range is supplied', function()
  1424. eq(
  1425. exec_lua(function()
  1426. return {
  1427. { [vim.diagnostic.severity.ERROR] = 1, [vim.diagnostic.severity.WARN] = 1 },
  1428. {
  1429. [vim.diagnostic.severity.WARN] = 1,
  1430. [vim.diagnostic.severity.INFO] = 1,
  1431. [vim.diagnostic.severity.HINT] = 1,
  1432. },
  1433. { [vim.diagnostic.severity.WARN] = 1, [vim.diagnostic.severity.INFO] = 1 },
  1434. }
  1435. end),
  1436. exec_lua(function()
  1437. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  1438. _G.make_error('Error 1', 1, 1, 1, 5),
  1439. _G.make_warning('Warning on Server 1', 1, 1, 2, 3),
  1440. _G.make_info('Ignored information', 1, 1, 2, 3),
  1441. _G.make_hint("Here's a hint", 1, 1, 2, 3),
  1442. })
  1443. return {
  1444. vim.diagnostic.count(
  1445. _G.diagnostic_bufnr,
  1446. { severity = { min = vim.diagnostic.severity.WARN } }
  1447. ),
  1448. vim.diagnostic.count(
  1449. _G.diagnostic_bufnr,
  1450. { severity = { max = vim.diagnostic.severity.WARN } }
  1451. ),
  1452. vim.diagnostic.count(_G.diagnostic_bufnr, {
  1453. severity = {
  1454. min = vim.diagnostic.severity.INFO,
  1455. max = vim.diagnostic.severity.WARN,
  1456. },
  1457. }),
  1458. }
  1459. end)
  1460. )
  1461. end)
  1462. it('returns only requested diagnostics when severities are supplied', function()
  1463. eq(
  1464. exec_lua(function()
  1465. return {
  1466. { [vim.diagnostic.severity.WARN] = 1 },
  1467. { [vim.diagnostic.severity.ERROR] = 1 },
  1468. { [vim.diagnostic.severity.WARN] = 1, [vim.diagnostic.severity.INFO] = 1 },
  1469. }
  1470. end),
  1471. exec_lua(function()
  1472. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  1473. _G.make_error('Error 1', 1, 1, 1, 5),
  1474. _G.make_warning('Warning on Server 1', 1, 1, 2, 3),
  1475. _G.make_info('Ignored information', 1, 1, 2, 3),
  1476. _G.make_hint("Here's a hint", 1, 1, 2, 3),
  1477. })
  1478. return {
  1479. vim.diagnostic.count(
  1480. _G.diagnostic_bufnr,
  1481. { severity = { vim.diagnostic.severity.WARN } }
  1482. ),
  1483. vim.diagnostic.count(
  1484. _G.diagnostic_bufnr,
  1485. { severity = { vim.diagnostic.severity.ERROR } }
  1486. ),
  1487. vim.diagnostic.count(_G.diagnostic_bufnr, {
  1488. severity = {
  1489. vim.diagnostic.severity.INFO,
  1490. vim.diagnostic.severity.WARN,
  1491. },
  1492. }),
  1493. }
  1494. end)
  1495. )
  1496. end)
  1497. it('allows filtering by line', function()
  1498. eq(
  1499. exec_lua(function()
  1500. return {
  1501. [vim.diagnostic.severity.WARN] = 1,
  1502. [vim.diagnostic.severity.INFO] = 1,
  1503. }
  1504. end),
  1505. exec_lua(function()
  1506. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  1507. _G.make_error('Error 1', 1, 1, 1, 5),
  1508. _G.make_warning('Warning on Server 1', 1, 1, 2, 3),
  1509. _G.make_info('Ignored information', 1, 1, 2, 3),
  1510. _G.make_error('Error On Other Line', 3, 1, 3, 5),
  1511. })
  1512. return vim.diagnostic.count(_G.diagnostic_bufnr, { lnum = 2 })
  1513. end)
  1514. )
  1515. end)
  1516. end)
  1517. describe('config()', function()
  1518. it('works with global, namespace, and ephemeral options', function()
  1519. eq(
  1520. 1,
  1521. exec_lua(function()
  1522. vim.diagnostic.config({
  1523. virtual_text = false,
  1524. })
  1525. vim.diagnostic.config({
  1526. virtual_text = true,
  1527. underline = false,
  1528. }, _G.diagnostic_ns)
  1529. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  1530. _G.make_error('Some Error', 4, 4, 4, 4),
  1531. })
  1532. return _G.count_extmarks(_G.diagnostic_bufnr, _G.diagnostic_ns)
  1533. end)
  1534. )
  1535. eq(
  1536. 1,
  1537. exec_lua(function()
  1538. vim.diagnostic.config({
  1539. virtual_text = false,
  1540. })
  1541. vim.diagnostic.config({
  1542. virtual_text = false,
  1543. underline = false,
  1544. }, _G.diagnostic_ns)
  1545. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  1546. _G.make_error('Some Error', 4, 4, 4, 4),
  1547. }, { virtual_text = true })
  1548. return _G.count_extmarks(_G.diagnostic_bufnr, _G.diagnostic_ns)
  1549. end)
  1550. )
  1551. eq(
  1552. 0,
  1553. exec_lua(function()
  1554. vim.diagnostic.config({
  1555. virtual_text = false,
  1556. })
  1557. vim.diagnostic.config({
  1558. virtual_text = { severity = vim.diagnostic.severity.ERROR },
  1559. underline = false,
  1560. }, _G.diagnostic_ns)
  1561. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  1562. _G.make_warning('Some Warning', 4, 4, 4, 4),
  1563. }, { virtual_text = true })
  1564. return _G.count_extmarks(_G.diagnostic_bufnr, _G.diagnostic_ns)
  1565. end)
  1566. )
  1567. eq(
  1568. 1,
  1569. exec_lua(function()
  1570. vim.diagnostic.config({
  1571. virtual_text = false,
  1572. })
  1573. vim.diagnostic.config({
  1574. virtual_text = { severity = vim.diagnostic.severity.ERROR },
  1575. underline = false,
  1576. }, _G.diagnostic_ns)
  1577. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  1578. _G.make_warning('Some Warning', 4, 4, 4, 4),
  1579. }, {
  1580. virtual_text = {}, -- An empty table uses default values
  1581. })
  1582. return _G.count_extmarks(_G.diagnostic_bufnr, _G.diagnostic_ns)
  1583. end)
  1584. )
  1585. end)
  1586. it('can use functions for config values', function()
  1587. exec_lua(function()
  1588. vim.diagnostic.config({
  1589. virtual_text = function()
  1590. return true
  1591. end,
  1592. }, _G.diagnostic_ns)
  1593. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  1594. _G.make_error('Delayed Diagnostic', 4, 4, 4, 4),
  1595. })
  1596. end)
  1597. eq(
  1598. 1,
  1599. exec_lua [[return _G.count_diagnostics( _G.diagnostic_bufnr, vim.diagnostic.severity.ERROR, _G.diagnostic_ns)]]
  1600. )
  1601. eq(2, exec_lua [[return _G.count_extmarks( _G.diagnostic_bufnr, _G.diagnostic_ns)]])
  1602. -- Now, don't enable virtual text.
  1603. -- We should have one less extmark displayed.
  1604. exec_lua(function()
  1605. vim.diagnostic.config({
  1606. virtual_text = function()
  1607. return false
  1608. end,
  1609. }, _G.diagnostic_ns)
  1610. end)
  1611. eq(
  1612. 1,
  1613. exec_lua [[return _G.count_diagnostics( _G.diagnostic_bufnr, vim.diagnostic.severity.ERROR, _G.diagnostic_ns)]]
  1614. )
  1615. eq(1, exec_lua [[return _G.count_extmarks( _G.diagnostic_bufnr, _G.diagnostic_ns)]])
  1616. end)
  1617. it('allows filtering by severity', function()
  1618. local get_extmark_count_with_severity = function(min_severity)
  1619. return exec_lua(function()
  1620. vim.diagnostic.config({
  1621. underline = false,
  1622. virtual_text = {
  1623. severity = { min = min_severity },
  1624. },
  1625. })
  1626. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  1627. _G.make_warning('Delayed Diagnostic', 4, 4, 4, 4),
  1628. })
  1629. return _G.count_extmarks(_G.diagnostic_bufnr, _G.diagnostic_ns)
  1630. end)
  1631. end
  1632. -- No messages with Error or higher
  1633. eq(0, get_extmark_count_with_severity('ERROR'))
  1634. -- But now we don't filter it
  1635. eq(1, get_extmark_count_with_severity('WARN'))
  1636. eq(1, get_extmark_count_with_severity('HINT'))
  1637. end)
  1638. it('allows sorting by severity', function()
  1639. exec_lua(function()
  1640. vim.diagnostic.config({
  1641. underline = false,
  1642. signs = true,
  1643. virtual_text = true,
  1644. })
  1645. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  1646. _G.make_warning('Warning', 4, 4, 4, 4),
  1647. _G.make_error('Error', 4, 4, 4, 4),
  1648. _G.make_info('Info', 4, 4, 4, 4),
  1649. })
  1650. function _G.get_highest_underline_hl(severity_sort)
  1651. vim.diagnostic.config({
  1652. underline = true,
  1653. severity_sort = severity_sort,
  1654. })
  1655. local extmarks = _G.get_underline_extmarks(_G.diagnostic_ns)
  1656. table.sort(extmarks, function(a, b)
  1657. return a[4].priority > b[4].priority
  1658. end)
  1659. return extmarks[1][4].hl_group
  1660. end
  1661. function _G.get_virt_text_and_signs(severity_sort)
  1662. vim.diagnostic.config({
  1663. severity_sort = severity_sort,
  1664. })
  1665. local virt_text = _G.get_virt_text_extmarks(_G.diagnostic_ns)[1][4].virt_text
  1666. local virt_texts = {}
  1667. for i = 2, #virt_text - 1 do
  1668. table.insert(virt_texts, (string.gsub(virt_text[i][2], 'DiagnosticVirtualText', '')))
  1669. end
  1670. local ns = vim.diagnostic.get_namespace(_G.diagnostic_ns)
  1671. local sign_ns = ns.user_data.sign_ns
  1672. local signs = {}
  1673. local all_signs = vim.api.nvim_buf_get_extmarks(
  1674. _G.diagnostic_bufnr,
  1675. sign_ns,
  1676. 0,
  1677. -1,
  1678. { type = 'sign', details = true }
  1679. )
  1680. table.sort(all_signs, function(a, b)
  1681. return a[1] > b[1]
  1682. end)
  1683. for _, v in ipairs(all_signs) do
  1684. local s = v[4].sign_hl_group:gsub('DiagnosticSign', '')
  1685. if not vim.tbl_contains(signs, s) then
  1686. signs[#signs + 1] = s
  1687. end
  1688. end
  1689. return { virt_texts, signs }
  1690. end
  1691. end)
  1692. local result = exec_lua [[return _G.get_virt_text_and_signs(false)]]
  1693. -- Virt texts are defined lowest priority to highest, signs from
  1694. -- highest to lowest
  1695. eq({ 'Warn', 'Error', 'Info' }, result[1])
  1696. eq({ 'Info', 'Error', 'Warn' }, result[2])
  1697. result = exec_lua [[return _G.get_virt_text_and_signs(true)]]
  1698. eq({ 'Info', 'Warn', 'Error' }, result[1])
  1699. eq({ 'Error', 'Warn', 'Info' }, result[2])
  1700. result = exec_lua [[return _G.get_virt_text_and_signs({ reverse = true })]]
  1701. eq({ 'Error', 'Warn', 'Info' }, result[1])
  1702. eq({ 'Info', 'Warn', 'Error' }, result[2])
  1703. local underline_hl = exec_lua [[return _G.get_highest_underline_hl(true)]]
  1704. eq('DiagnosticUnderlineError', underline_hl)
  1705. underline_hl = exec_lua [[return _G.get_highest_underline_hl({ reverse = true })]]
  1706. eq('DiagnosticUnderlineInfo', underline_hl)
  1707. end)
  1708. it('can show diagnostic sources in virtual text', function()
  1709. local result = exec_lua(function()
  1710. local diagnostics = {
  1711. _G.make_error('Some error', 0, 0, 0, 0, 'source x'),
  1712. }
  1713. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, diagnostics, {
  1714. underline = false,
  1715. virtual_text = {
  1716. prefix = '',
  1717. source = 'always',
  1718. },
  1719. })
  1720. local extmarks = _G.get_virt_text_extmarks(_G.diagnostic_ns)
  1721. local virt_text = extmarks[1][4].virt_text[3][1]
  1722. return virt_text
  1723. end)
  1724. eq(' source x: Some error', result)
  1725. result = exec_lua(function()
  1726. vim.diagnostic.config({
  1727. underline = false,
  1728. virtual_text = {
  1729. prefix = '',
  1730. source = 'if_many',
  1731. },
  1732. }, _G.diagnostic_ns)
  1733. local extmarks = _G.get_virt_text_extmarks(_G.diagnostic_ns)
  1734. local virt_text = extmarks[1][4].virt_text[3][1]
  1735. return virt_text
  1736. end)
  1737. eq(' Some error', result)
  1738. result = exec_lua(function()
  1739. local diagnostics = {
  1740. _G.make_error('Some error', 0, 0, 0, 0, 'source x'),
  1741. _G.make_error('Another error', 1, 1, 1, 1, 'source y'),
  1742. }
  1743. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, diagnostics, {
  1744. underline = false,
  1745. virtual_text = {
  1746. prefix = '',
  1747. source = 'if_many',
  1748. },
  1749. })
  1750. local extmarks = _G.get_virt_text_extmarks(_G.diagnostic_ns)
  1751. local virt_text = { extmarks[1][4].virt_text[3][1], extmarks[2][4].virt_text[3][1] }
  1752. return virt_text
  1753. end)
  1754. eq(' source x: Some error', result[1])
  1755. eq(' source y: Another error', result[2])
  1756. end)
  1757. it('supports a format function for diagnostic messages', function()
  1758. local result = exec_lua(function()
  1759. vim.diagnostic.config({
  1760. underline = false,
  1761. virtual_text = {
  1762. prefix = '',
  1763. format = function(diagnostic)
  1764. if diagnostic.severity == vim.diagnostic.severity.ERROR then
  1765. return string.format('🔥 %s', diagnostic.message)
  1766. end
  1767. return string.format('👀 %s', diagnostic.message)
  1768. end,
  1769. },
  1770. })
  1771. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  1772. _G.make_warning('Warning', 0, 0, 0, 0),
  1773. _G.make_error('Error', 1, 0, 1, 0),
  1774. })
  1775. local extmarks = _G.get_virt_text_extmarks(_G.diagnostic_ns)
  1776. return { extmarks[1][4].virt_text, extmarks[2][4].virt_text }
  1777. end)
  1778. eq(' 👀 Warning', result[1][3][1])
  1779. eq(' 🔥 Error', result[2][3][1])
  1780. end)
  1781. it('includes source for formatted diagnostics', function()
  1782. local result = exec_lua(function()
  1783. vim.diagnostic.config({
  1784. underline = false,
  1785. virtual_text = {
  1786. prefix = '',
  1787. source = 'always',
  1788. format = function(diagnostic)
  1789. if diagnostic.severity == vim.diagnostic.severity.ERROR then
  1790. return string.format('🔥 %s', diagnostic.message)
  1791. end
  1792. return string.format('👀 %s', diagnostic.message)
  1793. end,
  1794. },
  1795. })
  1796. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  1797. _G.make_warning('Warning', 0, 0, 0, 0, 'some_linter'),
  1798. _G.make_error('Error', 1, 0, 1, 0, 'another_linter'),
  1799. })
  1800. local extmarks = _G.get_virt_text_extmarks(_G.diagnostic_ns)
  1801. return { extmarks[1][4].virt_text, extmarks[2][4].virt_text }
  1802. end)
  1803. eq(' some_linter: 👀 Warning', result[1][3][1])
  1804. eq(' another_linter: 🔥 Error', result[2][3][1])
  1805. end)
  1806. it('can add a prefix to virtual text', function()
  1807. eq(
  1808. 'E Some error',
  1809. exec_lua(function()
  1810. local diagnostics = {
  1811. _G.make_error('Some error', 0, 0, 0, 0),
  1812. }
  1813. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, diagnostics, {
  1814. underline = false,
  1815. virtual_text = {
  1816. prefix = 'E',
  1817. suffix = '',
  1818. },
  1819. })
  1820. local extmarks = _G.get_virt_text_extmarks(_G.diagnostic_ns)
  1821. local prefix = extmarks[1][4].virt_text[2][1]
  1822. local message = extmarks[1][4].virt_text[3][1]
  1823. return prefix .. message
  1824. end)
  1825. )
  1826. eq(
  1827. '[(1/1) err-code] Some error',
  1828. exec_lua(function()
  1829. local diagnostics = {
  1830. _G.make_error('Some error', 0, 0, 0, 0, nil, 'err-code'),
  1831. }
  1832. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, diagnostics, {
  1833. underline = false,
  1834. virtual_text = {
  1835. prefix = function(diag, i, total)
  1836. return string.format('[(%d/%d) %s]', i, total, diag.code)
  1837. end,
  1838. suffix = '',
  1839. },
  1840. })
  1841. local extmarks = _G.get_virt_text_extmarks(_G.diagnostic_ns)
  1842. local prefix = extmarks[1][4].virt_text[2][1]
  1843. local message = extmarks[1][4].virt_text[3][1]
  1844. return prefix .. message
  1845. end)
  1846. )
  1847. end)
  1848. it('can add a suffix to virtual text', function()
  1849. eq(
  1850. ' Some error ✘',
  1851. exec_lua(function()
  1852. local diagnostics = {
  1853. _G.make_error('Some error', 0, 0, 0, 0),
  1854. }
  1855. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, diagnostics, {
  1856. underline = false,
  1857. virtual_text = {
  1858. prefix = '',
  1859. suffix = ' ✘',
  1860. },
  1861. })
  1862. local extmarks = _G.get_virt_text_extmarks(_G.diagnostic_ns)
  1863. local virt_text = extmarks[1][4].virt_text[3][1]
  1864. return virt_text
  1865. end)
  1866. )
  1867. eq(
  1868. ' Some error [err-code]',
  1869. exec_lua(function()
  1870. local diagnostics = {
  1871. _G.make_error('Some error', 0, 0, 0, 0, nil, 'err-code'),
  1872. }
  1873. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, diagnostics, {
  1874. underline = false,
  1875. virtual_text = {
  1876. prefix = '',
  1877. suffix = function(diag)
  1878. return string.format(' [%s]', diag.code)
  1879. end,
  1880. },
  1881. })
  1882. local extmarks = _G.get_virt_text_extmarks(_G.diagnostic_ns)
  1883. local virt_text = extmarks[1][4].virt_text[3][1]
  1884. return virt_text
  1885. end)
  1886. )
  1887. end)
  1888. end)
  1889. describe('handlers.virtual_lines', function()
  1890. it('includes diagnostic code and message', function()
  1891. local result = exec_lua(function()
  1892. vim.diagnostic.config({ virtual_lines = true })
  1893. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  1894. _G.make_error('Missed symbol `,`', 0, 0, 0, 0, 'lua_ls', 'miss-symbol'),
  1895. })
  1896. local extmarks = _G.get_virt_lines_extmarks(_G.diagnostic_ns)
  1897. return extmarks[1][4].virt_lines
  1898. end)
  1899. eq('miss-symbol: Missed symbol `,`', result[1][3][1])
  1900. end)
  1901. it('adds space to the left of the diagnostic', function()
  1902. local error_offset = 5
  1903. local result = exec_lua(function()
  1904. vim.diagnostic.config({ virtual_lines = true })
  1905. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  1906. _G.make_error('Error here!', 0, error_offset, 0, error_offset, 'foo_server'),
  1907. })
  1908. local extmarks = _G.get_virt_lines_extmarks(_G.diagnostic_ns)
  1909. return extmarks[1][4].virt_lines
  1910. end)
  1911. eq(error_offset, result[1][1][1]:len())
  1912. end)
  1913. it('highlights diagnostics in multiple lines by default', function()
  1914. local result = exec_lua(function()
  1915. vim.diagnostic.config({ virtual_lines = true })
  1916. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  1917. _G.make_error('Error here!', 0, 0, 0, 0, 'foo_server'),
  1918. _G.make_error('Another error there!', 1, 0, 1, 0, 'foo_server'),
  1919. })
  1920. local extmarks = _G.get_virt_lines_extmarks(_G.diagnostic_ns)
  1921. return extmarks
  1922. end)
  1923. eq(2, #result)
  1924. eq('Error here!', result[1][4].virt_lines[1][3][1])
  1925. eq('Another error there!', result[2][4].virt_lines[1][3][1])
  1926. end)
  1927. it('can highlight diagnostics only in the current line', function()
  1928. local result = exec_lua(function()
  1929. vim.api.nvim_win_set_cursor(0, { 1, 0 })
  1930. vim.diagnostic.config({ virtual_lines = { current_line = true } })
  1931. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  1932. _G.make_error('Error here!', 0, 0, 0, 0, 'foo_server'),
  1933. _G.make_error('Another error there!', 1, 0, 1, 0, 'foo_server'),
  1934. })
  1935. local extmarks = _G.get_virt_lines_extmarks(_G.diagnostic_ns)
  1936. return extmarks
  1937. end)
  1938. eq(1, #result)
  1939. eq('Error here!', result[1][4].virt_lines[1][3][1])
  1940. end)
  1941. it('supports a format function for diagnostic messages', function()
  1942. local result = exec_lua(function()
  1943. vim.diagnostic.config({
  1944. virtual_lines = {
  1945. format = function()
  1946. return 'Error here!'
  1947. end,
  1948. },
  1949. })
  1950. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  1951. _G.make_error('Invalid syntax', 0, 0, 0, 0),
  1952. })
  1953. local extmarks = _G.get_virt_lines_extmarks(_G.diagnostic_ns)
  1954. return extmarks[1][4].virt_lines
  1955. end)
  1956. eq('Error here!', result[1][3][1])
  1957. end)
  1958. end)
  1959. describe('set()', function()
  1960. it('validation', function()
  1961. matches(
  1962. 'expected a list of diagnostics',
  1963. pcall_err(exec_lua, [[vim.diagnostic.set(1, 0, {lnum = 1, col = 2})]])
  1964. )
  1965. end)
  1966. it('can perform updates after insert_leave', function()
  1967. exec_lua(function()
  1968. vim.diagnostic.config({ virtual_text = true })
  1969. vim.api.nvim_set_current_buf(_G.diagnostic_bufnr)
  1970. end)
  1971. api.nvim_input('o')
  1972. eq({ mode = 'i', blocking = false }, api.nvim_get_mode())
  1973. -- Save the diagnostics
  1974. exec_lua(function()
  1975. vim.diagnostic.config({
  1976. update_in_insert = false,
  1977. })
  1978. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  1979. _G.make_error('Delayed Diagnostic', 4, 4, 4, 4),
  1980. })
  1981. end)
  1982. -- No diagnostics displayed yet.
  1983. eq({ mode = 'i', blocking = false }, api.nvim_get_mode())
  1984. eq(
  1985. 1,
  1986. exec_lua [[return _G.count_diagnostics( _G.diagnostic_bufnr, vim.diagnostic.severity.ERROR, _G.diagnostic_ns)]]
  1987. )
  1988. eq(0, exec_lua [[return _G.count_extmarks( _G.diagnostic_bufnr, _G.diagnostic_ns)]])
  1989. api.nvim_input('<esc>')
  1990. eq({ mode = 'n', blocking = false }, api.nvim_get_mode())
  1991. eq(
  1992. 1,
  1993. exec_lua [[return _G.count_diagnostics( _G.diagnostic_bufnr, vim.diagnostic.severity.ERROR, _G.diagnostic_ns)]]
  1994. )
  1995. eq(2, exec_lua [[return _G.count_extmarks( _G.diagnostic_bufnr, _G.diagnostic_ns)]])
  1996. end)
  1997. it('does not perform updates when not needed', function()
  1998. exec_lua [[vim.api.nvim_set_current_buf( _G.diagnostic_bufnr)]]
  1999. api.nvim_input('o')
  2000. eq({ mode = 'i', blocking = false }, api.nvim_get_mode())
  2001. -- Save the diagnostics
  2002. exec_lua(function()
  2003. vim.diagnostic.config({
  2004. update_in_insert = false,
  2005. virtual_text = true,
  2006. })
  2007. _G.DisplayCount = 0
  2008. local set_virtual_text = vim.diagnostic.handlers.virtual_text.show
  2009. vim.diagnostic.handlers.virtual_text.show = function(...)
  2010. _G.DisplayCount = _G.DisplayCount + 1
  2011. return set_virtual_text(...)
  2012. end
  2013. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  2014. _G.make_error('Delayed Diagnostic', 4, 4, 4, 4),
  2015. })
  2016. end)
  2017. -- No diagnostics displayed yet.
  2018. eq({ mode = 'i', blocking = false }, api.nvim_get_mode())
  2019. eq(
  2020. 1,
  2021. exec_lua [[return _G.count_diagnostics( _G.diagnostic_bufnr, vim.diagnostic.severity.ERROR, _G.diagnostic_ns)]]
  2022. )
  2023. eq(0, exec_lua [[return _G.count_extmarks( _G.diagnostic_bufnr, _G.diagnostic_ns)]])
  2024. eq(0, exec_lua [[return _G.DisplayCount]])
  2025. api.nvim_input('<esc>')
  2026. eq({ mode = 'n', blocking = false }, api.nvim_get_mode())
  2027. eq(
  2028. 1,
  2029. exec_lua [[return _G.count_diagnostics( _G.diagnostic_bufnr, vim.diagnostic.severity.ERROR, _G.diagnostic_ns)]]
  2030. )
  2031. eq(2, exec_lua [[return _G.count_extmarks( _G.diagnostic_bufnr, _G.diagnostic_ns)]])
  2032. eq(1, exec_lua [[return _G.DisplayCount]])
  2033. -- Go in and out of insert mode one more time.
  2034. api.nvim_input('o')
  2035. eq({ mode = 'i', blocking = false }, api.nvim_get_mode())
  2036. api.nvim_input('<esc>')
  2037. eq({ mode = 'n', blocking = false }, api.nvim_get_mode())
  2038. -- Should not have set the virtual text again.
  2039. eq(1, exec_lua [[return _G.DisplayCount]])
  2040. end)
  2041. it('never sets virtual text, in combination with insert leave', function()
  2042. exec_lua [[vim.api.nvim_set_current_buf( _G.diagnostic_bufnr)]]
  2043. api.nvim_input('o')
  2044. eq({ mode = 'i', blocking = false }, api.nvim_get_mode())
  2045. -- Save the diagnostics
  2046. exec_lua(function()
  2047. vim.diagnostic.config({
  2048. update_in_insert = false,
  2049. virtual_text = false,
  2050. })
  2051. _G.DisplayCount = 0
  2052. local set_virtual_text = vim.diagnostic.handlers.virtual_text.show
  2053. vim.diagnostic.handlers.virtual_text.show = function(...)
  2054. _G.DisplayCount = _G.DisplayCount + 1
  2055. return set_virtual_text(...)
  2056. end
  2057. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  2058. _G.make_error('Delayed Diagnostic', 4, 4, 4, 4),
  2059. })
  2060. end)
  2061. -- No diagnostics displayed yet.
  2062. eq({ mode = 'i', blocking = false }, api.nvim_get_mode())
  2063. eq(
  2064. 1,
  2065. exec_lua [[return _G.count_diagnostics( _G.diagnostic_bufnr, vim.diagnostic.severity.ERROR, _G.diagnostic_ns)]]
  2066. )
  2067. eq(0, exec_lua [[return _G.count_extmarks( _G.diagnostic_bufnr, _G.diagnostic_ns)]])
  2068. eq(0, exec_lua [[return _G.DisplayCount]])
  2069. api.nvim_input('<esc>')
  2070. eq({ mode = 'n', blocking = false }, api.nvim_get_mode())
  2071. eq(
  2072. 1,
  2073. exec_lua [[return _G.count_diagnostics( _G.diagnostic_bufnr, vim.diagnostic.severity.ERROR, _G.diagnostic_ns)]]
  2074. )
  2075. eq(1, exec_lua [[return _G.count_extmarks( _G.diagnostic_bufnr, _G.diagnostic_ns)]])
  2076. eq(0, exec_lua [[return _G.DisplayCount]])
  2077. -- Go in and out of insert mode one more time.
  2078. api.nvim_input('o')
  2079. eq({ mode = 'i', blocking = false }, api.nvim_get_mode())
  2080. api.nvim_input('<esc>')
  2081. eq({ mode = 'n', blocking = false }, api.nvim_get_mode())
  2082. -- Should not have set the virtual text still.
  2083. eq(0, exec_lua [[return _G.DisplayCount]])
  2084. end)
  2085. it('can perform updates while in insert mode, if desired', function()
  2086. exec_lua(function()
  2087. vim.diagnostic.config({ virtual_text = true })
  2088. vim.api.nvim_set_current_buf(_G.diagnostic_bufnr)
  2089. end)
  2090. api.nvim_input('o')
  2091. eq({ mode = 'i', blocking = false }, api.nvim_get_mode())
  2092. -- Save the diagnostics
  2093. exec_lua(function()
  2094. vim.diagnostic.config({
  2095. update_in_insert = true,
  2096. })
  2097. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  2098. _G.make_error('Delayed Diagnostic', 4, 4, 4, 4),
  2099. })
  2100. end)
  2101. -- Diagnostics are displayed, because the user wanted them that way!
  2102. eq({ mode = 'i', blocking = false }, api.nvim_get_mode())
  2103. eq(
  2104. 1,
  2105. exec_lua [[return _G.count_diagnostics( _G.diagnostic_bufnr, vim.diagnostic.severity.ERROR, _G.diagnostic_ns)]]
  2106. )
  2107. eq(2, exec_lua [[return _G.count_extmarks( _G.diagnostic_bufnr, _G.diagnostic_ns)]])
  2108. api.nvim_input('<esc>')
  2109. eq({ mode = 'n', blocking = false }, api.nvim_get_mode())
  2110. eq(
  2111. 1,
  2112. exec_lua [[return _G.count_diagnostics( _G.diagnostic_bufnr, vim.diagnostic.severity.ERROR, _G.diagnostic_ns)]]
  2113. )
  2114. eq(2, exec_lua [[return _G.count_extmarks( _G.diagnostic_bufnr, _G.diagnostic_ns)]])
  2115. end)
  2116. it('can set diagnostics without displaying them', function()
  2117. exec_lua(function()
  2118. vim.diagnostic.config({ virtual_text = true })
  2119. end)
  2120. eq(
  2121. 0,
  2122. exec_lua(function()
  2123. vim.diagnostic.enable(false, { bufnr = _G.diagnostic_bufnr, ns_id = _G.diagnostic_ns })
  2124. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  2125. _G.make_error('Diagnostic From Server 1:1', 1, 1, 1, 1),
  2126. })
  2127. return _G.count_extmarks(_G.diagnostic_bufnr, _G.diagnostic_ns)
  2128. end)
  2129. )
  2130. eq(
  2131. 2,
  2132. exec_lua(function()
  2133. vim.diagnostic.enable(true, { bufnr = _G.diagnostic_bufnr, ns_id = _G.diagnostic_ns })
  2134. return _G.count_extmarks(_G.diagnostic_bufnr, _G.diagnostic_ns)
  2135. end)
  2136. )
  2137. end)
  2138. it('can set display options', function()
  2139. eq(
  2140. 0,
  2141. exec_lua(function()
  2142. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  2143. _G.make_error('Diagnostic From Server 1:1', 1, 1, 1, 1),
  2144. }, { virtual_text = false, underline = false })
  2145. return _G.count_extmarks(_G.diagnostic_bufnr, _G.diagnostic_ns)
  2146. end)
  2147. )
  2148. eq(
  2149. 1,
  2150. exec_lua(function()
  2151. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  2152. _G.make_error('Diagnostic From Server 1:1', 1, 1, 1, 1),
  2153. }, { virtual_text = true, underline = false })
  2154. return _G.count_extmarks(_G.diagnostic_bufnr, _G.diagnostic_ns)
  2155. end)
  2156. )
  2157. end)
  2158. it('sets and clears signs #26193 #26555', function()
  2159. do
  2160. local result = exec_lua(function()
  2161. vim.diagnostic.config({
  2162. signs = true,
  2163. })
  2164. local diagnostics = {
  2165. _G.make_error('Error', 1, 1, 1, 2),
  2166. _G.make_warning('Warning', 3, 3, 3, 3),
  2167. }
  2168. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, diagnostics)
  2169. local ns = vim.diagnostic.get_namespace(_G.diagnostic_ns)
  2170. local sign_ns = ns.user_data.sign_ns
  2171. local signs = vim.api.nvim_buf_get_extmarks(
  2172. _G.diagnostic_bufnr,
  2173. sign_ns,
  2174. 0,
  2175. -1,
  2176. { type = 'sign', details = true }
  2177. )
  2178. local result = {}
  2179. for _, s in ipairs(signs) do
  2180. result[#result + 1] = { lnum = s[2] + 1, name = s[4].sign_hl_group }
  2181. end
  2182. return result
  2183. end)
  2184. eq({ 2, 'DiagnosticSignError' }, { result[1].lnum, result[1].name })
  2185. eq({ 4, 'DiagnosticSignWarn' }, { result[2].lnum, result[2].name })
  2186. end
  2187. do
  2188. local result = exec_lua(function()
  2189. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {})
  2190. local ns = vim.diagnostic.get_namespace(_G.diagnostic_ns)
  2191. local sign_ns = ns.user_data.sign_ns
  2192. return vim.api.nvim_buf_get_extmarks(
  2193. _G.diagnostic_bufnr,
  2194. sign_ns,
  2195. 0,
  2196. -1,
  2197. { type = 'sign', details = true }
  2198. )
  2199. end)
  2200. eq({}, result)
  2201. end
  2202. end)
  2203. it('respects legacy signs placed with :sign define or sign_define #26618', function()
  2204. -- Legacy signs for diagnostics were deprecated in 0.10 and will be removed in 0.12
  2205. eq(0, n.fn.has('nvim-0.12'))
  2206. n.command('sign define DiagnosticSignError text= texthl= linehl=ErrorMsg numhl=ErrorMsg')
  2207. n.command('sign define DiagnosticSignWarn text= texthl= linehl=WarningMsg numhl=WarningMsg')
  2208. n.command('sign define DiagnosticSignInfo text= texthl= linehl=Underlined numhl=Underlined')
  2209. n.command('sign define DiagnosticSignHint text= texthl= linehl=Underlined numhl=Underlined')
  2210. local result = exec_lua(function()
  2211. vim.diagnostic.config({
  2212. signs = true,
  2213. })
  2214. local diagnostics = {
  2215. _G.make_error('Error', 1, 1, 1, 2),
  2216. _G.make_warning('Warning', 3, 3, 3, 3),
  2217. }
  2218. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, diagnostics)
  2219. local ns = vim.diagnostic.get_namespace(_G.diagnostic_ns)
  2220. local sign_ns = ns.user_data.sign_ns
  2221. local signs = vim.api.nvim_buf_get_extmarks(
  2222. _G.diagnostic_bufnr,
  2223. sign_ns,
  2224. 0,
  2225. -1,
  2226. { type = 'sign', details = true }
  2227. )
  2228. local result = {}
  2229. for _, s in ipairs(signs) do
  2230. result[#result + 1] = {
  2231. lnum = s[2] + 1,
  2232. name = s[4].sign_hl_group,
  2233. text = s[4].sign_text or '',
  2234. numhl = s[4].number_hl_group,
  2235. linehl = s[4].line_hl_group,
  2236. }
  2237. end
  2238. return result
  2239. end)
  2240. eq({
  2241. lnum = 2,
  2242. name = 'DiagnosticSignError',
  2243. text = '',
  2244. numhl = 'ErrorMsg',
  2245. linehl = 'ErrorMsg',
  2246. }, result[1])
  2247. eq({
  2248. lnum = 4,
  2249. name = 'DiagnosticSignWarn',
  2250. text = '',
  2251. numhl = 'WarningMsg',
  2252. linehl = 'WarningMsg',
  2253. }, result[2])
  2254. end)
  2255. end)
  2256. describe('open_float()', function()
  2257. it('can display a header', function()
  2258. eq(
  2259. { 'Diagnostics:', '1. Syntax error' },
  2260. exec_lua(function()
  2261. local diagnostics = {
  2262. _G.make_error('Syntax error', 0, 1, 0, 3),
  2263. }
  2264. vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)
  2265. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, diagnostics)
  2266. local float_bufnr, winnr = vim.diagnostic.open_float()
  2267. local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
  2268. vim.api.nvim_win_close(winnr, true)
  2269. return lines
  2270. end)
  2271. )
  2272. eq(
  2273. { "We're no strangers to love...", '1. Syntax error' },
  2274. exec_lua(function()
  2275. local diagnostics = {
  2276. _G.make_error('Syntax error', 0, 1, 0, 3),
  2277. }
  2278. vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)
  2279. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, diagnostics)
  2280. local float_bufnr, winnr =
  2281. vim.diagnostic.open_float({ header = "We're no strangers to love..." })
  2282. local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
  2283. vim.api.nvim_win_close(winnr, true)
  2284. return lines
  2285. end)
  2286. )
  2287. eq(
  2288. { 'You know the rules', '1. Syntax error' },
  2289. exec_lua(function()
  2290. local diagnostics = {
  2291. _G.make_error('Syntax error', 0, 1, 0, 3),
  2292. }
  2293. vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)
  2294. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, diagnostics)
  2295. local float_bufnr, winnr =
  2296. vim.diagnostic.open_float({ header = { 'You know the rules', 'Search' } })
  2297. local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
  2298. vim.api.nvim_win_close(winnr, true)
  2299. return lines
  2300. end)
  2301. )
  2302. end)
  2303. it('can show diagnostics from the whole buffer', function()
  2304. eq(
  2305. { '1. Syntax error', '2. Some warning' },
  2306. exec_lua(function()
  2307. local diagnostics = {
  2308. _G.make_error('Syntax error', 0, 1, 0, 3),
  2309. _G.make_warning('Some warning', 1, 1, 1, 3),
  2310. }
  2311. vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)
  2312. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, diagnostics)
  2313. local float_bufnr, winnr = vim.diagnostic.open_float({ header = false, scope = 'buffer' })
  2314. local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
  2315. vim.api.nvim_win_close(winnr, true)
  2316. return lines
  2317. end)
  2318. )
  2319. end)
  2320. it('can show diagnostics from a single line', function()
  2321. -- Using cursor position
  2322. eq(
  2323. { '1. Some warning' },
  2324. exec_lua(function()
  2325. local diagnostics = {
  2326. _G.make_error('Syntax error', 0, 1, 0, 3),
  2327. _G.make_warning('Some warning', 1, 1, 1, 3),
  2328. }
  2329. vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)
  2330. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, diagnostics)
  2331. vim.api.nvim_win_set_cursor(0, { 2, 1 })
  2332. local float_bufnr, winnr = vim.diagnostic.open_float({ header = false })
  2333. local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
  2334. vim.api.nvim_win_close(winnr, true)
  2335. return lines
  2336. end)
  2337. )
  2338. -- With specified position
  2339. eq(
  2340. { '1. Some warning' },
  2341. exec_lua(function()
  2342. local diagnostics = {
  2343. _G.make_error('Syntax error', 0, 1, 0, 3),
  2344. _G.make_warning('Some warning', 1, 1, 1, 3),
  2345. }
  2346. vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)
  2347. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, diagnostics)
  2348. vim.api.nvim_win_set_cursor(0, { 1, 1 })
  2349. local float_bufnr, winnr = vim.diagnostic.open_float({ header = false, pos = 1 })
  2350. local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
  2351. vim.api.nvim_win_close(winnr, true)
  2352. return lines
  2353. end)
  2354. )
  2355. -- End position is exclusive
  2356. eq(
  2357. nil,
  2358. exec_lua(function()
  2359. local diagnostics = {
  2360. _G.make_error('Syntax error', 1, 1, 2, 0),
  2361. }
  2362. vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)
  2363. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, diagnostics)
  2364. vim.api.nvim_win_set_cursor(0, { 1, 1 })
  2365. local _, winnr = vim.diagnostic.open_float(0, { header = false, pos = { 2, 0 } })
  2366. return winnr
  2367. end)
  2368. )
  2369. -- Works when width == 0
  2370. eq(
  2371. { '1. Syntax error' },
  2372. exec_lua(function()
  2373. local diagnostics = {
  2374. _G.make_error('Syntax error', 2, 0, 2, 0),
  2375. }
  2376. vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)
  2377. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, diagnostics)
  2378. vim.api.nvim_win_set_cursor(0, { 1, 1 })
  2379. local float_bufnr, winnr =
  2380. vim.diagnostic.open_float(0, { header = false, pos = { 2, 1 } })
  2381. local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
  2382. vim.api.nvim_win_close(winnr, true)
  2383. return lines
  2384. end)
  2385. )
  2386. end)
  2387. it('can show diagnostics from a specific position', function()
  2388. -- Using cursor position
  2389. eq(
  2390. { 'Syntax error' },
  2391. exec_lua(function()
  2392. local diagnostics = {
  2393. _G.make_error('Syntax error', 1, 1, 1, 3),
  2394. _G.make_warning('Some warning', 1, 3, 1, 4),
  2395. }
  2396. vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)
  2397. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, diagnostics)
  2398. vim.api.nvim_win_set_cursor(0, { 2, 2 })
  2399. local float_bufnr, winnr = vim.diagnostic.open_float({ header = false, scope = 'cursor' })
  2400. local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
  2401. vim.api.nvim_win_close(winnr, true)
  2402. return lines
  2403. end)
  2404. )
  2405. -- With specified position
  2406. eq(
  2407. { 'Some warning' },
  2408. exec_lua(function()
  2409. local diagnostics = {
  2410. _G.make_error('Syntax error', 1, 1, 1, 3),
  2411. _G.make_warning('Some warning', 1, 3, 1, 4),
  2412. }
  2413. vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)
  2414. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, diagnostics)
  2415. vim.api.nvim_win_set_cursor(0, { 1, 1 })
  2416. local float_bufnr, winnr =
  2417. vim.diagnostic.open_float({ header = false, scope = 'cursor', pos = { 1, 3 } })
  2418. local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
  2419. vim.api.nvim_win_close(winnr, true)
  2420. return lines
  2421. end)
  2422. )
  2423. -- With column position past the end of the line. #16062
  2424. eq(
  2425. { 'Syntax error' },
  2426. exec_lua(function()
  2427. local first_line_len = #vim.api.nvim_buf_get_lines(_G.diagnostic_bufnr, 0, 1, true)[1]
  2428. local diagnostics = {
  2429. _G.make_error('Syntax error', 0, first_line_len + 1, 1, 0),
  2430. }
  2431. vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)
  2432. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, diagnostics)
  2433. vim.api.nvim_win_set_cursor(0, { 1, 1 })
  2434. local float_bufnr, winnr = vim.diagnostic.open_float({
  2435. header = false,
  2436. scope = 'cursor',
  2437. pos = { 0, first_line_len },
  2438. })
  2439. local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
  2440. vim.api.nvim_win_close(winnr, true)
  2441. return lines
  2442. end)
  2443. )
  2444. -- End position is exclusive
  2445. eq(
  2446. nil,
  2447. exec_lua(function()
  2448. local diagnostics = {
  2449. _G.make_error('Syntax error', 1, 1, 1, 3),
  2450. }
  2451. vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)
  2452. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, diagnostics)
  2453. vim.api.nvim_win_set_cursor(0, { 1, 1 })
  2454. local _, winnr =
  2455. vim.diagnostic.open_float(0, { header = false, scope = 'cursor', pos = { 1, 3 } })
  2456. return winnr
  2457. end)
  2458. )
  2459. -- Works when width == 0
  2460. eq(
  2461. { 'Syntax error' },
  2462. exec_lua(function()
  2463. local diagnostics = {
  2464. _G.make_error('Syntax error', 2, 0, 2, 0),
  2465. }
  2466. vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)
  2467. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, diagnostics)
  2468. vim.api.nvim_win_set_cursor(0, { 1, 1 })
  2469. local float_bufnr, winnr =
  2470. vim.diagnostic.open_float({ header = false, scope = 'cursor', pos = { 2, 1 } })
  2471. local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
  2472. vim.api.nvim_win_close(winnr, true)
  2473. return lines
  2474. end)
  2475. )
  2476. end)
  2477. it(
  2478. 'creates floating window and returns float bufnr and winnr if current line contains diagnostics',
  2479. function()
  2480. -- Two lines:
  2481. -- Diagnostic:
  2482. -- 1. <msg>
  2483. eq(
  2484. 2,
  2485. exec_lua(function()
  2486. local diagnostics = {
  2487. _G.make_error('Syntax error', 0, 1, 0, 3),
  2488. }
  2489. vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)
  2490. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, diagnostics)
  2491. local float_bufnr, winnr = vim.diagnostic.open_float(_G.diagnostic_bufnr)
  2492. local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
  2493. vim.api.nvim_win_close(winnr, true)
  2494. return #lines
  2495. end)
  2496. )
  2497. end
  2498. )
  2499. it('only reports diagnostics from the current buffer when bufnr is omitted #15710', function()
  2500. eq(
  2501. 2,
  2502. exec_lua(function()
  2503. local other_bufnr = vim.api.nvim_create_buf(true, false)
  2504. local buf_1_diagnostics = {
  2505. _G.make_error('Syntax error', 0, 1, 0, 3),
  2506. }
  2507. local buf_2_diagnostics = {
  2508. _G.make_warning('Some warning', 0, 1, 0, 3),
  2509. }
  2510. vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)
  2511. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, buf_1_diagnostics)
  2512. vim.diagnostic.set(_G.other_ns, other_bufnr, buf_2_diagnostics)
  2513. local float_bufnr, winnr = vim.diagnostic.open_float()
  2514. local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
  2515. vim.api.nvim_win_close(winnr, true)
  2516. return #lines
  2517. end)
  2518. )
  2519. end)
  2520. it('allows filtering by namespace', function()
  2521. eq(
  2522. 2,
  2523. exec_lua(function()
  2524. local ns_1_diagnostics = {
  2525. _G.make_error('Syntax error', 0, 1, 0, 3),
  2526. }
  2527. local ns_2_diagnostics = {
  2528. _G.make_warning('Some warning', 0, 1, 0, 3),
  2529. }
  2530. vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)
  2531. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, ns_1_diagnostics)
  2532. vim.diagnostic.set(_G.other_ns, _G.diagnostic_bufnr, ns_2_diagnostics)
  2533. local float_bufnr, winnr =
  2534. vim.diagnostic.open_float(_G.diagnostic_bufnr, { namespace = _G.diagnostic_ns })
  2535. local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
  2536. vim.api.nvim_win_close(winnr, true)
  2537. return #lines
  2538. end)
  2539. )
  2540. end)
  2541. it(
  2542. 'creates floating window and returns float bufnr and winnr without header, if requested',
  2543. function()
  2544. -- One line (since no header):
  2545. -- 1. <msg>
  2546. eq(
  2547. 1,
  2548. exec_lua(function()
  2549. local diagnostics = {
  2550. _G.make_error('Syntax error', 0, 1, 0, 3),
  2551. }
  2552. vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)
  2553. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, diagnostics)
  2554. local float_bufnr, winnr =
  2555. vim.diagnostic.open_float(_G.diagnostic_bufnr, { header = false })
  2556. local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
  2557. vim.api.nvim_win_close(winnr, true)
  2558. return #lines
  2559. end)
  2560. )
  2561. end
  2562. )
  2563. it('clamps diagnostic line numbers within the valid range', function()
  2564. eq(
  2565. 1,
  2566. exec_lua(function()
  2567. local diagnostics = {
  2568. _G.make_error('Syntax error', 6, 0, 6, 0),
  2569. }
  2570. vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)
  2571. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, diagnostics)
  2572. local float_bufnr, winnr =
  2573. vim.diagnostic.open_float(_G.diagnostic_bufnr, { header = false, pos = 5 })
  2574. local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
  2575. vim.api.nvim_win_close(winnr, true)
  2576. return #lines
  2577. end)
  2578. )
  2579. end)
  2580. it('can show diagnostic source', function()
  2581. exec_lua [[vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)]]
  2582. eq(
  2583. { '1. Syntax error' },
  2584. exec_lua(function()
  2585. local diagnostics = {
  2586. _G.make_error('Syntax error', 0, 1, 0, 3, 'source x'),
  2587. }
  2588. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, diagnostics)
  2589. local float_bufnr, winnr = vim.diagnostic.open_float(_G.diagnostic_bufnr, {
  2590. header = false,
  2591. source = 'if_many',
  2592. })
  2593. local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
  2594. vim.api.nvim_win_close(winnr, true)
  2595. return lines
  2596. end)
  2597. )
  2598. eq(
  2599. { '1. source x: Syntax error' },
  2600. exec_lua(function()
  2601. local float_bufnr, winnr = vim.diagnostic.open_float(_G.diagnostic_bufnr, {
  2602. header = false,
  2603. source = 'always',
  2604. })
  2605. local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
  2606. vim.api.nvim_win_close(winnr, true)
  2607. return lines
  2608. end)
  2609. )
  2610. eq(
  2611. { '1. source x: Syntax error', '2. source y: Another error' },
  2612. exec_lua(function()
  2613. local diagnostics = {
  2614. _G.make_error('Syntax error', 0, 1, 0, 3, 'source x'),
  2615. _G.make_error('Another error', 0, 1, 0, 3, 'source y'),
  2616. }
  2617. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, diagnostics)
  2618. local float_bufnr, winnr = vim.diagnostic.open_float(_G.diagnostic_bufnr, {
  2619. header = false,
  2620. source = 'if_many',
  2621. })
  2622. local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
  2623. vim.api.nvim_win_close(winnr, true)
  2624. return lines
  2625. end)
  2626. )
  2627. end)
  2628. it('respects severity_sort', function()
  2629. exec_lua [[vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)]]
  2630. eq(
  2631. { '1. Syntax error', '2. Info', '3. Error', '4. Warning' },
  2632. exec_lua(function()
  2633. local diagnostics = {
  2634. _G.make_error('Syntax error', 0, 1, 0, 3),
  2635. _G.make_info('Info', 0, 3, 0, 4),
  2636. _G.make_error('Error', 0, 2, 0, 2),
  2637. _G.make_warning('Warning', 0, 0, 0, 1),
  2638. }
  2639. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, diagnostics)
  2640. vim.diagnostic.config({ severity_sort = false })
  2641. local float_bufnr, winnr =
  2642. vim.diagnostic.open_float(_G.diagnostic_bufnr, { header = false })
  2643. local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
  2644. vim.api.nvim_win_close(winnr, true)
  2645. return lines
  2646. end)
  2647. )
  2648. eq(
  2649. { '1. Syntax error', '2. Error', '3. Warning', '4. Info' },
  2650. exec_lua(function()
  2651. vim.diagnostic.config({ severity_sort = true })
  2652. local float_bufnr, winnr =
  2653. vim.diagnostic.open_float(_G.diagnostic_bufnr, { header = false })
  2654. local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
  2655. vim.api.nvim_win_close(winnr, true)
  2656. return lines
  2657. end)
  2658. )
  2659. eq(
  2660. { '1. Info', '2. Warning', '3. Error', '4. Syntax error' },
  2661. exec_lua(function()
  2662. vim.diagnostic.config({ severity_sort = { reverse = true } })
  2663. local float_bufnr, winnr =
  2664. vim.diagnostic.open_float(_G.diagnostic_bufnr, { header = false })
  2665. local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
  2666. vim.api.nvim_win_close(winnr, true)
  2667. return lines
  2668. end)
  2669. )
  2670. end)
  2671. it('can filter by severity', function()
  2672. local count_diagnostics_with_severity = function(min_severity, max_severity)
  2673. return exec_lua(function()
  2674. vim.diagnostic.config({
  2675. float = {
  2676. severity = { min = min_severity, max = max_severity },
  2677. },
  2678. })
  2679. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  2680. _G.make_error('Syntax error', 0, 1, 0, 3),
  2681. _G.make_info('Info', 0, 3, 0, 4),
  2682. _G.make_error('Error', 0, 2, 0, 2),
  2683. _G.make_warning('Warning', 0, 0, 0, 1),
  2684. })
  2685. local float_bufnr, winnr =
  2686. vim.diagnostic.open_float(_G.diagnostic_bufnr, { header = false })
  2687. if not float_bufnr then
  2688. return 0
  2689. end
  2690. local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
  2691. vim.api.nvim_win_close(winnr, true)
  2692. return #lines
  2693. end)
  2694. end
  2695. eq(2, count_diagnostics_with_severity('ERROR'))
  2696. eq(3, count_diagnostics_with_severity('WARN'))
  2697. eq(1, count_diagnostics_with_severity('WARN', 'WARN'))
  2698. eq(4, count_diagnostics_with_severity('HINT'))
  2699. eq(0, count_diagnostics_with_severity('HINT', 'HINT'))
  2700. end)
  2701. it('can add a prefix to diagnostics', function()
  2702. -- Default is to add a number
  2703. eq(
  2704. { '1. Syntax error', '2. Some warning' },
  2705. exec_lua(function()
  2706. local diagnostics = {
  2707. _G.make_error('Syntax error', 0, 1, 0, 3),
  2708. _G.make_warning('Some warning', 1, 1, 1, 3),
  2709. }
  2710. vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)
  2711. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, diagnostics)
  2712. local float_bufnr, winnr = vim.diagnostic.open_float({ header = false, scope = 'buffer' })
  2713. local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
  2714. vim.api.nvim_win_close(winnr, true)
  2715. return lines
  2716. end)
  2717. )
  2718. eq(
  2719. { 'Syntax error', 'Some warning' },
  2720. exec_lua(function()
  2721. local diagnostics = {
  2722. _G.make_error('Syntax error', 0, 1, 0, 3),
  2723. _G.make_warning('Some warning', 1, 1, 1, 3),
  2724. }
  2725. vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)
  2726. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, diagnostics)
  2727. local float_bufnr, winnr =
  2728. vim.diagnostic.open_float({ header = false, scope = 'buffer', prefix = '' })
  2729. local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
  2730. vim.api.nvim_win_close(winnr, true)
  2731. return lines
  2732. end)
  2733. )
  2734. eq(
  2735. { '1. Syntax error', '2. Some warning' },
  2736. exec_lua(function()
  2737. local diagnostics = {
  2738. _G.make_error('Syntax error', 0, 1, 0, 3),
  2739. _G.make_warning('Some warning', 0, 1, 0, 3),
  2740. }
  2741. vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)
  2742. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, diagnostics)
  2743. local float_bufnr, winnr = vim.diagnostic.open_float({
  2744. header = false,
  2745. prefix = function(_, i, total)
  2746. -- Only show a number if there is more than one diagnostic
  2747. if total > 1 then
  2748. return string.format('%d. ', i)
  2749. end
  2750. return ''
  2751. end,
  2752. })
  2753. local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
  2754. vim.api.nvim_win_close(winnr, true)
  2755. return lines
  2756. end)
  2757. )
  2758. eq(
  2759. { 'Syntax error' },
  2760. exec_lua(function()
  2761. local diagnostics = {
  2762. _G.make_error('Syntax error', 0, 1, 0, 3),
  2763. }
  2764. vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)
  2765. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, diagnostics)
  2766. local float_bufnr, winnr = vim.diagnostic.open_float({
  2767. header = false,
  2768. prefix = function(_, i, total)
  2769. -- Only show a number if there is more than one diagnostic
  2770. if total > 1 then
  2771. return string.format('%d. ', i)
  2772. end
  2773. return ''
  2774. end,
  2775. })
  2776. local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
  2777. vim.api.nvim_win_close(winnr, true)
  2778. return lines
  2779. end)
  2780. )
  2781. eq(
  2782. '.../diagnostic.lua:0: prefix: expected string|table|function, got number',
  2783. pcall_err(exec_lua, [[ vim.diagnostic.open_float({ prefix = 42 }) ]])
  2784. )
  2785. end)
  2786. it('can add a suffix to diagnostics', function()
  2787. -- Default is to render the diagnostic error code
  2788. eq(
  2789. { '1. Syntax error [code-x]', '2. Some warning [code-y]' },
  2790. exec_lua(function()
  2791. local diagnostics = {
  2792. _G.make_error('Syntax error', 0, 1, 0, 3, nil, 'code-x'),
  2793. _G.make_warning('Some warning', 1, 1, 1, 3, nil, 'code-y'),
  2794. }
  2795. vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)
  2796. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, diagnostics)
  2797. local float_bufnr, winnr = vim.diagnostic.open_float({ header = false, scope = 'buffer' })
  2798. local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
  2799. vim.api.nvim_win_close(winnr, true)
  2800. return lines
  2801. end)
  2802. )
  2803. eq(
  2804. { '1. Syntax error', '2. Some warning' },
  2805. exec_lua(function()
  2806. local diagnostics = {
  2807. _G.make_error('Syntax error', 0, 1, 0, 3, nil, 'code-x'),
  2808. _G.make_warning('Some warning', 1, 1, 1, 3, nil, 'code-y'),
  2809. }
  2810. vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)
  2811. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, diagnostics)
  2812. local float_bufnr, winnr =
  2813. vim.diagnostic.open_float({ header = false, scope = 'buffer', suffix = '' })
  2814. local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
  2815. vim.api.nvim_win_close(winnr, true)
  2816. return lines
  2817. end)
  2818. )
  2819. -- Suffix is rendered on the last line of a multiline diagnostic
  2820. eq(
  2821. { '1. Syntax error', ' More context [code-x]' },
  2822. exec_lua(function()
  2823. local diagnostics = {
  2824. _G.make_error('Syntax error\nMore context', 0, 1, 0, 3, nil, 'code-x'),
  2825. }
  2826. vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)
  2827. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, diagnostics)
  2828. local float_bufnr, winnr = vim.diagnostic.open_float({ header = false, scope = 'buffer' })
  2829. local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
  2830. vim.api.nvim_win_close(winnr, true)
  2831. return lines
  2832. end)
  2833. )
  2834. eq(
  2835. '.../diagnostic.lua:0: suffix: expected string|table|function, got number',
  2836. pcall_err(exec_lua, [[ vim.diagnostic.open_float({ suffix = 42 }) ]])
  2837. )
  2838. end)
  2839. it('works with the old signature', function()
  2840. eq(
  2841. { '1. Syntax error' },
  2842. exec_lua(function()
  2843. local diagnostics = {
  2844. _G.make_error('Syntax error', 0, 1, 0, 3),
  2845. }
  2846. vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)
  2847. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, diagnostics)
  2848. local float_bufnr, winnr = vim.diagnostic.open_float(0, { header = false })
  2849. local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
  2850. vim.api.nvim_win_close(winnr, true)
  2851. return lines
  2852. end)
  2853. )
  2854. end)
  2855. it('works for multi-line diagnostics #21949', function()
  2856. -- create diagnostic
  2857. exec_lua(function()
  2858. local diagnostics = {
  2859. _G.make_error('Error in two lines lnum is 1 and end_lnum is 2', 1, 1, 2, 3),
  2860. }
  2861. vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)
  2862. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, diagnostics)
  2863. end)
  2864. -- open float failed non diagnostic lnum
  2865. eq(
  2866. nil,
  2867. exec_lua(function()
  2868. vim.api.nvim_win_set_cursor(0, { 1, 0 })
  2869. local _, winnr = vim.diagnostic.open_float(0, { header = false })
  2870. return winnr
  2871. end)
  2872. )
  2873. eq(
  2874. nil,
  2875. exec_lua(function()
  2876. vim.api.nvim_win_set_cursor(0, { 1, 0 })
  2877. local _, winnr = vim.diagnostic.open_float(0, { header = false, scope = 'cursor' })
  2878. return winnr
  2879. end)
  2880. )
  2881. -- can open a float window on lnum 1
  2882. eq(
  2883. { '1. Error in two lines lnum is 1 and end_lnum is 2' },
  2884. exec_lua(function()
  2885. vim.api.nvim_win_set_cursor(0, { 2, 0 })
  2886. local float_bufnr, winnr = vim.diagnostic.open_float(0, { header = false })
  2887. local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
  2888. vim.api.nvim_win_close(winnr, true)
  2889. return lines
  2890. end)
  2891. )
  2892. -- can open a cursor-scoped float window on lnum 1
  2893. eq(
  2894. { 'Error in two lines lnum is 1 and end_lnum is 2' },
  2895. exec_lua(function()
  2896. vim.api.nvim_win_set_cursor(0, { 2, 1 })
  2897. local float_bufnr, winnr =
  2898. vim.diagnostic.open_float(0, { header = false, scope = 'cursor' })
  2899. local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
  2900. vim.api.nvim_win_close(winnr, true)
  2901. return lines
  2902. end)
  2903. )
  2904. -- can open a float window on end_lnum 2
  2905. eq(
  2906. { '1. Error in two lines lnum is 1 and end_lnum is 2' },
  2907. exec_lua(function()
  2908. vim.api.nvim_win_set_cursor(0, { 3, 0 })
  2909. local float_bufnr, winnr = vim.diagnostic.open_float(0, { header = false })
  2910. local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
  2911. vim.api.nvim_win_close(winnr, true)
  2912. return lines
  2913. end)
  2914. )
  2915. -- can open a cursor-scoped float window on end_lnum 2
  2916. eq(
  2917. { 'Error in two lines lnum is 1 and end_lnum is 2' },
  2918. exec_lua(function()
  2919. vim.api.nvim_win_set_cursor(0, { 3, 2 })
  2920. local float_bufnr, winnr =
  2921. vim.diagnostic.open_float(0, { header = false, scope = 'cursor' })
  2922. local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
  2923. vim.api.nvim_win_close(winnr, true)
  2924. return lines
  2925. end)
  2926. )
  2927. end)
  2928. end)
  2929. describe('setloclist()', function()
  2930. it('sets diagnostics in lnum order', function()
  2931. local loc_list = exec_lua(function()
  2932. vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)
  2933. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  2934. _G.make_error('Farther Diagnostic', 4, 4, 4, 4),
  2935. _G.make_error('Lower Diagnostic', 1, 1, 1, 1),
  2936. })
  2937. vim.diagnostic.setloclist()
  2938. return vim.fn.getloclist(0)
  2939. end)
  2940. assert(loc_list[1].lnum < loc_list[2].lnum)
  2941. end)
  2942. it('sets diagnostics in lnum order, regardless of namespace', function()
  2943. local loc_list = exec_lua(function()
  2944. vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)
  2945. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  2946. _G.make_error('Lower Diagnostic', 1, 1, 1, 1),
  2947. })
  2948. vim.diagnostic.set(_G.other_ns, _G.diagnostic_bufnr, {
  2949. _G.make_warning('Farther Diagnostic', 4, 4, 4, 4),
  2950. })
  2951. vim.diagnostic.setloclist()
  2952. return vim.fn.getloclist(0)
  2953. end)
  2954. assert(loc_list[1].lnum < loc_list[2].lnum)
  2955. end)
  2956. end)
  2957. describe('setqflist()', function()
  2958. it('updates existing diagnostics quickfix if one already exists', function()
  2959. local result = exec_lua(function()
  2960. vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)
  2961. vim.fn.setqflist({}, ' ', { title = 'Diagnostics' })
  2962. local diagnostics_qf_id = vim.fn.getqflist({ id = 0 }).id
  2963. vim.diagnostic.setqflist({ title = 'Diagnostics' })
  2964. local qf_id = vim.fn.getqflist({ id = 0, nr = '$' }).id
  2965. return { diagnostics_qf_id, qf_id }
  2966. end)
  2967. eq(result[1], result[2])
  2968. end)
  2969. it('navigates to existing diagnostics quickfix if one already exists and open=true', function()
  2970. local result = exec_lua(function()
  2971. vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)
  2972. vim.fn.setqflist({}, ' ', { title = 'Diagnostics' })
  2973. local diagnostics_qf_id = vim.fn.getqflist({ id = 0 }).id
  2974. vim.fn.setqflist({}, ' ', { title = 'Other' })
  2975. vim.diagnostic.setqflist({ title = 'Diagnostics', open = true })
  2976. local qf_id = vim.fn.getqflist({ id = 0 }).id
  2977. return { diagnostics_qf_id, qf_id }
  2978. end)
  2979. eq(result[1], result[2])
  2980. end)
  2981. it('sets new diagnostics quickfix as active when open=true', function()
  2982. local result = exec_lua(function()
  2983. vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)
  2984. vim.fn.setqflist({}, ' ', { title = 'Other' })
  2985. local other_qf_id = vim.fn.getqflist({ id = 0 }).id
  2986. vim.diagnostic.setqflist({ title = 'Diagnostics', open = true })
  2987. local qf_id = vim.fn.getqflist({ id = 0 }).id
  2988. return { other_qf_id, qf_id }
  2989. end)
  2990. neq(result[1], result[2])
  2991. end)
  2992. it('opens quickfix window when open=true', function()
  2993. local qf_winid = exec_lua(function()
  2994. vim.api.nvim_win_set_buf(0, _G.diagnostic_bufnr)
  2995. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  2996. _G.make_error('Error', 1, 1, 1, 1),
  2997. })
  2998. vim.diagnostic.setqflist({ open = true })
  2999. return vim.fn.getqflist({ winid = 0 }).winid
  3000. end)
  3001. neq(0, qf_winid)
  3002. end)
  3003. end)
  3004. describe('match()', function()
  3005. it('matches a string', function()
  3006. local msg = 'ERROR: george.txt:19:84:Two plus two equals five'
  3007. local diagnostic = {
  3008. severity = exec_lua [[return vim.diagnostic.severity.ERROR]],
  3009. lnum = 18,
  3010. col = 83,
  3011. end_lnum = 18,
  3012. end_col = 83,
  3013. message = 'Two plus two equals five',
  3014. }
  3015. eq(
  3016. diagnostic,
  3017. exec_lua(function()
  3018. return vim.diagnostic.match(
  3019. msg,
  3020. '^(%w+): [^:]+:(%d+):(%d+):(.+)$',
  3021. { 'severity', 'lnum', 'col', 'message' }
  3022. )
  3023. end)
  3024. )
  3025. end)
  3026. it('returns nil if the pattern fails to match', function()
  3027. eq(
  3028. nil,
  3029. exec_lua(function()
  3030. local msg = 'The answer to life, the universe, and everything is'
  3031. return vim.diagnostic.match(msg, 'This definitely will not match', {})
  3032. end)
  3033. )
  3034. end)
  3035. it('respects default values', function()
  3036. local msg = 'anna.txt:1:Happy families are all alike'
  3037. local diagnostic = {
  3038. severity = exec_lua [[return vim.diagnostic.severity.INFO]],
  3039. lnum = 0,
  3040. col = 0,
  3041. end_lnum = 0,
  3042. end_col = 0,
  3043. message = 'Happy families are all alike',
  3044. }
  3045. eq(
  3046. diagnostic,
  3047. exec_lua(function()
  3048. return vim.diagnostic.match(
  3049. msg,
  3050. '^[^:]+:(%d+):(.+)$',
  3051. { 'lnum', 'message' },
  3052. nil,
  3053. { severity = vim.diagnostic.severity.INFO }
  3054. )
  3055. end)
  3056. )
  3057. end)
  3058. it('accepts a severity map', function()
  3059. local msg = '46:FATAL:Et tu, Brute?'
  3060. local diagnostic = {
  3061. severity = exec_lua [[return vim.diagnostic.severity.ERROR]],
  3062. lnum = 45,
  3063. col = 0,
  3064. end_lnum = 45,
  3065. end_col = 0,
  3066. message = 'Et tu, Brute?',
  3067. }
  3068. eq(
  3069. diagnostic,
  3070. exec_lua(function()
  3071. return vim.diagnostic.match(
  3072. msg,
  3073. '^(%d+):(%w+):(.+)$',
  3074. { 'lnum', 'severity', 'message' },
  3075. { FATAL = vim.diagnostic.severity.ERROR }
  3076. )
  3077. end)
  3078. )
  3079. end)
  3080. end)
  3081. describe('toqflist() and fromqflist()', function()
  3082. it('works', function()
  3083. local result = exec_lua(function()
  3084. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  3085. _G.make_error('Error 1', 0, 1, 0, 1),
  3086. _G.make_error('Error 2', 1, 1, 1, 1),
  3087. _G.make_warning('Warning', 2, 2, 2, 2),
  3088. })
  3089. local diagnostics = vim.diagnostic.get(_G.diagnostic_bufnr)
  3090. vim.fn.setqflist(vim.diagnostic.toqflist(diagnostics))
  3091. local list = vim.fn.getqflist()
  3092. local new_diagnostics = vim.diagnostic.fromqflist(list)
  3093. -- Remove namespace since it isn't present in the return value of
  3094. -- fromlist()
  3095. for _, v in ipairs(diagnostics) do
  3096. v.namespace = nil
  3097. end
  3098. return { diagnostics, new_diagnostics }
  3099. end)
  3100. eq(result[1], result[2])
  3101. end)
  3102. end)
  3103. describe('handlers', function()
  3104. it('checks that a new handler is a table', function()
  3105. matches(
  3106. [[.*handler: expected table, got string.*]],
  3107. pcall_err(exec_lua, [[ vim.diagnostic.handlers.foo = "bar" ]])
  3108. )
  3109. matches(
  3110. [[.*handler: expected table, got function.*]],
  3111. pcall_err(exec_lua, [[ vim.diagnostic.handlers.foo = function() end ]])
  3112. )
  3113. end)
  3114. it('can add new handlers', function()
  3115. eq(
  3116. true,
  3117. exec_lua(function()
  3118. local handler_called = false
  3119. vim.diagnostic.handlers.test = {
  3120. show = function(namespace, bufnr, diagnostics, opts)
  3121. assert(namespace == _G.diagnostic_ns)
  3122. assert(bufnr == _G.diagnostic_bufnr)
  3123. assert(#diagnostics == 1)
  3124. assert(opts.test.some_opt == 42)
  3125. handler_called = true
  3126. end,
  3127. }
  3128. vim.diagnostic.config({ test = { some_opt = 42 } })
  3129. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  3130. _G.make_warning('Warning', 0, 0, 0, 0),
  3131. })
  3132. return handler_called
  3133. end)
  3134. )
  3135. end)
  3136. it('can disable handlers by setting the corresponding option to false', function()
  3137. eq(
  3138. false,
  3139. exec_lua(function()
  3140. local handler_called = false
  3141. vim.diagnostic.handlers.test = {
  3142. show = function(_, _, _, _)
  3143. handler_called = true
  3144. end,
  3145. }
  3146. vim.diagnostic.config({ test = false })
  3147. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  3148. _G.make_warning('Warning', 0, 0, 0, 0),
  3149. })
  3150. return handler_called
  3151. end)
  3152. )
  3153. end)
  3154. it("always calls a handler's hide function if defined", function()
  3155. eq(
  3156. { false, true },
  3157. exec_lua(function()
  3158. local hide_called = false
  3159. local show_called = false
  3160. vim.diagnostic.handlers.test = {
  3161. show = function(_, _, _, _)
  3162. show_called = true
  3163. end,
  3164. hide = function(namespace, bufnr)
  3165. assert(namespace == _G.diagnostic_ns)
  3166. assert(bufnr == _G.diagnostic_bufnr)
  3167. hide_called = true
  3168. end,
  3169. }
  3170. vim.diagnostic.config({ test = false })
  3171. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  3172. _G.make_warning('Warning', 0, 0, 0, 0),
  3173. })
  3174. vim.diagnostic.hide(_G.diagnostic_ns, _G.diagnostic_bufnr)
  3175. return { show_called, hide_called }
  3176. end)
  3177. )
  3178. end)
  3179. it('triggers the autocommand when diagnostics are set', function()
  3180. eq(
  3181. { true, true },
  3182. exec_lua(function()
  3183. -- Set a different buffer as current to test that <abuf> is being set properly in
  3184. -- DiagnosticChanged callbacks
  3185. local tmp = vim.api.nvim_create_buf(false, true)
  3186. vim.api.nvim_set_current_buf(tmp)
  3187. local triggered = {}
  3188. vim.api.nvim_create_autocmd('DiagnosticChanged', {
  3189. callback = function(args)
  3190. triggered = { args.buf, #args.data.diagnostics }
  3191. end,
  3192. })
  3193. vim.api.nvim_buf_set_name(_G.diagnostic_bufnr, 'test | test')
  3194. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  3195. _G.make_error('Diagnostic', 0, 0, 0, 0),
  3196. })
  3197. return {
  3198. triggered[1] == _G.diagnostic_bufnr,
  3199. triggered[2] == 1,
  3200. }
  3201. end)
  3202. )
  3203. end)
  3204. it('triggers the autocommand when diagnostics are cleared', function()
  3205. eq(
  3206. true,
  3207. exec_lua(function()
  3208. local tmp = vim.api.nvim_create_buf(false, true)
  3209. vim.api.nvim_set_current_buf(tmp)
  3210. vim.g.diagnostic_autocmd_triggered = 0
  3211. vim.cmd(
  3212. 'autocmd DiagnosticChanged * let g:diagnostic_autocmd_triggered = +expand("<abuf>")'
  3213. )
  3214. vim.api.nvim_buf_set_name(_G.diagnostic_bufnr, 'test | test')
  3215. vim.diagnostic.reset(_G.diagnostic_ns, _G.diagnostic_bufnr)
  3216. return vim.g.diagnostic_autocmd_triggered == _G.diagnostic_bufnr
  3217. end)
  3218. )
  3219. end)
  3220. it('is_enabled', function()
  3221. eq(
  3222. { false, false, false, false, false },
  3223. exec_lua(function()
  3224. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  3225. _G.make_error('Diagnostic #1', 1, 1, 1, 1),
  3226. })
  3227. vim.api.nvim_set_current_buf(_G.diagnostic_bufnr)
  3228. vim.diagnostic.enable(false)
  3229. return {
  3230. vim.diagnostic.is_enabled(),
  3231. vim.diagnostic.is_enabled { bufnr = 0 },
  3232. vim.diagnostic.is_enabled { bufnr = _G.diagnostic_bufnr },
  3233. vim.diagnostic.is_enabled { bufnr = _G.diagnostic_bufnr, ns_id = _G.diagnostic_ns },
  3234. vim.diagnostic.is_enabled { bufnr = 0, ns_id = _G.diagnostic_ns },
  3235. }
  3236. end)
  3237. )
  3238. eq(
  3239. { true, true, true, true, true },
  3240. exec_lua(function()
  3241. vim.diagnostic.enable()
  3242. return {
  3243. vim.diagnostic.is_enabled(),
  3244. vim.diagnostic.is_enabled { bufnr = 0 },
  3245. vim.diagnostic.is_enabled { bufnr = _G.diagnostic_bufnr },
  3246. vim.diagnostic.is_enabled { bufnr = _G.diagnostic_bufnr, ns_id = _G.diagnostic_ns },
  3247. vim.diagnostic.is_enabled { bufnr = 0, ns_id = _G.diagnostic_ns },
  3248. }
  3249. end)
  3250. )
  3251. end)
  3252. it('is_disabled (deprecated)', function()
  3253. eq(
  3254. { true, true, true, true },
  3255. exec_lua(function()
  3256. vim.diagnostic.set(_G.diagnostic_ns, _G.diagnostic_bufnr, {
  3257. _G.make_error('Diagnostic #1', 1, 1, 1, 1),
  3258. })
  3259. vim.api.nvim_set_current_buf(_G.diagnostic_bufnr)
  3260. vim.diagnostic.disable()
  3261. return {
  3262. vim.diagnostic.is_disabled(),
  3263. vim.diagnostic.is_disabled(_G.diagnostic_bufnr),
  3264. vim.diagnostic.is_disabled(_G.diagnostic_bufnr, _G.diagnostic_ns),
  3265. vim.diagnostic.is_disabled(0, _G.diagnostic_ns),
  3266. }
  3267. end)
  3268. )
  3269. eq(
  3270. { false, false, false, false },
  3271. exec_lua(function()
  3272. vim.diagnostic.enable()
  3273. return {
  3274. vim.diagnostic.is_disabled(),
  3275. vim.diagnostic.is_disabled(_G.diagnostic_bufnr),
  3276. vim.diagnostic.is_disabled(_G.diagnostic_bufnr, _G.diagnostic_ns),
  3277. vim.diagnostic.is_disabled(0, _G.diagnostic_ns),
  3278. }
  3279. end)
  3280. )
  3281. end)
  3282. end)
  3283. end)