@@ -527,6 +527,30 @@ impl<T: LspContext> Backend<T> {
527527 _ => None ,
528528 }
529529 }
530+ DefinitionLocation :: Unresolved { source, name } => {
531+ match self . context . get_url_for_global_symbol ( & uri, & name) ? {
532+ Some ( uri) => {
533+ let loaded_location = self
534+ . get_ast_or_load_from_disk ( & uri) ?
535+ . and_then ( |ast| ast. find_exported_symbol ( & name) ) ;
536+ match loaded_location {
537+ None => Some ( LocationLink {
538+ origin_selection_range : Some ( source. into ( ) ) ,
539+ target_uri : uri. try_into ( ) ?,
540+ target_range : Range :: default ( ) ,
541+ target_selection_range : Range :: default ( ) ,
542+ } ) ,
543+ Some ( loaded_location) => Some ( LocationLink {
544+ origin_selection_range : Some ( source. into ( ) ) ,
545+ target_uri : uri. try_into ( ) ?,
546+ target_range : loaded_location. into ( ) ,
547+ target_selection_range : loaded_location. into ( ) ,
548+ } ) ,
549+ }
550+ }
551+ None => None ,
552+ }
553+ }
530554 } ,
531555 None => None ,
532556 } ;
@@ -1565,4 +1589,91 @@ mod test {
15651589
15661590 Ok ( ( ) )
15671591 }
1592+
1593+ #[ test]
1594+ fn goto_works_for_native_symbols ( ) -> anyhow:: Result < ( ) > {
1595+ let foo_uri = temp_file_uri ( "foo.star" ) ;
1596+ let native_uri = Url :: parse ( "starlark:/native/builtin.bzl" ) ?;
1597+
1598+ let mut server = TestServer :: new ( ) ?;
1599+
1600+ let foo_contents = dedent (
1601+ r#"
1602+ <click_n1>na<n1>t</n1>ive_function1</click_n1>()
1603+ def f(<n2_loc>native_function1</n2_loc>):
1604+ print(<click_n2>nat<n2>i</n2>ve_function1</click_n2>)
1605+ mi<n3>s</n3>sing_global()
1606+ "# ,
1607+ )
1608+ . trim ( )
1609+ . to_owned ( ) ;
1610+ let native_contents = dedent (
1611+ r#"
1612+ def <n1_loc>native_function1</n1_loc>():
1613+ pass
1614+
1615+ def native_function2():
1616+ pass
1617+ "# ,
1618+ )
1619+ . trim ( )
1620+ . to_owned ( ) ;
1621+
1622+ let foo = FixtureWithRanges :: from_fixture ( foo_uri. path ( ) , & foo_contents) ?;
1623+ let native = FixtureWithRanges :: from_fixture ( native_uri. path ( ) , & native_contents) ?;
1624+
1625+ server. open_file ( foo_uri. clone ( ) , foo. program ( ) ) ?;
1626+
1627+ let expected_n1_location = expected_location_link_from_spans (
1628+ native_uri,
1629+ foo. span ( "click_n1" ) ,
1630+ native. span ( "n1_loc" ) ,
1631+ ) ;
1632+
1633+ let goto_definition = goto_definition_request (
1634+ & mut server,
1635+ foo_uri. clone ( ) ,
1636+ foo. begin_line ( "n1" ) ,
1637+ foo. begin_column ( "n1" ) ,
1638+ ) ;
1639+ let request_id = server. send_request ( goto_definition) ?;
1640+ let n1_location = goto_definition_response_location ( & mut server, request_id) ?;
1641+
1642+ assert_eq ! ( expected_n1_location, n1_location) ;
1643+
1644+ let expected_n2_location = expected_location_link_from_spans (
1645+ foo_uri. clone ( ) ,
1646+ foo. span ( "click_n2" ) ,
1647+ foo. span ( "n2_loc" ) ,
1648+ ) ;
1649+
1650+ let goto_definition = goto_definition_request (
1651+ & mut server,
1652+ foo_uri. clone ( ) ,
1653+ foo. begin_line ( "n2" ) ,
1654+ foo. begin_column ( "n2" ) ,
1655+ ) ;
1656+ let request_id = server. send_request ( goto_definition) ?;
1657+ let n2_location = goto_definition_response_location ( & mut server, request_id) ?;
1658+
1659+ assert_eq ! ( expected_n2_location, n2_location) ;
1660+
1661+ let goto_definition = goto_definition_request (
1662+ & mut server,
1663+ foo_uri,
1664+ foo. begin_line ( "n3" ) ,
1665+ foo. begin_column ( "n3" ) ,
1666+ ) ;
1667+ let request_id = server. send_request ( goto_definition) ?;
1668+ let n3_response = server. get_response :: < GotoDefinitionResponse > ( request_id) ?;
1669+ match n3_response {
1670+ GotoDefinitionResponse :: Array ( definitions) if definitions. is_empty ( ) => Ok ( ( ) ) ,
1671+ response => Err ( anyhow:: anyhow!(
1672+ "Expected empty definitions, got `{:?}`" ,
1673+ response
1674+ ) ) ,
1675+ } ?;
1676+
1677+ Ok ( ( ) )
1678+ }
15681679}
0 commit comments