diff --git a/interop.v b/interop.v index b114775c..478e17ab 100644 --- a/interop.v +++ b/interop.v @@ -345,32 +345,46 @@ fn (mut app App) run_v_line_info(method Method, path string, line_info string) R } .hover { result_tmp := json.decode(JsonVarAC, x.output) or { JsonVarAC{} } - // Extract vdoc comment via cross-file search (current file → open files - // → project dir → vlib/builtin → imported stdlib modules). + // Extract vdoc comment via cross-file search as a fallback when the + // compiler does not provide documentation. mut doc := '' file_content := app.open_files[path] or { app.text } file_lines := file_content.split_into_lines() // line_info format for hover is "line:col" (1-based line, 0-based col) info_parts := line_info.split(':') + mut cursor_symbol := '' if info_parts.len >= 2 { cursor_line := info_parts[0].int() - 1 cursor_col := info_parts[1].int() if cursor_line >= 0 && cursor_line < file_lines.len { - symbol := get_word_at_col(file_lines[cursor_line], cursor_col) - if symbol != '' { - doc = app.find_doc_comment_for_symbol(symbol, file_lines, path) + cursor_symbol = get_word_at_col(file_lines[cursor_line], cursor_col) + if cursor_symbol != '' { + doc = app.find_doc_comment_for_symbol(cursor_symbol, file_lines, + path) } } } if result_tmp.details.len > 0 { detail := result_tmp.details[0] + // When the compiler returned a named symbol (e.g. hovering over the `fn` + // keyword resolves to the function's label), re-run the doc search using + // the compiler's label so we pick up the correct vdoc comment. + if doc == '' && detail.label != '' && detail.label != cursor_symbol { + doc = app.find_doc_comment_for_symbol(detail.label, file_lines, path) + } // Prefer compiler-provided documentation over our extracted vdoc if detail.documentation != '' { doc = detail.documentation } - mut content := '```v\n${detail.detail}\n```' + // Use the full declaration from the compiler when available; + // fall back to detail (return type) if declaration is absent. + sig := if detail.declaration != '' { detail.declaration } else { detail.detail } + mut content := if sig != '' { '```v\n${sig}\n```' } else { '' } if doc != '' { - content += '\n\n${doc}' + if content != '' { + content += '\n\n' + } + content += doc } result = Hover{ contents: MarkupContent{ diff --git a/lsp.v b/lsp.v index 71672fb6..5d43cf84 100644 --- a/lsp.v +++ b/lsp.v @@ -107,6 +107,7 @@ struct Detail { kind int // The type of item (e.g., Method, Function, Field) label string // The name of the completion item detail string // Additional info like the function signature or return type + declaration string // Full fn declaration, e.g. "fn greet(name string) string" documentation string // The documentation for the item insert_text ?string @[json: 'insertText'] insert_text_format ?int @[json: 'insertTextFormat'] // 1 for PlainText, 2 for Snippet