diagnostic_spec.lua 113 KB

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