8
8
use std:: collections:: BTreeMap ;
9
9
use std:: collections:: HashMap ;
10
10
use std:: collections:: HashSet ;
11
+ use std:: sync:: Arc ;
11
12
12
13
use anyhow:: bail;
13
14
use anyhow:: Result ;
@@ -28,6 +29,7 @@ use crate::lsp::documents::Document;
28
29
use crate :: lsp:: encoding:: convert_tree_sitter_range_to_lsp_range;
29
30
use crate :: lsp:: indexer;
30
31
use crate :: lsp:: inputs:: library:: Library ;
32
+ use crate :: lsp:: inputs:: package:: Package ;
31
33
use crate :: lsp:: state:: WorldState ;
32
34
use crate :: lsp:: traits:: node:: NodeExt ;
33
35
use crate :: lsp:: traits:: rope:: RopeExt ;
@@ -826,24 +828,91 @@ fn handle_package_attach_call(node: Node, context: &mut DiagnosticContext) -> an
826
828
} ;
827
829
828
830
let package_name = value. get_identifier_or_string_text ( context. contents ) ?;
831
+ let attach_pos = node. end_position ( ) ;
829
832
830
- // Insert exports for the attached package
831
- if let Some ( package) = context. library . get ( & package_name) {
832
- for symbol in & package. namespace . exports {
833
- let pos = node. end_position ( ) ;
834
- context
835
- . library_symbols
836
- . entry ( pos)
837
- . or_insert_with ( HashSet :: new)
838
- . insert ( symbol. clone ( ) ) ;
833
+ let package = match insert_package_exports ( & package_name, attach_pos, context) {
834
+ Ok ( package) => package,
835
+ Err ( err) => {
836
+ lsp:: log_warn!( "{err:?}" ) ;
837
+ return Ok ( ( ) ) ;
838
+ } ,
839
+ } ;
840
+
841
+ // Also attach packages from `Depends` field
842
+ let mut attach_dependencies = package. description . depends . clone ( ) ;
843
+
844
+ // Special handling for the tidyverse and tidymodels packages. Hard-coded
845
+ // for now but in the future, this should probably be expressed as a
846
+ // `DESCRIPTION` field like `Config/Needs/attach`.
847
+ let attach_field = match package. description . name . as_str ( ) {
848
+ // https://github.com/tidyverse/tidyverse/blob/0231aafb/R/attach.R#L1
849
+ "tidyverse" => {
850
+ vec ! [
851
+ "dplyr" ,
852
+ "readr" ,
853
+ "forcats" ,
854
+ "stringr" ,
855
+ "ggplot2" ,
856
+ "tibble" ,
857
+ "lubridate" ,
858
+ "tidyr" ,
859
+ "purrr" ,
860
+ ]
861
+ } ,
862
+ // https://github.com/tidymodels/tidymodels/blob/aa3f82cf/R/attach.R#L1
863
+ "tidymodels" => {
864
+ vec ! [
865
+ "broom" ,
866
+ "dials" ,
867
+ "dplyr" ,
868
+ "ggplot2" ,
869
+ "infer" ,
870
+ "modeldata" ,
871
+ "parsnip" ,
872
+ "purrr" ,
873
+ "recipes" ,
874
+ "rsample" ,
875
+ "tibble" ,
876
+ "tidyr" ,
877
+ "tune" ,
878
+ "workflows" ,
879
+ "workflowsets" ,
880
+ "yardstick" ,
881
+ ]
882
+ } ,
883
+ _ => vec ! [ ] ,
884
+ } ;
885
+ attach_dependencies. extend ( attach_field. into_iter ( ) . map ( String :: from) ) ;
886
+
887
+ for package_name in attach_dependencies {
888
+ if let Err ( err) = insert_package_exports ( & package_name, attach_pos, context) {
889
+ lsp:: log_warn!( "{err:?}" ) ;
839
890
}
840
- } else {
841
- lsp:: log_warn!( "Can't get exports from package {package_name} because it is not installed." )
842
891
}
843
892
844
893
Ok ( ( ) )
845
894
}
846
895
896
+ fn insert_package_exports (
897
+ package_name : & str ,
898
+ attach_pos : Point ,
899
+ context : & mut DiagnosticContext ,
900
+ ) -> anyhow:: Result < Arc < Package > > {
901
+ let Some ( package) = context. library . get ( package_name) else {
902
+ return Err ( anyhow:: anyhow!(
903
+ "Can't get exports from package {package_name} because it is not installed."
904
+ ) ) ;
905
+ } ;
906
+
907
+ context
908
+ . library_symbols
909
+ . entry ( attach_pos)
910
+ . or_default ( )
911
+ . extend ( package. namespace . exports . iter ( ) . cloned ( ) ) ;
912
+
913
+ Ok ( package)
914
+ }
915
+
847
916
fn recurse_subset_or_subset2 (
848
917
node : Node ,
849
918
context : & mut DiagnosticContext ,
@@ -1030,9 +1099,10 @@ mod tests {
1030
1099
use crate :: lsp:: diagnostics:: generate_diagnostics;
1031
1100
use crate :: lsp:: documents:: Document ;
1032
1101
use crate :: lsp:: inputs:: library:: Library ;
1033
- use crate :: lsp:: inputs:: package:: Description ;
1034
- use crate :: lsp:: inputs:: package:: Namespace ;
1035
1102
use crate :: lsp:: inputs:: package:: Package ;
1103
+ use crate :: lsp:: inputs:: package_description:: Dcf ;
1104
+ use crate :: lsp:: inputs:: package_description:: Description ;
1105
+ use crate :: lsp:: inputs:: package_namespace:: Namespace ;
1036
1106
use crate :: lsp:: state:: WorldState ;
1037
1107
use crate :: r_task;
1038
1108
@@ -1532,6 +1602,7 @@ foo
1532
1602
name : "mockpkg" . to_string ( ) ,
1533
1603
version : "1.0.0" . to_string ( ) ,
1534
1604
depends : vec ! [ ] ,
1605
+ fields : Dcf :: new ( ) ,
1535
1606
} ;
1536
1607
let package = Package {
1537
1608
path : PathBuf :: from ( "/mock/path" ) ,
@@ -1613,6 +1684,7 @@ foo
1613
1684
name : "pkg1" . to_string ( ) ,
1614
1685
version : "1.0.0" . to_string ( ) ,
1615
1686
depends : vec ! [ ] ,
1687
+ fields : Dcf :: new ( ) ,
1616
1688
} ;
1617
1689
let package1 = Package {
1618
1690
path : PathBuf :: from ( "/mock/path1" ) ,
@@ -1630,6 +1702,7 @@ foo
1630
1702
name : "pkg2" . to_string ( ) ,
1631
1703
version : "1.0.0" . to_string ( ) ,
1632
1704
depends : vec ! [ ] ,
1705
+ fields : Dcf :: new ( ) ,
1633
1706
} ;
1634
1707
let package2 = Package {
1635
1708
path : PathBuf :: from ( "/mock/path2" ) ,
@@ -1689,6 +1762,7 @@ foo
1689
1762
name : "pkg" . to_string ( ) ,
1690
1763
version : "1.0.0" . to_string ( ) ,
1691
1764
depends : vec ! [ ] ,
1765
+ fields : Dcf :: new ( ) ,
1692
1766
} ;
1693
1767
let package = Package {
1694
1768
path : PathBuf :: from ( "/mock/path" ) ,
0 commit comments