Skip to content

Commit

Permalink
refactor: lsp crates and codes (#1609)
Browse files Browse the repository at this point in the history
* refactor: lsp codes and crates

Signed-off-by: peefy <xpf6677@163.com>

* fix ut

Signed-off-by: he1pa <18012015693@163.com>

---------

Signed-off-by: peefy <xpf6677@163.com>
Signed-off-by: he1pa <18012015693@163.com>
Co-authored-by: he1pa <18012015693@163.com>
  • Loading branch information
Peefy and He1pa authored Aug 29, 2024
1 parent 67cf599 commit 08dbac3
Show file tree
Hide file tree
Showing 19 changed files with 257 additions and 396 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,16 @@ use clap::{builder::Str, Command};
use lsp_server::Connection;
use lsp_types::InitializeParams;

#[allow(dead_code)]
/// Runs the main loop of the language server. This will receive requests and handle them.
pub(crate) fn main_loop(
pub fn main_loop(
connection: Connection,
initialize_params: InitializeParams,
) -> anyhow::Result<()> {
LanguageServerState::new(connection.sender, initialize_params).run(connection.receiver)
}

#[allow(dead_code)]
/// Get the kcl language server CLI application.
pub(crate) fn app() -> Command {
pub fn app() -> Command {
Command::new("kcl-language-server")
.version(Str::from(kclvm_version::get_version_info()))
.about("KCL language server CLI.")
Expand Down
1 change: 0 additions & 1 deletion kclvm/tools/src/LSP/src/capabilities.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ use lsp_types::{
use crate::semantic_token::LEGEND_TYPE;

/// Returns the capabilities of this LSP server implementation given the capabilities of the client.
#[allow(dead_code)]
pub fn server_capabilities(client_caps: &ClientCapabilities) -> ServerCapabilities {
ServerCapabilities {
text_document_sync: Some(TextDocumentSyncCapability::Kind(TextDocumentSyncKind::FULL)),
Expand Down
158 changes: 158 additions & 0 deletions kclvm/tools/src/LSP/src/compile.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
use std::collections::HashSet;

use indexmap::IndexSet;
use kclvm_ast::ast::Program;
use kclvm_driver::{lookup_compile_workspace, toolchain};
use kclvm_error::Diagnostic;
use kclvm_parser::{
entry::get_normalized_k_files_from_paths, load_program, KCLModuleCache, LoadProgramOptions,
ParseSessionRef,
};
use kclvm_sema::{
advanced_resolver::AdvancedResolver,
core::global_state::GlobalState,
namer::Namer,
resolver::{resolve_program_with_opts, scope::KCLScopeCache},
};

use crate::{
state::{KCLGlobalStateCache, KCLVfs},
util::load_files_code_from_vfs,
};

pub struct Params {
pub file: Option<String>,
pub module_cache: Option<KCLModuleCache>,
pub scope_cache: Option<KCLScopeCache>,
pub vfs: Option<KCLVfs>,
pub gs_cache: Option<KCLGlobalStateCache>,
}

pub fn compile(
params: Params,
files: &mut [String],
opts: Option<LoadProgramOptions>,
) -> (IndexSet<Diagnostic>, anyhow::Result<(Program, GlobalState)>) {
// Ignore the kcl plugin sematic check.
let mut opts = opts.unwrap_or_default();
opts.load_plugins = true;
// Get input files
let files = match get_normalized_k_files_from_paths(files, &opts) {
Ok(file_list) => file_list,
Err(e) => {
return (
IndexSet::new(),
Err(anyhow::anyhow!("Compile failed: {:?}", e)),
)
}
};
let files: Vec<&str> = files.iter().map(|s| s.as_str()).collect();
// Update opt.k_code_list
if let Some(vfs) = &params.vfs {
let mut k_code_list = match load_files_code_from_vfs(&files, vfs) {
Ok(code_list) => code_list,
Err(e) => {
return (
IndexSet::new(),
Err(anyhow::anyhow!("Compile failed: {:?}", e)),
)
}
};
opts.k_code_list.append(&mut k_code_list);
}

let mut diags = IndexSet::new();

if let Some(module_cache) = params.module_cache.as_ref() {
if let Some(file) = &params.file {
let code = if let Some(vfs) = &params.vfs {
match load_files_code_from_vfs(&[file.as_str()], vfs) {
Ok(code_list) => code_list.first().cloned(),
Err(_) => None,
}
} else {
None
};
let mut module_cache_ref = module_cache.write().unwrap();
module_cache_ref
.invalidate_module
.insert(file.clone(), code);
}
}

// Parser
let sess = ParseSessionRef::default();
let mut program = match load_program(sess.clone(), &files, Some(opts), params.module_cache) {
Ok(r) => r.program,
Err(e) => return (diags, Err(anyhow::anyhow!("Parse failed: {:?}", e))),
};
diags.extend(sess.1.read().diagnostics.clone());

// Resolver
if let Some(cached_scope) = params.scope_cache.as_ref() {
if let Some(file) = &params.file {
if let Some(mut cached_scope) = cached_scope.try_write() {
let mut invalidate_pkg_modules = HashSet::new();
invalidate_pkg_modules.insert(file.clone());
cached_scope.invalidate_pkg_modules = Some(invalidate_pkg_modules);
}
}
}

let prog_scope = resolve_program_with_opts(
&mut program,
kclvm_sema::resolver::Options {
merge_program: false,
type_erasure: false,
..Default::default()
},
params.scope_cache.clone(),
);
diags.extend(prog_scope.handler.diagnostics);

let mut default = GlobalState::default();
let mut gs_ref;

let gs = match &params.gs_cache {
Some(cache) => match cache.try_lock() {
Ok(locked_state) => {
gs_ref = locked_state;
&mut gs_ref
}
Err(_) => &mut default,
},
None => &mut default,
};

gs.new_or_invalidate_pkgs = match &params.scope_cache {
Some(cache) => match cache.try_write() {
Some(scope) => scope.invalidate_pkgs.clone(),
None => HashSet::new(),
},
None => HashSet::new(),
};
gs.clear_cache();

Namer::find_symbols(&program, gs);

match AdvancedResolver::resolve_program(&program, gs, prog_scope.node_ty_map) {
Ok(_) => (diags, Ok((program, gs.clone()))),
Err(e) => (diags, Err(anyhow::anyhow!("Resolve failed: {:?}", e))),
}
}

#[allow(unused)]
pub fn compile_with_params(
params: Params,
) -> (
IndexSet<kclvm_error::Diagnostic>,
anyhow::Result<(Program, GlobalState)>,
) {
let file = params.file.clone().unwrap();
// Lookup compile workspace from the cursor file.
let (mut files, opts, _) = lookup_compile_workspace(&toolchain::default(), &file, true);
if !files.contains(&file) {
files.push(file);
}
compile(params, &mut files, opts)
}
2 changes: 1 addition & 1 deletion kclvm/tools/src/LSP/src/completion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ pub(crate) struct KCLCompletionItem {
}

/// Computes completions at the given position.
pub(crate) fn completion(
pub fn completion(
trigger_character: Option<char>,
program: &Program,
pos: &KCLPos,
Expand Down
5 changes: 1 addition & 4 deletions kclvm/tools/src/LSP/src/document_symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,7 @@ use lsp_types::{DocumentSymbol, DocumentSymbolResponse, SymbolKind};

use crate::to_lsp::lsp_pos;

pub(crate) fn document_symbol(
file: &str,
gs: &GlobalState,
) -> Option<lsp_types::DocumentSymbolResponse> {
pub fn document_symbol(file: &str, gs: &GlobalState) -> Option<lsp_types::DocumentSymbolResponse> {
let mut document_symbols: Vec<DocumentSymbol> = vec![];

let dummy_pos = Position {
Expand Down
2 changes: 1 addition & 1 deletion kclvm/tools/src/LSP/src/find_refs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use kclvm_sema::core::global_state::GlobalState;
use lsp_types::Location;
use std::collections::HashSet;

pub(crate) fn find_refs(kcl_pos: &KCLPos, gs: &GlobalState) -> Option<Vec<Location>> {
pub fn find_refs(kcl_pos: &KCLPos, gs: &GlobalState) -> Option<Vec<Location>> {
match gs.look_up_exact_symbol(kcl_pos) {
Some(symbol_ref) => match gs.get_symbols().get_symbol(symbol_ref) {
Some(symbol) => match symbol.get_definition() {
Expand Down
2 changes: 1 addition & 1 deletion kclvm/tools/src/LSP/src/formatting.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use kclvm_tools::format::{format_source, FormatOptions};
use lsp_types::{Position, Range, TextEdit};

pub(crate) fn format(
pub fn format(
file: String,
src: String,
range: Option<Range>,
Expand Down
7 changes: 2 additions & 5 deletions kclvm/tools/src/LSP/src/goto_def.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,8 @@ use kclvm_sema::core::global_state::GlobalState;
use kclvm_sema::core::symbol::SymbolRef;
use lsp_types::GotoDefinitionResponse;

// Navigates to the definition of an identifier.
pub(crate) fn goto_def(
kcl_pos: &KCLPos,
gs: &GlobalState,
) -> Option<lsp_types::GotoDefinitionResponse> {
/// Navigates to the definition of an identifier.
pub fn goto_def(kcl_pos: &KCLPos, gs: &GlobalState) -> Option<lsp_types::GotoDefinitionResponse> {
let mut res = IndexSet::new();
let def = find_def(kcl_pos, gs, true);
match def {
Expand Down
2 changes: 1 addition & 1 deletion kclvm/tools/src/LSP/src/hover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ enum MarkedStringType {

/// Returns a short text describing element at position.
/// Specifically, the doc for schema and schema attr(todo)
pub(crate) fn hover(kcl_pos: &KCLPos, gs: &GlobalState) -> Option<lsp_types::Hover> {
pub fn hover(kcl_pos: &KCLPos, gs: &GlobalState) -> Option<lsp_types::Hover> {
let mut docs: Vec<(String, MarkedStringType)> = vec![];
let def = find_def(kcl_pos, gs, true);
match def {
Expand Down
36 changes: 19 additions & 17 deletions kclvm/tools/src/LSP/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,27 @@
mod analysis;
mod capabilities;
mod completion;
pub mod analysis;
pub mod capabilities;
pub mod completion;
pub mod document_symbol;
pub mod find_refs;
pub mod formatting;
pub mod goto_def;
pub mod hover;
pub mod inlay_hints;
pub mod quick_fix;
pub mod rename;
pub mod request;
pub mod semantic_token;
pub mod signature_help;

pub mod app;
pub mod compile;
mod dispatcher;
mod document_symbol;
mod error;
mod find_refs;
mod formatting;
mod from_lsp;
mod goto_def;
mod hover;
mod inlay_hints;
mod main_loop;
pub mod from_lsp;
mod notification;
mod quick_fix;
pub mod rename;
mod request;
mod semantic_token;
mod signature_help;
mod state;
#[cfg(test)]
mod tests;
mod to_lsp;
pub mod to_lsp;
mod util;
mod word_index;
10 changes: 5 additions & 5 deletions kclvm/tools/src/LSP/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
use crate::main_loop::main_loop;
use main_loop::app;

mod analysis;
mod app;
mod capabilities;
mod compile;
mod completion;
mod dispatcher;
mod document_symbol;
mod error;
mod find_refs;
mod formatting;
mod from_lsp;
mod goto_def;
mod hover;
mod inlay_hints;
mod main_loop;
mod notification;
mod quick_fix;
mod request;
Expand All @@ -23,10 +22,11 @@ mod to_lsp;
mod util;
mod word_index;

mod formatting;
#[cfg(test)]
mod tests;

use app::{app, main_loop};

/// Main entry point for the `kcl-language-server` executable.
fn main() -> Result<(), anyhow::Error> {
let args: Vec<String> = std::env::args().collect();
Expand Down
11 changes: 3 additions & 8 deletions kclvm/tools/src/LSP/src/quick_fix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use lsp_types::{
};
use serde_json::Value;

pub(crate) fn quick_fix(uri: &Url, diags: &[Diagnostic]) -> Vec<lsp_types::CodeActionOrCommand> {
pub fn quick_fix(uri: &Url, diags: &[Diagnostic]) -> Vec<lsp_types::CodeActionOrCommand> {
let mut code_actions: Vec<lsp_types::CodeActionOrCommand> = vec![];
for diag in diags {
if let Some(code) = &diag.code {
Expand Down Expand Up @@ -158,21 +158,18 @@ pub(crate) fn convert_code_to_kcl_diag_id(code: &NumberOrString) -> Option<Diagn

#[cfg(test)]
mod tests {

use kclvm_driver::toolchain;
use lsp_types::{
CodeAction, CodeActionKind, CodeActionOrCommand, Diagnostic, Position, Range, TextEdit,
Url, WorkspaceEdit,
};
use parking_lot::RwLock;
use proc_macro_crate::bench_test;
use std::{path::PathBuf, sync::Arc};
use std::path::PathBuf;

use super::quick_fix;
use crate::{
compile::{compile_with_params, Params},
state::KCLVfs,
to_lsp::kcl_diag_to_lsp_diags_by_file,
util::{compile_with_params, Params},
};

#[test]
Expand All @@ -188,8 +185,6 @@ mod tests {
module_cache: None,
scope_cache: None,
vfs: Some(KCLVfs::default()),
entry_cache: None,
tool: Arc::new(RwLock::new(toolchain::default())),
gs_cache: None,
})
.0;
Expand Down
13 changes: 7 additions & 6 deletions kclvm/tools/src/LSP/src/rename.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,12 +302,13 @@ pub fn match_pkgpath_and_code(
}
}

/// the rename_symbol API
/// find all the occurrences of the target symbol and return the text edit actions to rename them
/// pkg_root: the absolute file path to the root package
/// vfs: contains all the files and contents to be renamed
/// symbol_path: path to the symbol. The symbol path should be in the format of: `pkg.sub_pkg:name.sub_name`
/// new_name: the new name of the symbol
/// Find all the occurrences of the target symbol and return the text edit actions to rename them.
///
/// ## Parameters
/// - pkg_root: the absolute file path to the root package
/// - vfs: contains all the files and contents to be renamed
/// - symbol_path: path to the symbol. The symbol path should be in the format of: `pkg.sub_pkg:name.sub_name`
/// - new_name: the new name of the symbol
pub fn rename_symbol<F>(
pkg_root: &str,
vfs: KCLVfs,
Expand Down
Loading

0 comments on commit 08dbac3

Please sign in to comment.