Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

👍 show constraint error warning #404

Merged
merged 3 commits into from
Aug 7, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 24 additions & 5 deletions autoload/denops/_internal/server/proc.vim
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const s:SCRIPT = denops#_internal#path#script(['@denops-private', 'cli.ts'])
const s:LAST_ERROR_LINES = 20

let s:job = v:null
let s:stopped_on_purpose = 0
Expand Down Expand Up @@ -59,13 +60,13 @@ function! s:start(options) abort
if g:denops#deno_dir isnot# v:null
let l:env['DENO_DIR'] = g:denops#deno_dir
endif
let l:store = {'prepared': 0}
let l:store = {'prepared': 0, 'stderr': []}
let s:stopped_on_purpose = 0
let s:job = denops#_internal#job#start(l:args, {
\ 'env': l:env,
\ 'on_stdout': { _job, data, _event -> s:on_stdout(l:store, data) },
\ 'on_stderr': { _job, data, _event -> s:on_stderr(data) },
\ 'on_exit': { _job, status, _event -> s:on_exit(a:options, status) },
\ 'on_stderr': { _job, data, _event -> s:on_stderr(l:store, data) },
\ 'on_exit': { _job, status, _event -> s:on_exit(l:store, a:options, status) },
\})
call denops#_internal#echo#debug(printf('Server started: %s', l:args))
call denops#_internal#event#emit('DenopsSystemProcessStarted')
Expand All @@ -84,18 +85,36 @@ function! s:on_stdout(store, data) abort
call denops#_internal#event#emit(printf('DenopsSystemProcessListen:%s', l:addr))
endfunction

function! s:on_stderr(data) abort
function! s:on_stderr(store, data) abort
echohl ErrorMsg
for l:line in split(a:data, '\n')
echomsg printf('[denops] %s', substitute(l:line, '\t', ' ', 'g'))
endfor
echohl None
if a:store.stderr->add(a:data)->len() > s:LAST_ERROR_LINES
eval a:store.stderr->remove(0, -(s:LAST_ERROR_LINES + 1))
endif
Milly marked this conversation as resolved.
Show resolved Hide resolved
endfunction

function! s:on_exit(options, status) abort
function! s:on_exit(store, options, status) abort
let s:job = v:null
call denops#_internal#echo#debug(printf('Server stopped: %s', a:status))
call denops#_internal#event#emit(printf('DenopsSystemProcessStopped:%s', a:status))
const l:last_error = a:store.stderr->join("\n")
Milly marked this conversation as resolved.
Show resolved Hide resolved
if l:last_error =~# 'Could not find constraint\|Could not find version of'
" Show a warning message when Deno module cache issue is detected
" https://github.com/vim-denops/denops.vim/issues/358
call denops#_internal#echo#warn(repeat('*', 80))
call denops#_internal#echo#warn('Deno module cache issue is detected.')
call denops#_internal#echo#warn(
\ "Execute 'call denops#cache#update(#{reload: v:true})' and restart Vim/Neovim."
\ )
call denops#_internal#echo#warn(
\ 'See https://github.com/vim-denops/denops.vim/issues/358 for more detail.'
\ )
call denops#_internal#echo#warn(repeat('*', 80))
return
endif
if s:job isnot# v:null || !a:options.restart_on_exit || s:stopped_on_purpose || s:exiting
return
endif
Expand Down
3 changes: 2 additions & 1 deletion deno.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
"apply:supported-versions": "deno run --allow-read --allow-write .scripts/apply_supported_versions.ts"
},
"exclude": [
".coverage/"
".coverage/",
"tests/denops/testdata/no_check/"
],
// NOTE: Import maps should only be used from test modules.
"imports": {
Expand Down
57 changes: 57 additions & 0 deletions tests/denops/runtime/functions/server_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import {
assertEquals,
assertFalse,
assertMatch,
assertNotMatch,
assertRejects,
assertStringIncludes,
} from "jsr:@std/assert@^1.0.1";
import { delay } from "jsr:@std/async@^0.224.0/delay";
import { AsyncDisposableStack } from "jsr:@nick/dispose@^1.1.0/async-disposable-stack";
Expand Down Expand Up @@ -489,6 +491,56 @@ testHost({
);
});
});

await t.step(
"if the server is stopped with a constraint error",
async (t) => {
await using stack = new AsyncDisposableStack();
stack.defer(async () => {
await host.call("denops#server#stop");
await wait(
() => host.call("eval", "denops#server#status() ==# 'stopped'"),
);
});

outputs = [];
await host.call("execute", [
"silent! unlet g:__test_denops_process_stopped_fired",
`let g:denops#server#deno_args = ['${
resolve("no_check/cli_error_on_issue_401.ts")
}']`,
"let g:denops#server#restart_delay = 1000",
"let g:denops#server#restart_interval = 10000",
"let g:denops#server#restart_threshold = 1",
"call denops#server#start()",
], "");

await t.step("fires DenopsProcessStopped", async () => {
await wait(() =>
host.call("exists", "g:__test_denops_process_stopped_fired")
);
});

await t.step("changes status to 'stopped' asynchronously", async () => {
assertEquals(await host.call("denops#server#status"), "stopped");
});

await t.step("outputs warning message", async () => {
await delay(MESSAGE_DELAY);
assertStringIncludes(
outputs.join(""),
"Execute 'call denops#cache#update(#{reload: v:true})' and restart Vim/Neovim.",
);
});

await t.step("does not restart the server", () => {
assertNotMatch(
outputs.join(""),
/Server stopped.*Restarting/,
);
});
},
);
},
});

Expand Down Expand Up @@ -1275,3 +1327,8 @@ testHost({
});
},
});

/** Resolve testdata script URL. */
function resolve(path: string): string {
return new URL(`../../testdata/${path}`, import.meta.url).href;
}
1 change: 1 addition & 0 deletions tests/denops/testdata/no_check/cli_error_on_issue_401.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import * as _ from "jsr:@std/[email protected]";
Milly marked this conversation as resolved.
Show resolved Hide resolved