diagnostic_spec.lua 127 KB

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