Add documentation to hovers
This commit is contained in:
		
							parent
							
								
									6dccab8b12
								
							
						
					
					
						commit
						dcb4e76a40
					
				| @ -193,6 +193,33 @@ impl AnalysisState { | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn set_documentation(&mut self, token_idx: usize, documentation: Option<String>) { | ||||
|         if let Some(documentation) = documentation { | ||||
|             if let Some(token) = self.map.get_mut(&token_idx) { | ||||
|                 if let Some(hover) = &mut token.hover { | ||||
|                     hover.documentation = Some(documentation); | ||||
|                 } else { | ||||
|                     token.hover = Some(Hover { | ||||
|                         documentation: Some(documentation), | ||||
|                         kind: None, | ||||
|                     }); | ||||
|                 } | ||||
|             } else { | ||||
|                 self.map.insert( | ||||
|                     token_idx, | ||||
|                     SemanticToken { | ||||
|                         hover: Some(Hover { | ||||
|                             documentation: Some(documentation), | ||||
|                             kind: None, | ||||
|                         }), | ||||
|                         autocomplete: Vec::new(), | ||||
|                         symbol: Default::default(), | ||||
|                     }, | ||||
|                 ); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     pub fn set_symbol(&mut self, idx: usize, symbol: SymbolId) { | ||||
|         self.symbol_to_token.insert(symbol, idx); | ||||
|         if let Some(token) = self.map.get_mut(&idx) { | ||||
| @ -246,8 +273,8 @@ pub struct AnalysisScope<'a> { | ||||
|     tokens: &'a Vec<FullToken>, | ||||
|     variables: HashMap<String, SymbolId>, | ||||
|     types: HashMap<TypeKind, (SourceModuleId, SymbolId)>, | ||||
|     functions: HashMap<String, (SourceModuleId, SymbolId)>, | ||||
|     associated_functions: HashMap<(TypeKind, String), (SourceModuleId, SymbolId)>, | ||||
|     functions: HashMap<String, (SourceModuleId, SymbolId, Option<String>)>, | ||||
|     associated_functions: HashMap<(TypeKind, String), (SourceModuleId, SymbolId, Option<String>)>, | ||||
|     map: &'a StateMap, | ||||
| } | ||||
| 
 | ||||
| @ -646,9 +673,10 @@ pub fn analyze_context( | ||||
|             if source_id != module.module_id { | ||||
|                 if let Some(state) = map.get(&source_id) { | ||||
|                     if let Some(symbol) = state.associated_functions.get(&(ty.clone(), function.name.clone())) { | ||||
|                         scope | ||||
|                             .associated_functions | ||||
|                             .insert((ty.clone(), function.name.clone()), (source_id, *symbol)); | ||||
|                         scope.associated_functions.insert( | ||||
|                             (ty.clone(), function.name.clone()), | ||||
|                             (source_id, *symbol, function.documentation.clone()), | ||||
|                         ); | ||||
|                     } | ||||
|                 } | ||||
|                 continue; | ||||
| @ -664,9 +692,10 @@ pub fn analyze_context( | ||||
|             .state | ||||
|             .associated_functions | ||||
|             .insert((ty.clone(), function.name.clone()), symbol); | ||||
|         scope | ||||
|             .associated_functions | ||||
|             .insert((ty.clone(), function.name.clone()), (module.module_id, symbol)); | ||||
|         scope.associated_functions.insert( | ||||
|             (ty.clone(), function.name.clone()), | ||||
|             (module.module_id, symbol, function.documentation.clone()), | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|     for (_, function) in &module.associated_functions { | ||||
| @ -692,7 +721,10 @@ pub fn analyze_context( | ||||
|             if source_id != module.module_id { | ||||
|                 if let Some(state) = map.get(&source_id) { | ||||
|                     if let Some(symbol) = state.functions.get(&function.name) { | ||||
|                         scope.functions.insert(function.name.clone(), (source_id, *symbol)); | ||||
|                         scope.functions.insert( | ||||
|                             function.name.clone(), | ||||
|                             (source_id, *symbol, function.documentation.clone()), | ||||
|                         ); | ||||
|                     } | ||||
|                 } | ||||
|                 continue; | ||||
| @ -702,7 +734,7 @@ pub fn analyze_context( | ||||
|         scope.state.init_hover( | ||||
|             &function.signature(), | ||||
|             Some(HoverKind::Type(function.return_type.clone())), | ||||
|             None, | ||||
|             function.documentation.clone(), | ||||
|         ); | ||||
| 
 | ||||
|         let idx = scope | ||||
| @ -711,9 +743,10 @@ pub fn analyze_context( | ||||
|         let function_symbol = scope.state.new_symbol(idx, SemanticKind::Function); | ||||
|         scope.state.set_symbol(idx, function_symbol); | ||||
|         scope.state.functions.insert(function.name.clone(), function_symbol); | ||||
|         scope | ||||
|             .functions | ||||
|             .insert(function.name.clone(), (module.module_id, function_symbol)); | ||||
|         scope.functions.insert( | ||||
|             function.name.clone(), | ||||
|             (module.module_id, function_symbol, function.documentation.clone()), | ||||
|         ); | ||||
|     } | ||||
| 
 | ||||
|     for function in &module.functions { | ||||
| @ -777,10 +810,12 @@ pub fn analyze_context( | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             let symbol = if let Some((source_id, symbol_id)) = scope.functions.get(&import_name) { | ||||
|                 scope | ||||
|             let symbol = if let Some((source_id, symbol_id, doc)) = scope.functions.get(&import_name) { | ||||
|                 let symbol_id = scope | ||||
|                     .state | ||||
|                     .new_symbol(import_idx, SemanticKind::Reference(*source_id, *symbol_id)) | ||||
|                     .new_symbol(import_idx, SemanticKind::Reference(*source_id, *symbol_id)); | ||||
|                 scope.state.set_documentation(import_idx, doc.clone()); | ||||
|                 symbol_id | ||||
|             } else if let Some(module_source) = scope.map.values().find(|s| s.module_name == *module_name) { | ||||
|                 if let Some((source_id, symbol_id)) = scope.types.get(&TypeKind::CustomType(CustomTypeKey( | ||||
|                     import_name.clone(), | ||||
| @ -1070,10 +1105,12 @@ pub fn analyze_expr( | ||||
|             let idx = scope | ||||
|                 .token_idx(&meta, |t| matches!(t, Token::Identifier(_))) | ||||
|                 .unwrap_or(meta.range.end); | ||||
|             let symbol = if let Some((module_id, symbol_id)) = scope.functions.get(name) { | ||||
|                 scope | ||||
|             let symbol = if let Some((module_id, symbol_id, doc)) = scope.functions.get(name) { | ||||
|                 let symbol = scope | ||||
|                     .state | ||||
|                     .new_symbol(idx, SemanticKind::Reference(*module_id, *symbol_id)) | ||||
|                     .new_symbol(idx, SemanticKind::Reference(*module_id, *symbol_id)); | ||||
|                 scope.state.set_documentation(idx, doc.clone()); | ||||
|                 symbol | ||||
|             } else { | ||||
|                 scope.state.new_symbol(idx, SemanticKind::Function) | ||||
|             }; | ||||
| @ -1106,12 +1143,14 @@ pub fn analyze_expr( | ||||
|             let fn_idx = scope | ||||
|                 .token_idx(&meta, |t| matches!(t, Token::Identifier(_))) | ||||
|                 .unwrap_or(meta.range.end); | ||||
|             let fn_symbol = if let Some((module_id, symbol_id)) = | ||||
|             let fn_symbol = if let Some((module_id, symbol_id, doc)) = | ||||
|                 scope.associated_functions.get(&(invoked_ty.clone(), name.clone())) | ||||
|             { | ||||
|                 scope | ||||
|                 let symbol = scope | ||||
|                     .state | ||||
|                     .new_symbol(fn_idx, SemanticKind::Reference(*module_id, *symbol_id)) | ||||
|                     .new_symbol(fn_idx, SemanticKind::Reference(*module_id, *symbol_id)); | ||||
|                 scope.state.set_documentation(fn_idx, doc.clone()); | ||||
|                 symbol | ||||
|             } else { | ||||
|                 scope.state.new_symbol(fn_idx, SemanticKind::Function) | ||||
|             }; | ||||
|  | ||||
| @ -12,12 +12,12 @@ use tower_lsp::lsp_types::{ | ||||
|     self, CompletionItem, CompletionItemKind, CompletionOptions, CompletionParams, CompletionResponse, Diagnostic, | ||||
|     DiagnosticSeverity, DidChangeTextDocumentParams, DidOpenTextDocumentParams, DidSaveTextDocumentParams, | ||||
|     DocumentFilter, GotoDefinitionParams, GotoDefinitionResponse, Hover, HoverContents, HoverParams, | ||||
|     HoverProviderCapability, InitializeParams, InitializeResult, InitializedParams, Location, MarkupContent, | ||||
|     MarkupKind, MessageType, OneOf, Range, ReferenceParams, RenameParams, SemanticToken, SemanticTokensLegend, | ||||
|     SemanticTokensOptions, SemanticTokensParams, SemanticTokensResult, SemanticTokensServerCapabilities, | ||||
|     ServerCapabilities, TextDocumentItem, TextDocumentRegistrationOptions, TextDocumentSyncCapability, | ||||
|     TextDocumentSyncKind, TextDocumentSyncOptions, TextDocumentSyncSaveOptions, TextEdit, Url, WorkspaceEdit, | ||||
|     WorkspaceFoldersServerCapabilities, WorkspaceServerCapabilities, | ||||
|     HoverProviderCapability, InitializeParams, InitializeResult, InitializedParams, Location, MarkedString, | ||||
|     MarkupContent, MarkupKind, MessageType, OneOf, Range, ReferenceParams, RenameParams, SemanticToken, | ||||
|     SemanticTokensLegend, SemanticTokensOptions, SemanticTokensParams, SemanticTokensResult, | ||||
|     SemanticTokensServerCapabilities, ServerCapabilities, TextDocumentItem, TextDocumentRegistrationOptions, | ||||
|     TextDocumentSyncCapability, TextDocumentSyncKind, TextDocumentSyncOptions, TextDocumentSyncSaveOptions, TextEdit, | ||||
|     Url, WorkspaceEdit, WorkspaceFoldersServerCapabilities, WorkspaceServerCapabilities, | ||||
| }; | ||||
| use tower_lsp::{Client, LanguageServer, LspService, Server, jsonrpc}; | ||||
| 
 | ||||
| @ -199,7 +199,7 @@ impl LanguageServer for Backend { | ||||
|             None | ||||
|         }; | ||||
| 
 | ||||
|         let (range, ty) = if let Some((idx, token)) = token { | ||||
|         let (range, ty, documentation) = if let Some((idx, token)) = token { | ||||
|             if let Some(analysis) = self.analysis.get(&path).unwrap().state.map.get(&idx) { | ||||
|                 let start = token.position; | ||||
|                 let end = token.position.add(token.token.len() as u32); | ||||
| @ -216,7 +216,9 @@ impl LanguageServer for Backend { | ||||
|                 if let Some(hover) = analysis.hover.clone() { | ||||
|                     if let Some(kind) = hover.kind { | ||||
|                         match kind { | ||||
|                             analysis::HoverKind::Type(type_kind) => (Some(range), format!("{}", type_kind)), | ||||
|                             analysis::HoverKind::Type(type_kind) => { | ||||
|                                 (Some(range), format!("{}", type_kind), hover.documentation) | ||||
|                             } | ||||
|                             analysis::HoverKind::Function(name, function_params, return_type) => ( | ||||
|                                 Some(range), | ||||
|                                 format!( | ||||
| @ -229,25 +231,30 @@ impl LanguageServer for Backend { | ||||
|                                         .join(", "), | ||||
|                                     return_type | ||||
|                                 ), | ||||
|                                 hover.documentation, | ||||
|                             ), | ||||
|                         } | ||||
|                     } else { | ||||
|                         (Some(range), String::from("No type")) | ||||
|                         (Some(range), String::from("No type"), hover.documentation) | ||||
|                     } | ||||
|                 } else { | ||||
|                     (Some(range), String::from("No hover")) | ||||
|                     (Some(range), String::from("No hover"), None) | ||||
|                 } | ||||
|             } else { | ||||
|                 (None, String::from("no type")) | ||||
|                 (None, String::from("no type"), None) | ||||
|             } | ||||
|         } else { | ||||
|             (None, String::from("no token")) | ||||
|             (None, String::from("no token"), None) | ||||
|         }; | ||||
| 
 | ||||
|         let contents = HoverContents::Markup(MarkupContent { | ||||
|             kind: MarkupKind::Markdown, | ||||
|             value: format!("`{ty}`"), | ||||
|         }); | ||||
|         let contents = if let Some(doc) = documentation { | ||||
|             HoverContents::Array(vec![MarkedString::String(doc), MarkedString::String(format!("`{ty}`"))]) | ||||
|         } else { | ||||
|             HoverContents::Markup(MarkupContent { | ||||
|                 kind: MarkupKind::Markdown, | ||||
|                 value: format!("`{ty}`"), | ||||
|             }) | ||||
|         }; | ||||
| 
 | ||||
|         Ok(Some(Hover { contents, range })) | ||||
|     } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user