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