Skip to content

Commit

Permalink
Merge ec02a65 into 2cbc24d
Browse files Browse the repository at this point in the history
  • Loading branch information
sdankel authored Jun 26, 2024
2 parents 2cbc24d + ec02a65 commit 1794207
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 17 deletions.
14 changes: 12 additions & 2 deletions sway-lsp/benches/lsp_benchmarks/requests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ use lsp_types::{
CompletionResponse, DocumentSymbolResponse, Position, Range, TextDocumentContentChangeEvent,
TextDocumentIdentifier,
};
use sway_lsp::{capabilities, lsp_ext::OnEnterParams, utils::keyword_docs::KeywordDocs};
use sway_lsp::{
capabilities, config::LspClient, lsp_ext::OnEnterParams, utils::keyword_docs::KeywordDocs,
};
use tokio::runtime::Runtime;

fn benchmarks(c: &mut Criterion) {
Expand Down Expand Up @@ -37,7 +39,15 @@ fn benchmarks(c: &mut Criterion) {
});

c.bench_function("hover", |b| {
b.iter(|| capabilities::hover::hover_data(session.clone(), &keyword_docs, &uri, position))
b.iter(|| {
capabilities::hover::hover_data(
session.clone(),
&keyword_docs,
&uri,
position,
LspClient::default(),
)
})
});

