Add hover kind
This commit is contained in:
		
							parent
							
								
									7b4f38406d
								
							
						
					
					
						commit
						6dccab8b12
					
				| @ -8,9 +8,8 @@ struct Otus { | ||||
| } | ||||
| 
 | ||||
| impl Otus { | ||||
|     /// Some test documentation | ||||
|     /// Here | ||||
|     /// qwe | ||||
|     /// Some test documentation here. | ||||
|     /// On a second line | ||||
|     fn test(&self) -> u32 { | ||||
|         *self.field | ||||
|     } | ||||
|  | ||||
| @ -2,6 +2,7 @@ use std::{collections::HashMap, hash::Hash, path::PathBuf}; | ||||
| 
 | ||||
| use reid::{ | ||||
|     ast::{ | ||||
|         ReturnType, | ||||
|         lexer::{FullToken, Token}, | ||||
|         token_stream::TokenRange, | ||||
|     }, | ||||
| @ -84,7 +85,7 @@ impl StaticAnalysis { | ||||
| 
 | ||||
| #[derive(Debug, Clone)] | ||||
| pub struct SemanticToken { | ||||
|     pub ty: Option<TypeKind>, | ||||
|     pub hover: Option<Hover>, | ||||
|     pub autocomplete: Vec<Autocomplete>, | ||||
|     pub symbol: Option<SymbolId>, | ||||
| } | ||||
| @ -103,6 +104,18 @@ pub enum AutocompleteKind { | ||||
|     Function(Vec<FunctionParam>, TypeKind), | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug, Clone)] | ||||
| pub struct Hover { | ||||
|     pub documentation: Option<String>, | ||||
|     pub kind: Option<HoverKind>, | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug, Clone)] | ||||
| pub enum HoverKind { | ||||
|     Type(TypeKind), | ||||
|     Function(String, Vec<FunctionParam>, TypeKind), | ||||
| } | ||||
| 
 | ||||
| impl ToString for AutocompleteKind { | ||||
|     fn to_string(&self) -> String { | ||||
|         match self { | ||||
| @ -149,12 +162,15 @@ impl AnalysisState { | ||||
| } | ||||
| 
 | ||||
| impl AnalysisState { | ||||
|     pub fn init_types(&mut self, meta: &mir::Metadata, ty: Option<TypeKind>) { | ||||
|     pub fn init_hover(&mut self, meta: &mir::Metadata, kind: Option<HoverKind>, documentation: Option<String>) { | ||||
|         for token in meta.range.start..=meta.range.end { | ||||
|             self.map.insert( | ||||
|                 token, | ||||
|                 SemanticToken { | ||||
|                     ty: ty.clone(), | ||||
|                     hover: Some(Hover { | ||||
|                         documentation: documentation.clone(), | ||||
|                         kind: kind.clone(), | ||||
|                     }), | ||||
|                     autocomplete: Vec::new(), | ||||
|                     symbol: Default::default(), | ||||
|                 }, | ||||
| @ -169,7 +185,7 @@ impl AnalysisState { | ||||
|             self.map.insert( | ||||
|                 token_idx, | ||||
|                 SemanticToken { | ||||
|                     ty: None, | ||||
|                     hover: None, | ||||
|                     autocomplete: autocomplete.clone(), | ||||
|                     symbol: Default::default(), | ||||
|                 }, | ||||
| @ -185,7 +201,7 @@ impl AnalysisState { | ||||
|             self.map.insert( | ||||
|                 idx, | ||||
|                 SemanticToken { | ||||
|                     ty: None, | ||||
|                     hover: None, | ||||
|                     autocomplete: Vec::new(), | ||||
|                     symbol: Some(symbol), | ||||
|                 }, | ||||
| @ -533,7 +549,7 @@ pub fn analyze_context( | ||||
|                         .token_idx(&field.2, |t| matches!(t, Token::Identifier(_))) | ||||
|                         .unwrap_or(field.2.range.end); | ||||
| 
 | ||||
|                     scope.state.init_types( | ||||
|                     scope.state.init_hover( | ||||
|                         &Metadata { | ||||
|                             source_module_id: field.2.source_module_id, | ||||
|                             range: TokenRange { | ||||
| @ -542,7 +558,8 @@ pub fn analyze_context( | ||||
|                             }, | ||||
|                             position: None, | ||||
|                         }, | ||||
|                         Some(field.1.clone()), | ||||
|                         Some(HoverKind::Type(field.1.clone())), | ||||
|                         None, | ||||
|                     ); | ||||
| 
 | ||||
|                     let field_symbol = scope.state.new_symbol(field_idx, SemanticKind::Property); | ||||
| @ -584,7 +601,7 @@ pub fn analyze_context( | ||||
|                         scope.state.new_symbol(field_ty_idx, SemanticKind::Type) | ||||
|                     }; | ||||
| 
 | ||||
|                     scope.state.init_types( | ||||
|                     scope.state.init_hover( | ||||
|                         &Metadata { | ||||
|                             source_module_id: field.2.source_module_id, | ||||
|                             range: TokenRange { | ||||
| @ -593,7 +610,8 @@ pub fn analyze_context( | ||||
|                             }, | ||||
|                             position: None, | ||||
|                         }, | ||||
|                         Some(field.1.clone()), | ||||
|                         Some(HoverKind::Type(field.1.clone())), | ||||
|                         None, | ||||
|                     ); | ||||
|                     scope.state.set_symbol(field_ty_idx, field_ty_symbol); | ||||
|                 } | ||||
| @ -604,7 +622,9 @@ pub fn analyze_context( | ||||
|     for binop in &module.binop_defs { | ||||
|         if binop.meta.source_module_id == module.module_id { | ||||
|             for param in [&binop.lhs, &binop.rhs] { | ||||
|                 scope.state.init_types(¶m.meta, Some(param.ty.clone())); | ||||
|                 scope | ||||
|                     .state | ||||
|                     .init_hover(¶m.meta, Some(HoverKind::Type(param.ty.clone())), None); | ||||
|                 let idx = scope | ||||
|                     .token_idx(¶m.meta, |t| matches!(t, Token::Identifier(_))) | ||||
|                     .unwrap_or(param.meta.range.end); | ||||
| @ -679,9 +699,11 @@ pub fn analyze_context( | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         scope | ||||
|             .state | ||||
|             .init_types(&function.signature(), Some(function.return_type.clone())); | ||||
|         scope.state.init_hover( | ||||
|             &function.signature(), | ||||
|             Some(HoverKind::Type(function.return_type.clone())), | ||||
|             None, | ||||
|         ); | ||||
| 
 | ||||
|         let idx = scope | ||||
|             .token_idx(&function.signature(), |t| matches!(t, Token::Identifier(_))) | ||||
| @ -713,7 +735,7 @@ pub fn analyze_context( | ||||
|     } | ||||
| 
 | ||||
|     for import in &module.imports { | ||||
|         scope.state.init_types(&import.1, None); | ||||
|         scope.state.init_hover(&import.1, None, None); | ||||
|         if let Some((module_name, _)) = import.0.get(0) { | ||||
|             let module_idx = scope | ||||
|                 .token_idx(&import.1, |t| matches!(t, Token::Identifier(_))) | ||||
| @ -793,7 +815,9 @@ pub fn analyze_function_parameters( | ||||
|     scope: &mut AnalysisScope, | ||||
| ) { | ||||
|     for param in &function.parameters { | ||||
|         scope.state.init_types(¶m.meta, Some(param.ty.clone())); | ||||
|         scope | ||||
|             .state | ||||
|             .init_hover(¶m.meta, Some(HoverKind::Type(param.ty.clone())), None); | ||||
| 
 | ||||
|         if param.meta.source_module_id == module.module_id { | ||||
|             let param_var_idx = scope | ||||
| @ -832,12 +856,14 @@ pub fn analyze_block( | ||||
|     for statement in &block.statements { | ||||
|         match &statement.0 { | ||||
|             mir::StmtKind::Let(named_variable_ref, _, expression) => { | ||||
|                 scope.state.init_types( | ||||
|                 scope.state.init_hover( | ||||
|                     &named_variable_ref.2, | ||||
|                     expression | ||||
|                         .return_type(&TypeRefs::unknown(), source_module.module_id) | ||||
|                         .ok() | ||||
|                         .map(|(_, ty)| ty), | ||||
|                         .map(|(_, ty)| ty) | ||||
|                         .map(|t| HoverKind::Type(t)), | ||||
|                     None, | ||||
|                 ); | ||||
|                 let idx = scope | ||||
|                     .token_idx(&named_variable_ref.2, |t| matches!(t, Token::Identifier(_))) | ||||
| @ -888,16 +914,19 @@ pub fn analyze_expr( | ||||
|     expr: &mir::Expression, | ||||
|     scope: &mut AnalysisScope, | ||||
| ) { | ||||
|     scope.state.init_types( | ||||
|     scope.state.init_hover( | ||||
|         &expr.1, | ||||
|         expr.return_type(&TypeRefs::unknown(), source_module.module_id) | ||||
|             .ok() | ||||
|             .map(|(_, t)| t), | ||||
|             .map(|(_, t)| HoverKind::Type(t)), | ||||
|         None, | ||||
|     ); | ||||
| 
 | ||||
|     match &expr.0 { | ||||
|         mir::ExprKind::Variable(var_ref) => { | ||||
|             scope.state.init_types(&var_ref.2, Some(var_ref.0.clone())); | ||||
|             scope | ||||
|                 .state | ||||
|                 .init_hover(&var_ref.2, Some(HoverKind::Type(var_ref.0.clone())), None); | ||||
| 
 | ||||
|             let idx = scope | ||||
|                 .token_idx(&var_ref.2, |t| matches!(t, Token::Identifier(_))) | ||||
|  | ||||
| @ -213,10 +213,29 @@ impl LanguageServer for Backend { | ||||
|                         character: (end.0 as i32 - 1).max(0) as u32, | ||||
|                     }, | ||||
|                 }; | ||||
|                 if let Some(ty) = analysis.ty.clone() { | ||||
|                     (Some(range), format!("{}", ty)) | ||||
|                 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::Function(name, function_params, return_type) => ( | ||||
|                                 Some(range), | ||||
|                                 format!( | ||||
|                                     "{}({}) -> {}", | ||||
|                                     name, | ||||
|                                     function_params | ||||
|                                         .iter() | ||||
|                                         .map(|p| format!("{}: {}", p.name, p.ty)) | ||||
|                                         .collect::<Vec<_>>() | ||||
|                                         .join(", "), | ||||
|                                     return_type | ||||
|                                 ), | ||||
|                             ), | ||||
|                         } | ||||
|                     } else { | ||||
|                         (Some(range), String::from("No type")) | ||||
|                     } | ||||
|                 } else { | ||||
|                     (Some(range), String::from("None type")) | ||||
|                     (Some(range), String::from("No hover")) | ||||
|                 } | ||||
|             } else { | ||||
|                 (None, String::from("no type")) | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user