Repository: neovim
Issue: docs: `:h diagnostic-handlers-example` - sign handler can pass outdated diagnostics to original handler
Labels: bug,documentation,diagnostic

### Problem

I use the custom sign handler from `:h diagnostic-handlers-example`. It can fail on external changes e.g. `git stash`:
```
Error executing vim.schedule lua callback: .../nvim-from-src/share/nvim/runtime/lua/vim/diagnostic.lua:1150: Invalid 'line': out of range
stack traceback:
        [C]: in function 'nvim_buf_set_extmark'
        .../nvim-from-src/share/nvim/runtime/lua/vim/diagnostic.lua:1150: in function 'show'
        ...current/2024-01-25-20.16.00-outdated-diag-signs/init.lua:19: in function 'show'
        .../nvim-from-src/share/nvim/runtime/lua/vim/diagnostic.lua:1499: in function 'show'
        ...tgx/tmp/nvim-from-src/share/nvim/runtime/lua/vim/lsp.lua:374: in function <...tgx/tmp/nvim-from-src/share/nvim/runtime/lua/vim/lsp.lua:369>
Press ENTER or type command to continue
```


### Steps to reproduce

**Beware: it overrides existing local files `copy.lua` and `copy-truncated.lua` without any prompt. Please review `init.lua` contents before use!**

init.lua:
```lua
vim.opt.number = true

local ns = vim.api.nvim_create_namespace('diag')
local orig_signs_handler = vim.diagnostic.handlers.signs

vim.diagnostic.handlers.signs = {
  show = function(_, bufnr, _, opts)
    local diagnostics = vim.diagnostic.get(bufnr)

    local max_severity_per_line = {}
    for _, d in pairs(diagnostics) do
      local m = max_severity_per_line[d.lnum]
      if not m or d.severity < m.severity then
        max_severity_per_line[d.lnum] = d
      end
    end

    local filtered_diagnostics = vim.tbl_values(max_severity_per_line)
    orig_signs_handler.show(ns, bufnr, filtered_diagnostics, opts)
  end,
  hide = function(_, bufnr)
    orig_signs_handler.hide(ns, bufnr)
  end,
}

vim.api.nvim_create_autocmd('FileType', {
  pattern = 'lua',
  callback = function (args)
    vim.lsp.start({
      name = 'luals',
      cmd = {'lua-language-server'},
      root_dir = vim.uv.cwd(),
      single_file_support = true,
      log_level = vim.lsp.protocol.MessageType.Warning,
    })
  end
})

local origPath = vim.api.nvim_get_runtime_file('lua/vim/termcap.lua', false)[1]
local newPath = 'copy-534534535.lua'
local backupTruncated = 'copy-truncated-48560834573.lua'

local function truncateFromEnd(file, linesToTruncate)
  vim.cmd.edit(file)

  local lastLine = vim.fn.line('$')
  vim.api.nvim_win_set_cursor(0, {lastLine, 1})
  while lastLine - vim.fn.line('$') < linesToTruncate do
    vim.api.nvim_del_current_line()
  end
  vim.cmd.write({mods = {silent = true}})
  vim.api.nvim_buf_delete(0, {})
end

local function overwriteWithTruncated()
  vim.uv.fs_copyfile(backupTruncated, newPath)
  vim.cmd.checktime()
end

vim.api.nvim_create_autocmd('UIEnter', {
  once = true,
  callback = function ()
    vim.schedule(function ()
      vim.uv.fs_copyfile(origPath, newPath)
      vim.uv.fs_copyfile(origPath, backupTruncated)
      truncateFromEnd(backupTruncated, 20)
      vim.cmd.edit(newPath)
      vim.api.nvim_win_set_cursor(0, {vim.fn.line('$'), 1})
      vim.diagnostic.set(ns, vim.api.nvim_get_current_buf(), {
        {
          lnum = vim.fn.line('$'),
          col = 1,
          end_lnum = vim.fn.line('$'),
          end_col = 1,
          message = 'test diag',
        }
      })
    end)

  end,
})

vim.api.nvim_create_user_command('Truncate', overwriteWithTruncated, {nargs = 0})
```
- run
```sh
mkdir /tmp/new-nonexisting-directory
cd /tmp/new-nonexisting-directory
nvim -u init.lua
```
- wait for loading diagnostics from lua-ls or possibly edit the current buffer to get some diagnostics near the end line. 
![image](https://github.com/neovim/neovim/assets/11404453/e6e5ad45-6cf6-4204-90ab-a2289261e9cb)

- run `:Truncate`
- look for the following error
![image](https://github.com/neovim/neovim/assets/11404453/172756f4-3eed-46a8-a886-e57a8b86f2af)



### Expected behavior

We probably need to prevent outdated diagnostics from being sent on an external file reload. I have no idea if `on_reload` event can be used here.

### Neovim version (nvim -v)

v0.10.0-dev-2196+g1e0996b57

### Vim (not Nvim) behaves the same?

-

### Operating system/version

Debian Sid

### Terminal name/version

alacritty 0.13.1

### $TERM environment variable

alacritty

### Installation

from repo