Skip to content

Commit

Permalink
LSP: Refactor the API (FuelLabs#3463)
Browse files Browse the repository at this point in the history
No new methods or functionality have been added. This PR just cleans up
the API so everything is a little more obvious and also improves the
documentation.

closes FuelLabs#3459
  • Loading branch information
JoshuaBatty authored Dec 8, 2022
1 parent 1b75006 commit 80aa366
Show file tree
Hide file tree
Showing 26 changed files with 515 additions and 487 deletions.
27 changes: 23 additions & 4 deletions sway-lsp/src/capabilities/completion.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use crate::core::token::{SymbolKind, TokenMap};
use crate::utils::token::is_initial_declaration;
use crate::core::{
token::{AstToken, SymbolKind, Token, TypedAstToken},
token_map::TokenMap,
};
use tower_lsp::lsp_types::{CompletionItem, CompletionItemKind};

pub fn to_completion_items(token_map: &TokenMap) -> Vec<CompletionItem> {
pub(crate) fn to_completion_items(token_map: &TokenMap) -> Vec<CompletionItem> {
let mut completion_items = vec![];

for item in token_map.iter() {
Expand All @@ -21,7 +23,7 @@ pub fn to_completion_items(token_map: &TokenMap) -> Vec<CompletionItem> {
}

/// Given a `SymbolKind`, return the `lsp_types::CompletionItemKind` that corresponds to it.
pub(crate) fn completion_item_kind(symbol_kind: &SymbolKind) -> Option<CompletionItemKind> {
pub fn completion_item_kind(symbol_kind: &SymbolKind) -> Option<CompletionItemKind> {
match symbol_kind {
SymbolKind::Field => Some(CompletionItemKind::FIELD),
SymbolKind::BuiltinType => Some(CompletionItemKind::TYPE_PARAMETER),
Expand All @@ -42,3 +44,20 @@ pub(crate) fn completion_item_kind(symbol_kind: &SymbolKind) -> Option<Completio
SymbolKind::Unknown => None,
}
}

fn is_initial_declaration(token_type: &Token) -> bool {
match &token_type.typed {
Some(typed_ast_token) => {
matches!(
typed_ast_token,
TypedAstToken::TypedDeclaration(_) | TypedAstToken::TypedFunctionDeclaration(_)
)
}
None => {
matches!(
token_type.parsed,
AstToken::Declaration(_) | AstToken::FunctionDeclaration(_)
)
}
}
}
31 changes: 15 additions & 16 deletions sway-lsp/src/capabilities/document_symbol.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::core::token::{SymbolKind, Token};
use crate::utils::common::get_range_from_span;
use crate::core::token::{get_range_from_span, SymbolKind, Token};
use sway_types::{Ident, Spanned};
use tower_lsp::lsp_types::{self, Location, SymbolInformation, Url};

Expand All @@ -17,20 +16,6 @@ where
symbols
}

#[allow(warnings)]
// TODO: the "deprecated: None" field is deprecated according to this library
fn symbol_info(ident: &Ident, token: &Token, url: Url) -> SymbolInformation {
let range = get_range_from_span(&ident.span());
SymbolInformation {
name: ident.as_str().to_string(),
kind: symbol_kind(&token.kind),
location: Location::new(url, range),
tags: None,
container_name: None,
deprecated: None,
}
}

/// Given a `token::SymbolKind`, return the `lsp_types::SymbolKind` that corresponds to it.
pub(crate) fn symbol_kind(symbol_kind: &SymbolKind) -> lsp_types::SymbolKind {
match symbol_kind {
Expand All @@ -53,3 +38,17 @@ pub(crate) fn symbol_kind(symbol_kind: &SymbolKind) -> lsp_types::SymbolKind {
| SymbolKind::Unknown => lsp_types::SymbolKind::VARIABLE,
}
}

#[allow(warnings)]
// TODO: the "deprecated: None" field is deprecated according to this library
fn symbol_info(ident: &Ident, token: &Token, url: Url) -> SymbolInformation {
let range = get_range_from_span(&ident.span());
SymbolInformation {
name: ident.as_str().to_string(),
kind: symbol_kind(&token.kind),
location: Location::new(url, range),
tags: None,
container_name: None,
deprecated: None,
}
}
3 changes: 1 addition & 2 deletions sway-lsp/src/capabilities/formatting.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
use crate::error::LanguageServerError;
use std::sync::Arc;
use swayfmt::Formatter;
use tower_lsp::lsp_types::{Position, Range, TextEdit};

use crate::error::LanguageServerError;

pub fn get_page_text_edit(
text: Arc<str>,
formatter: &mut Formatter,
Expand Down
11 changes: 4 additions & 7 deletions sway-lsp/src/capabilities/hover.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
use crate::{
core::{
session::Session,
token::{Token, TypedAstToken},
},
utils::{
attributes::doc_attributes, common::get_range_from_span, markdown, markup::Markup,
token::to_ident_key,
token::{get_range_from_span, to_ident_key, Token, TypedAstToken},
},
utils::{attributes::doc_attributes, markdown, markup::Markup},
};
use std::sync::Arc;
use sway_core::{
Expand All @@ -19,9 +16,9 @@ use tower_lsp::lsp_types::{self, Position, Url};

/// Extracts the hover information for a token at the current position.
pub fn hover_data(session: Arc<Session>, url: Url, position: Position) -> Option<lsp_types::Hover> {
let (ident, token) = session.token_at_position(&url, position)?;
let (ident, token) = session.token_map().token_at_position(&url, position)?;
let range = get_range_from_span(&ident.span());
let (decl_ident, decl_token) = match session.declared_token_ident(&token) {
let (decl_ident, decl_token) = match token.declared_token_ident(&session.type_engine.read()) {
Some(decl_ident) => {
let decl_token = session
.token_map()
Expand Down
12 changes: 8 additions & 4 deletions sway-lsp/src/capabilities/inlay_hints.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use crate::{
core::{config::InlayHintsConfig, session::Session, token::TypedAstToken},
utils::common::get_range_from_span,
config::InlayHintsConfig,
core::{
session::Session,
token::{get_range_from_span, TypedAstToken},
},
};
use std::sync::Arc;
use sway_core::{language::ty::TyDeclaration, type_system::TypeInfo};
Expand Down Expand Up @@ -38,6 +41,7 @@ pub(crate) fn inlay_hints(
let type_engine = session.type_engine.read();

let hints: Vec<lsp_types::InlayHint> = session
.token_map()
.tokens_for_file(uri)
.filter_map(|(_, token)| {
token.typed.as_ref().and_then(|t| match t {
Expand Down Expand Up @@ -65,7 +69,7 @@ pub(crate) fn inlay_hints(
}
})
.map(|var| {
let range = crate::utils::common::get_range_from_span(&var.name.span());
let range = get_range_from_span(&var.name.span());
let kind = InlayKind::TypeHint;
let label = format!("{}", type_engine.help_out(var.type_ascription));
let inlay_hint = InlayHint { range, kind, label };
Expand All @@ -76,7 +80,7 @@ pub(crate) fn inlay_hints(
Some(hints)
}

pub(crate) fn inlay_hint(render_colons: bool, inlay_hint: InlayHint) -> lsp_types::InlayHint {
fn inlay_hint(render_colons: bool, inlay_hint: InlayHint) -> lsp_types::InlayHint {
lsp_types::InlayHint {
position: match inlay_hint.kind {
// after annotated thing
Expand Down
16 changes: 10 additions & 6 deletions sway-lsp/src/capabilities/rename.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,26 @@
use crate::core::{
session::Session,
token::{get_range_from_span, AstToken},
};
use std::collections::HashMap;
use std::sync::Arc;
use sway_types::Spanned;
use tower_lsp::lsp_types::{Position, PrepareRenameResponse, TextEdit, Url, WorkspaceEdit};

use crate::core::{session::Session, token::AstToken};
use crate::utils::common::get_range_from_span;

pub fn rename(
session: Arc<Session>,
new_name: String,
url: Url,
position: Position,
) -> Option<WorkspaceEdit> {
let (_, token) = session.token_at_position(&url, position)?;
let (_, token) = session.token_map().token_at_position(&url, position)?;
let mut edits = Vec::new();

// todo: currently only supports single file rename
for (ident, _) in session.all_references_of_token(&token) {
for (ident, _) in session
.token_map()
.all_references_of_token(&token, &session.type_engine.read())
{
let range = get_range_from_span(&ident.span());
edits.push(TextEdit::new(range, new_name.clone()));
}
Expand All @@ -33,7 +37,7 @@ pub fn prepare_rename(
url: Url,
position: Position,
) -> Option<PrepareRenameResponse> {
let (ident, token) = session.token_at_position(&url, position)?;
let (ident, token) = session.token_map().token_at_position(&url, position)?;
match token.parsed {
AstToken::Reassignment(_) => None,
_ => Some(PrepareRenameResponse::RangeWithPlaceholder {
Expand Down
67 changes: 33 additions & 34 deletions sway-lsp/src/capabilities/semantic_tokens.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
use crate::core::{
session::Session,
token::{SymbolKind, Token},
token::{get_range_from_span, SymbolKind, Token},
};
use crate::utils::common::get_range_from_span;
use std::sync::{
atomic::{AtomicU32, Ordering},
Arc,
Expand All @@ -15,7 +14,7 @@ use tower_lsp::lsp_types::{

// https://github.com/microsoft/vscode-extension-samples/blob/5ae1f7787122812dcc84e37427ca90af5ee09f14/semantic-tokens-sample/vscode.proposed.d.ts#L71
pub fn semantic_tokens_full(session: Arc<Session>, url: &Url) -> Option<SemanticTokensResult> {
let tokens = session.tokens_for_file(url);
let tokens = session.token_map().tokens_for_file(url);

// The tokens need sorting by their span so each token is sequential
// If this step isn't done, then the bit offsets used for the lsp_types::SemanticToken are incorrect.
Expand All @@ -36,15 +35,15 @@ pub fn semantic_tokens_full(session: Arc<Session>, url: &Url) -> Option<Semantic
/// Tokens are encoded relative to each other.
///
/// This is taken from rust-analyzer which is also a direct port of <https://github.com/microsoft/vscode-languageserver-node/blob/f425af9de46a0187adb78ec8a46b9b2ce80c5412/server/src/sematicTokens.proposed.ts#L45>
pub(crate) struct SemanticTokensBuilder {
struct SemanticTokensBuilder {
id: String,
prev_line: u32,
prev_char: u32,
data: Vec<SemanticToken>,
}

impl SemanticTokensBuilder {
pub(crate) fn new(id: String) -> Self {
pub fn new(id: String) -> Self {
SemanticTokensBuilder {
id,
prev_line: 0,
Expand All @@ -54,7 +53,7 @@ impl SemanticTokensBuilder {
}

/// Push a new token onto the builder
pub(crate) fn push(&mut self, range: Range, token_index: u32, modifier_bitset: u32) {
pub fn push(&mut self, range: Range, token_index: u32, modifier_bitset: u32) {
let mut push_line = range.start.line as u32;
let mut push_char = range.start.character as u32;

Expand Down Expand Up @@ -82,15 +81,15 @@ impl SemanticTokensBuilder {
self.prev_char = range.start.character as u32;
}

pub(crate) fn build(self) -> SemanticTokens {
pub fn build(self) -> SemanticTokens {
SemanticTokens {
result_id: Some(self.id),
data: self.data,
}
}
}

pub(crate) fn semantic_tokens(tokens_sorted: &[(Span, Token)]) -> SemanticTokens {
pub fn semantic_tokens(tokens_sorted: &[(Span, Token)]) -> SemanticTokens {
static TOKEN_RESULT_COUNTER: AtomicU32 = AtomicU32::new(1);
let id = TOKEN_RESULT_COUNTER
.fetch_add(1, Ordering::SeqCst)
Expand All @@ -109,32 +108,6 @@ pub(crate) fn semantic_tokens(tokens_sorted: &[(Span, Token)]) -> SemanticTokens
builder.build()
}

/// Get the semantic token type from the symbol kind.
fn semantic_token_type(kind: &SymbolKind) -> SemanticTokenType {
match kind {
SymbolKind::Field => SemanticTokenType::PROPERTY,
SymbolKind::ValueParam => SemanticTokenType::PARAMETER,
SymbolKind::Variable => SemanticTokenType::VARIABLE,
SymbolKind::Function => SemanticTokenType::FUNCTION,
SymbolKind::Const => SemanticTokenType::VARIABLE,
SymbolKind::Struct => SemanticTokenType::STRUCT,
SymbolKind::Enum => SemanticTokenType::ENUM,
SymbolKind::Variant => SemanticTokenType::ENUM_MEMBER,
SymbolKind::Trait => SemanticTokenType::INTERFACE,
SymbolKind::TypeParameter => SemanticTokenType::TYPE_PARAMETER,
SymbolKind::BoolLiteral => SemanticTokenType::new("boolean"),
SymbolKind::ByteLiteral | SymbolKind::NumericLiteral => SemanticTokenType::NUMBER,
SymbolKind::StringLiteral => SemanticTokenType::STRING,
SymbolKind::BuiltinType => SemanticTokenType::new("builtinType"),
SymbolKind::Module => SemanticTokenType::NAMESPACE,
SymbolKind::Unknown => SemanticTokenType::new("generic"),
}
}

pub(crate) fn type_index(ty: SemanticTokenType) -> u32 {
SUPPORTED_TYPES.iter().position(|it| *it == ty).unwrap() as u32
}

pub(crate) const SUPPORTED_TYPES: &[SemanticTokenType] = &[
SemanticTokenType::STRING,
SemanticTokenType::NUMBER,
Expand Down Expand Up @@ -169,3 +142,29 @@ pub(crate) const SUPPORTED_MODIFIERS: &[SemanticTokenModifier] = &[
// for symbols that are part of stdlib
SemanticTokenModifier::DEFAULT_LIBRARY,
];

/// Get the semantic token type from the symbol kind.
fn semantic_token_type(kind: &SymbolKind) -> SemanticTokenType {
match kind {
SymbolKind::Field => SemanticTokenType::PROPERTY,
SymbolKind::ValueParam => SemanticTokenType::PARAMETER,
SymbolKind::Variable => SemanticTokenType::VARIABLE,
SymbolKind::Function => SemanticTokenType::FUNCTION,
SymbolKind::Const => SemanticTokenType::VARIABLE,
SymbolKind::Struct => SemanticTokenType::STRUCT,
SymbolKind::Enum => SemanticTokenType::ENUM,
SymbolKind::Variant => SemanticTokenType::ENUM_MEMBER,
SymbolKind::Trait => SemanticTokenType::INTERFACE,
SymbolKind::TypeParameter => SemanticTokenType::TYPE_PARAMETER,
SymbolKind::BoolLiteral => SemanticTokenType::new("boolean"),
SymbolKind::ByteLiteral | SymbolKind::NumericLiteral => SemanticTokenType::NUMBER,
SymbolKind::StringLiteral => SemanticTokenType::STRING,
SymbolKind::BuiltinType => SemanticTokenType::new("builtinType"),
SymbolKind::Module => SemanticTokenType::NAMESPACE,
SymbolKind::Unknown => SemanticTokenType::new("generic"),
}
}

fn type_index(ty: SemanticTokenType) -> u32 {
SUPPORTED_TYPES.iter().position(|it| *it == ty).unwrap() as u32
}
File renamed without changes.
2 changes: 1 addition & 1 deletion sway-lsp/src/core/document.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ struct EditText<'text> {

#[cfg(test)]
mod tests {
use crate::test_utils::get_absolute_path;
use crate::utils::test::get_absolute_path;

use super::*;

Expand Down
6 changes: 2 additions & 4 deletions sway-lsp/src/core/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
pub(crate) mod config;
pub(crate) mod dependency;
pub mod document;
pub mod session;
pub(crate) mod sync;
pub(crate) mod token;
pub(crate) mod traverse_parse_tree;
pub(crate) mod traverse_typed_tree;
pub(crate) mod token_map;
Loading

0 comments on commit 80aa366

Please sign in to comment.