@@ -40,6 +40,10 @@ use lsp_types::CodeActionParams;
4040use lsp_types:: CodeActionProviderCapability ;
4141use lsp_types:: CodeActionResponse ;
4242use lsp_types:: CodeActionTriggerKind ;
43+ use lsp_types:: CodeLens ;
44+ use lsp_types:: CodeLensOptions ;
45+ use lsp_types:: CodeLensParams ;
46+ use lsp_types:: Command ;
4347use lsp_types:: CompletionItem ;
4448use lsp_types:: CompletionList ;
4549use lsp_types:: CompletionOptions ;
@@ -152,6 +156,7 @@ use lsp_types::request::CallHierarchyIncomingCalls;
152156use lsp_types:: request:: CallHierarchyOutgoingCalls ;
153157use lsp_types:: request:: CallHierarchyPrepare ;
154158use lsp_types:: request:: CodeActionRequest ;
159+ use lsp_types:: request:: CodeLensRequest ;
155160use lsp_types:: request:: Completion ;
156161use lsp_types:: request:: DocumentDiagnosticRequest ;
157162use lsp_types:: request:: DocumentHighlightRequest ;
@@ -949,6 +954,12 @@ struct InitializeResult<C> {
949954 server_info : Option < ServerInfo > ,
950955}
951956
957+ #[ derive( Debug , Clone ) ]
958+ struct CodeLensTarget {
959+ range : Range ,
960+ definition : FindDefinitionItemWithDocstring ,
961+ }
962+
952963pub fn initialize_finish < C : Serialize > (
953964 sender : & Sender < Message > ,
954965 reader : & mut MessageReader ,
@@ -1164,6 +1175,14 @@ pub fn capabilities(
11641175 ] ) ,
11651176 ..Default :: default ( )
11661177 } ) ) ,
1178+ code_lens_provider : match indexing_mode {
1179+ IndexingMode :: None => None ,
1180+ IndexingMode :: LazyNonBlockingBackground | IndexingMode :: LazyBlocking => {
1181+ Some ( CodeLensOptions {
1182+ resolve_provider : Some ( false ) ,
1183+ } )
1184+ }
1185+ } ,
11671186 completion_provider : Some ( CompletionOptions {
11681187 trigger_characters : Some ( vec ! [ "." . to_owned( ) , "'" . to_owned( ) , "\" " . to_owned( ) ] ) ,
11691188 resolve_provider : Some ( true ) ,
@@ -2024,6 +2043,20 @@ impl Server {
20242043 ) ) ,
20252044 ) ) ;
20262045 }
2046+ } else if let Some ( params) = as_request :: < CodeLensRequest > ( & x) {
2047+ if let Some ( params) = self
2048+ . extract_request_params_or_send_err_response :: < CodeLensRequest > (
2049+ params, & x. id ,
2050+ )
2051+ {
2052+ self . set_file_stats ( params. text_document . uri . clone ( ) , telemetry_event) ;
2053+ self . code_lens (
2054+ x. id ,
2055+ & transaction,
2056+ params,
2057+ telemetry_event. activity_key . clone ( ) ,
2058+ ) ;
2059+ }
20272060 } else if let Some ( params) = as_request :: < WorkspaceSymbolRequest > ( & x) {
20282061 if let Some ( params) = self
20292062 . extract_request_params_or_send_err_response :: < WorkspaceSymbolRequest > (
@@ -4259,6 +4292,61 @@ impl Server {
42594292 ( !actions. is_empty ( ) ) . then_some ( actions)
42604293 }
42614294
4295+ fn code_lens_targets (
4296+ & self ,
4297+ transaction : & Transaction < ' _ > ,
4298+ handle : & Handle ,
4299+ uri : & Url ,
4300+ ) -> Option < Vec < CodeLensTarget > > {
4301+ fn recurse_symbols < ' a > ( symbols : & ' a [ DocumentSymbol ] , out : & mut Vec < & ' a DocumentSymbol > ) {
4302+ for symbol in symbols {
4303+ if matches ! (
4304+ symbol. kind,
4305+ SymbolKind :: CLASS | SymbolKind :: FUNCTION | SymbolKind :: METHOD
4306+ ) {
4307+ out. push ( symbol) ;
4308+ }
4309+ if let Some ( children) = symbol. children . as_deref ( ) {
4310+ recurse_symbols ( children, out) ;
4311+ }
4312+ }
4313+ }
4314+
4315+ let module_info = transaction. get_module_info ( handle) ?;
4316+ let symbols = transaction. symbols ( handle) ?;
4317+ let mut symbol_defs = Vec :: new ( ) ;
4318+ recurse_symbols ( & symbols, & mut symbol_defs) ;
4319+
4320+ let mut seen = SmallSet :: new ( ) ;
4321+ let mut targets = Vec :: new ( ) ;
4322+ for symbol in symbol_defs {
4323+ let position = self . from_lsp_position ( uri, & module_info, symbol. selection_range . start ) ;
4324+ let Some ( definition) = transaction
4325+ . find_definition (
4326+ handle,
4327+ position,
4328+ FindPreference {
4329+ import_behavior : ImportBehavior :: StopAtRenamedImports ,
4330+ ..Default :: default ( )
4331+ } ,
4332+ )
4333+ . into_iter ( )
4334+ . next ( )
4335+ else {
4336+ continue ;
4337+ } ;
4338+ let key = ( definition. module . path ( ) . dupe ( ) , definition. definition_range ) ;
4339+ if !seen. insert ( key) {
4340+ continue ;
4341+ }
4342+ targets. push ( CodeLensTarget {
4343+ range : symbol. selection_range ,
4344+ definition,
4345+ } ) ;
4346+ }
4347+ Some ( targets)
4348+ }
4349+
42624350 fn document_highlight (
42634351 & self ,
42644352 transaction : & Transaction < ' _ > ,
@@ -4508,6 +4596,113 @@ impl Server {
45084596 ) ;
45094597 }
45104598
4599+ fn code_lens < ' a > (
4600+ & ' a self ,
4601+ request_id : RequestId ,
4602+ transaction : & Transaction < ' a > ,
4603+ params : CodeLensParams ,
4604+ activity_key : Option < ActivityKey > ,
4605+ ) {
4606+ let uri = & params. text_document . uri ;
4607+ if self . open_notebook_cells . read ( ) . contains_key ( uri) {
4608+ return self . send_response ( new_response ( request_id, Ok ( Some ( Vec :: < CodeLens > :: new ( ) ) ) ) ) ;
4609+ }
4610+ let Some ( handle) = self . make_handle_if_enabled ( uri, Some ( CodeLensRequest :: METHOD ) ) else {
4611+ return self . send_response ( new_response :: < Option < Vec < CodeLens > > > ( request_id, Ok ( None ) ) ) ;
4612+ } ;
4613+ let Some ( targets) = self . code_lens_targets ( transaction, & handle, uri) else {
4614+ return self . send_response ( new_response :: < Option < Vec < CodeLens > > > ( request_id, Ok ( None ) ) ) ;
4615+ } ;
4616+ if targets. is_empty ( ) {
4617+ return self . send_response ( new_response ( request_id, Ok ( Some ( Vec :: < CodeLens > :: new ( ) ) ) ) ) ;
4618+ }
4619+
4620+ let path_remapper = self . path_remapper . clone ( ) ;
4621+ let source_uri = uri. clone ( ) ;
4622+ self . find_reference_queue . queue_task (
4623+ TelemetryEventKind :: FindFromDefinition ,
4624+ Box :: new ( move |server, _telemetry, telemetry_event, _, _| {
4625+ telemetry_event. set_activity_key ( activity_key) ;
4626+ let mut transaction = server. state . cancellable_transaction ( ) ;
4627+ server
4628+ . cancellation_handles
4629+ . lock ( )
4630+ . insert ( request_id. clone ( ) , transaction. get_cancellation_handle ( ) ) ;
4631+ server. validate_in_memory_for_transaction (
4632+ transaction. as_mut ( ) ,
4633+ telemetry_event,
4634+ None ,
4635+ ) ;
4636+
4637+ let mut lenses = Vec :: new ( ) ;
4638+ for target in targets {
4639+ let local_results = match transaction. find_global_references_from_definition (
4640+ * handle. sys_info ( ) ,
4641+ target. definition . metadata ,
4642+ TextRangeWithModule :: new (
4643+ target. definition . module . clone ( ) ,
4644+ target. definition . definition_range ,
4645+ ) ,
4646+ false ,
4647+ ) {
4648+ Ok ( results) => results,
4649+ Err ( Cancelled ) => {
4650+ let message = format ! ( "Request {request_id} is canceled" ) ;
4651+ info ! ( "{message}" ) ;
4652+ server. connection . send ( Message :: Response ( Response :: new_err (
4653+ request_id,
4654+ ErrorCode :: RequestCanceled as i32 ,
4655+ message,
4656+ ) ) ) ;
4657+ return ;
4658+ }
4659+ } ;
4660+
4661+ let mut locations = Vec :: new ( ) ;
4662+ for ( info, ranges) in local_results {
4663+ if let Some ( uri) = module_info_to_uri ( & info, path_remapper. as_ref ( ) ) {
4664+ for range in ranges {
4665+ locations. push ( Location {
4666+ uri : uri. clone ( ) ,
4667+ range : info. to_lsp_range ( range) ,
4668+ } ) ;
4669+ }
4670+ }
4671+ }
4672+
4673+ let reference_count = locations. len ( ) ;
4674+ let title = if reference_count == 1 {
4675+ "1 reference" . to_owned ( )
4676+ } else {
4677+ format ! ( "{reference_count} references" )
4678+ } ;
4679+ lenses. push ( CodeLens {
4680+ range : target. range ,
4681+ command : Some ( Command {
4682+ title,
4683+ command : "editor.action.showReferences" . to_owned ( ) ,
4684+ arguments : Some ( vec ! [
4685+ serde_json:: to_value( & source_uri)
4686+ . expect( "URI should serialize for code lens" ) ,
4687+ serde_json:: to_value( target. range. start)
4688+ . expect( "Position should serialize for code lens" ) ,
4689+ serde_json:: to_value( & locations)
4690+ . expect( "Locations should serialize for code lens" ) ,
4691+ ] ) ,
4692+ } ) ,
4693+ data : None ,
4694+ } ) ;
4695+ }
4696+
4697+ server. cancellation_handles . lock ( ) . remove ( & request_id) ;
4698+ server. connection . send ( Message :: Response ( new_response (
4699+ request_id,
4700+ Ok ( Some ( lenses) ) ,
4701+ ) ) ) ;
4702+ } ) ,
4703+ ) ;
4704+ }
4705+
45114706 fn rename < ' a > (
45124707 & ' a self ,
45134708 request_id : RequestId ,
0 commit comments