c.bench_function("highlight", |b| {
Expand Down
19 changes: 14 additions & 5 deletions sway-lsp/src/capabilities/hover/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
pub(crate) mod hover_link_contents;

use self::hover_link_contents::HoverLinkContents;
use crate::config::LspClient;
use crate::{
core::{
session::Session,
Expand All @@ -9,23 +11,21 @@ use crate::{
attributes::doc_comment_attributes, keyword_docs::KeywordDocs, markdown, markup::Markup,
},
};
use lsp_types::{self, Position, Url};
use std::sync::Arc;
use sway_core::{
language::{ty, Visibility},
Engines, TypeId,
};

use lsp_types::{self, Position, Url};
use sway_types::{Span, Spanned};

use self::hover_link_contents::HoverLinkContents;

/// Extracts the hover information for a token at the current position.
pub fn hover_data(
session: Arc<Session>,
keyword_docs: &KeywordDocs,
url: &Url,
position: Position,
client_config: LspClient,
) -> Option<lsp_types::Hover> {
let t = session.token_map().token_at_position(url, position)?;
let (ident, token) = t.pair();
Expand Down Expand Up @@ -60,11 +60,18 @@ pub fn hover_data(
&session.engines.read(),
decl_token,
&decl_ident.name,
client_config.clone(),
)
}
// The `TypeInfo` of the token does not contain an `Ident`. In this case,
// we use the `Ident` of the token itself.
None => hover_format(session.clone(), &session.engines.read(), token, &ident.name),
None => hover_format(
session.clone(),
&session.engines.read(),
token,
&ident.name,
client_config.clone(),
),
};

Some(lsp_types::Hover {
Expand Down Expand Up @@ -122,6 +129,7 @@ fn hover_format(
engines: &Engines,
token: &Token,
ident_name: &str,
client_config: LspClient,
) -> lsp_types::HoverContents {
let decl_engine = engines.de();
let doc_comment = format_doc_attributes(engines, token);
Expand Down Expand Up @@ -219,6 +227,7 @@ fn hover_format(
engines.se(),
&hover_link_contents.related_types,
&hover_link_contents.implementations,
client_config,
);

lsp_types::HoverContents::Markup(markup_content(&content))
Expand Down
11 changes: 11 additions & 0 deletions sway-lsp/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ use tracing::metadata::LevelFilter;
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Default)]
#[serde(rename_all = "camelCase")]
pub struct Config {
#[serde(default)]
pub client: LspClient,
#[serde(default)]
pub debug: DebugConfig,
#[serde(default)]
Expand All @@ -20,6 +22,15 @@ pub struct Config {
pub garbage_collection: GarbageCollectionConfig,
}

#[derive(Clone, Default, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum LspClient {
VsCode,
#[serde(other)]
#[default]
Other,
}

#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Default)]
struct TraceConfig {}

Expand Down
1 change: 1 addition & 0 deletions sway-lsp/src/handlers/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ pub async fn handle_hover(
&state.keyword_docs,
&uri,
position,
state.config.read().client.clone(),
))
}
Err(err) => {
Expand Down
11 changes: 8 additions & 3 deletions sway-lsp/src/utils/markup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
//! markdown for this purpose.
//! Modified from rust-analyzer.
use crate::{
capabilities::hover::hover_link_contents::RelatedType, core::token::get_range_from_span,
utils::document::get_url_from_span,
capabilities::hover::hover_link_contents::RelatedType, config::LspClient,
core::token::get_range_from_span, utils::document::get_url_from_span,
};
use serde_json::{json, Value};
use std::fmt::{self};
Expand Down Expand Up @@ -56,13 +56,18 @@ impl Markup {
}

/// Adds go-to links if there are any related types, a link to view implementations if there are any,
/// or nothing if there are no related types or implementations.
/// or nothing if there are no related types or implementations. Only adds links for VSCode clients.
pub fn maybe_add_links(
self,
source_engine: &SourceEngine,
related_types: &[RelatedType],
implementations: &[Span],
client_config: LspClient,
) -> Self {
if client_config != LspClient::VsCode {
return self;
}

if related_types.is_empty() {
let locations = implementations
.iter()
Expand Down
35 changes: 28 additions & 7 deletions sway-lsp/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::integration::{code_actions, lsp};
use lsp_types::*;
use std::{fs, path::PathBuf};
use sway_lsp::{
config::LspClient,
handlers::{notification, request},
server_state::ServerState,
};
Expand Down Expand Up @@ -1635,9 +1636,10 @@ fn hover_docs_for_consts() {
}

#[test]
fn hover_docs_for_functions() {
fn hover_docs_for_functions_vscode() {
run_async!({
let server = ServerState::default();
server.config.write().client = LspClient::VsCode;
let uri = open(
&server,
test_fixtures_dir().join("tokens/functions/src/main.sw"),
Expand Down Expand Up @@ -1779,17 +1781,18 @@ fn hover_docs_with_code_examples() {
}

#[test]
fn hover_docs_for_self_keywords() {
fn hover_docs_for_self_keywords_vscode() {
run_async!({
let server = ServerState::default();
server.config.write().client = LspClient::VsCode;
let uri = open(&server, test_fixtures_dir().join("completion/src/main.sw")).await;

let mut hover = HoverDocumentation {
req_uri: &uri,
req_line: 11,
req_char: 13,
documentation: vec!["\n```sway\nself\n```\n\n---\n\n The receiver of a method, or the current module.\n\n `self` is used in two situations: referencing the current module and marking\n the receiver of a method.\n\n In paths, `self` can be used to refer to the current module, either in a\n [`use`] statement or in a path to access an element:\n\n ```sway\n use std::contract_id::{self, ContractId};\n ```\n\n Is functionally the same as:\n\n ```sway\n use std::contract_id;\n use std::contract_id::ContractId;\n ```\n\n `self` as the current receiver for a method allows to omit the parameter\n type most of the time. With the exception of this particularity, `self` is\n used much like any other parameter:\n\n ```sway\n struct Foo(u32);\n\n impl Foo {\n // No `self`.\n fn new() -> Self {\n Self(0)\n }\n\n // Borrowing `self`.\n fn value(&self) -> u32 {\n self.0\n }\n\n // Updating `self` mutably.\n fn clear(ref mut self) {\n self.0 = 0\n }\n }\n ```"],
};
req_uri: &uri,
req_line: 11,
req_char: 13,
documentation: vec!["\n```sway\nself\n```\n\n---\n\n The receiver of a method, or the current module.\n\n `self` is used in two situations: referencing the current module and marking\n the receiver of a method.\n\n In paths, `self` can be used to refer to the current module, either in a\n [`use`] statement or in a path to access an element:\n\n ```sway\n use std::contract_id::{self, ContractId};\n ```\n\n Is functionally the same as:\n\n ```sway\n use std::contract_id;\n use std::contract_id::ContractId;\n ```\n\n `self` as the current receiver for a method allows to omit the parameter\n type most of the time. With the exception of this particularity, `self` is\n used much like any other parameter:\n\n ```sway\n struct Foo(u32);\n\n impl Foo {\n // No `self`.\n fn new() -> Self {\n Self(0)\n }\n\n // Borrowing `self`.\n fn value(&self) -> u32 {\n self.0\n }\n\n // Updating `self` mutably.\n fn clear(ref mut self) {\n self.0 = 0\n }\n }\n ```"],
};

lsp::hover_request(&server, &hover).await;
hover.req_char = 24;
Expand All @@ -1799,6 +1802,24 @@ fn hover_docs_for_self_keywords() {
});
}

#[test]
fn hover_docs_for_self_keywords() {
run_async!({
let server = ServerState::default();
let uri = open(&server, test_fixtures_dir().join("completion/src/main.sw")).await;

let hover = HoverDocumentation {
req_uri: &uri,
req_line: 11,
req_char: 13,
documentation: vec!["\n```sway\nself\n```\n\n---\n\n The receiver of a method, or the current module.\n\n `self` is used in two situations: referencing the current module and marking\n the receiver of a method.\n\n In paths, `self` can be used to refer to the current module, either in a\n [`use`] statement or in a path to access an element:\n\n ```sway\n use std::contract_id::{self, ContractId};\n ```\n\n Is functionally the same as:\n\n ```sway\n use std::contract_id;\n use std::contract_id::ContractId;\n ```\n\n `self` as the current receiver for a method allows to omit the parameter\n type most of the time. With the exception of this particularity, `self` is\n used much like any other parameter:\n\n ```sway\n struct Foo(u32);\n\n impl Foo {\n // No `self`.\n fn new() -> Self {\n Self(0)\n }\n\n // Borrowing `self`.\n fn value(&self) -> u32 {\n self.0\n }\n\n // Updating `self` mutably.\n fn clear(ref mut self) {\n self.0 = 0\n }\n }\n ```"],
};

lsp::hover_request(&server, &hover).await;
let _ = server.shutdown_server();
});
}

#[test]
fn hover_docs_for_boolean_keywords() {
run_async!({
Expand Down

0 comments on commit 1794207

Please sign in to comment.