@@ -54,6 +54,8 @@ defmodule NextLS do
54
54
alias NextLS.Progress
55
55
alias NextLS.Runtime
56
56
57
+ require NextLS.Runtime
58
+
57
59
def start_link ( args ) do
58
60
{ args , opts } =
59
61
Keyword . split ( args , [
@@ -63,7 +65,9 @@ defmodule NextLS do
63
65
:runtime_task_supervisor ,
64
66
:dynamic_supervisor ,
65
67
:extensions ,
66
- :registry
68
+ :registry ,
69
+ :bundle_base ,
70
+ :mix_home
67
71
] )
68
72
69
73
GenLSP . start_link ( __MODULE__ , args , opts )
@@ -74,6 +78,8 @@ defmodule NextLS do
74
78
task_supervisor = Keyword . fetch! ( args , :task_supervisor )
75
79
runtime_task_supervisor = Keyword . fetch! ( args , :runtime_task_supervisor )
76
80
dynamic_supervisor = Keyword . fetch! ( args , :dynamic_supervisor )
81
+ bundle_base = Keyword . get ( args , :bundle_base , Path . expand ( "~/.cache/elixir-tools/nextls" ) )
82
+ mixhome = Keyword . get ( args , :mix_home , Path . expand ( "~/.mix" ) )
77
83
78
84
registry = Keyword . fetch! ( args , :registry )
79
85
@@ -83,6 +89,8 @@ defmodule NextLS do
83
89
cache = Keyword . fetch! ( args , :cache )
84
90
{ :ok , logger } = DynamicSupervisor . start_child ( dynamic_supervisor , { NextLS.Logger , lsp: lsp } )
85
91
92
+ NextLS.Runtime.BundledElixir . install ( bundle_base , logger , mix_home: mixhome )
93
+
86
94
{ :ok ,
87
95
assign ( lsp ,
88
96
auto_update: Keyword . get ( args , :auto_update , false ) ,
@@ -588,13 +596,16 @@ defmodule NextLS do
588
596
end )
589
597
|> Enum . join ( "\n " )
590
598
591
- env =
599
+ ast =
592
600
spliced
593
- |> Spitfire . parse ( literal_encoder: & { :ok , { :__literal__ , & 2 , [ & 1 ] } } )
601
+ |> Spitfire . parse ( literal_encoder: & { :ok , { :__block__ , & 2 , [ & 1 ] } } )
594
602
|> then ( fn
595
603
{ :ok , ast } -> ast
596
604
{ :error , ast , _ } -> ast
597
605
end )
606
+
607
+ env =
608
+ ast
598
609
|> NextLS.ASTHelpers . find_cursor ( )
599
610
|> then ( fn
600
611
{ :ok , cursor } ->
@@ -627,6 +638,23 @@ defmodule NextLS do
627
638
dispatch ( lsp . assigns . registry , :runtimes , fn entries ->
628
639
[ { wuri , result } ] =
629
640
for { runtime , % { uri: wuri } } <- entries , String . starts_with? ( uri , wuri ) do
641
+ ast =
642
+ spliced
643
+ |> Spitfire . parse ( )
644
+ |> then ( fn
645
+ { :ok , ast } -> ast
646
+ { :error , ast , _ } -> ast
647
+ end )
648
+
649
+ { :ok , { _ , _ , _ , macro_env } } = Runtime . expand ( runtime , ast , Path . basename ( uri ) )
650
+
651
+ env =
652
+ env
653
+ |> Map . put ( :functions , macro_env . functions )
654
+ |> Map . put ( :macros , macro_env . macros )
655
+ |> Map . put ( :aliases , macro_env . aliases )
656
+ |> Map . put ( :attrs , macro_env . attrs )
657
+
630
658
{ wuri ,
631
659
document_slice
632
660
|> String . to_charlist ( )
@@ -652,7 +680,7 @@ defmodule NextLS do
652
680
{ "#{ name } /#{ symbol . arity } " , GenLSP.Enumerations.CompletionItemKind . function ( ) , symbol . docs }
653
681
654
682
:module ->
655
- { name , GenLSP.Enumerations.CompletionItemKind . module ( ) , "" }
683
+ { name , GenLSP.Enumerations.CompletionItemKind . module ( ) , symbol . docs }
656
684
657
685
:variable ->
658
686
{ name , GenLSP.Enumerations.CompletionItemKind . variable ( ) , "" }
@@ -666,6 +694,12 @@ defmodule NextLS do
666
694
:keyword ->
667
695
{ name , GenLSP.Enumerations.CompletionItemKind . field ( ) , "" }
668
696
697
+ :attribute ->
698
+ { name , GenLSP.Enumerations.CompletionItemKind . property ( ) , "" }
699
+
700
+ :sigil ->
701
+ { name , GenLSP.Enumerations.CompletionItemKind . function ( ) , "" }
702
+
669
703
_ ->
670
704
{ name , GenLSP.Enumerations.CompletionItemKind . text ( ) , "" }
671
705
end
@@ -838,6 +872,18 @@ defmodule NextLS do
838
872
839
873
parent = self ( )
840
874
875
+ elixir_bin_path =
876
+ cond do
877
+ lsp . assigns . init_opts . elixir_bin_path != nil ->
878
+ lsp . assigns . init_opts . elixir_bin_path
879
+
880
+ lsp . assigns . init_opts . experimental . completions . enable ->
881
+ NextLS.Runtime.BundledElixir . binpath ( )
882
+
883
+ true ->
884
+ "elixir" |> System . find_executable ( ) |> Path . dirname ( )
885
+ end
886
+
841
887
for % { uri: uri , name: name } <- lsp . assigns . workspace_folders do
842
888
token = Progress . token ( )
843
889
Progress . start ( lsp , token , "Initializing NextLS runtime for folder #{ name } ..." )
@@ -859,6 +905,7 @@ defmodule NextLS do
859
905
uri: uri ,
860
906
mix_env: lsp . assigns . init_opts . mix_env ,
861
907
mix_target: lsp . assigns . init_opts . mix_target ,
908
+ elixir_bin_path: elixir_bin_path ,
862
909
on_initialized: fn status ->
863
910
if status == :ready do
864
911
Progress . stop ( lsp , token , "NextLS runtime for folder #{ name } has initialized!" )
@@ -870,7 +917,7 @@ defmodule NextLS do
870
917
for { pid , _ } <- entries , do: send ( pid , msg )
871
918
end )
872
919
873
- send ( parent , msg )
920
+ Process . send ( parent , msg , [ ] )
874
921
else
875
922
Progress . stop ( lsp , token )
876
923
@@ -884,7 +931,7 @@ defmodule NextLS do
884
931
)
885
932
end
886
933
887
- { :noreply , lsp }
934
+ { :noreply , assign ( lsp , elixir_bin_path: elixir_bin_path ) }
888
935
end
889
936
890
937
def handle_notification ( % TextDocumentDidSave { } , % { assigns: % { ready: false } } = lsp ) do
@@ -956,7 +1003,7 @@ defmodule NextLS do
956
1003
} ,
957
1004
lsp
958
1005
) do
959
- dispatch ( lsp . assigns . registry , :runtime_supervisors , fn entries ->
1006
+ NextLS.Registry . dispatch ( lsp . assigns . registry , :runtime_supervisors , fn entries ->
960
1007
names = Enum . map ( entries , fn { _ , % { name: name } } -> name end )
961
1008
962
1009
for % { name: name , uri: uri } <- added , name not in names do
@@ -976,6 +1023,7 @@ defmodule NextLS do
976
1023
runtime: [
977
1024
task_supervisor: lsp . assigns . runtime_task_supervisor ,
978
1025
working_dir: working_dir ,
1026
+ elixir_bin_path: lsp . assigns . elixir_bin_path ,
979
1027
uri: uri ,
980
1028
mix_env: lsp . assigns . init_opts . mix_env ,
981
1029
mix_target: lsp . assigns . init_opts . mix_target ,
@@ -1019,47 +1067,51 @@ defmodule NextLS do
1019
1067
lsp =
1020
1068
for % { type: type , uri: uri } <- changes , reduce: lsp do
1021
1069
lsp ->
1070
+ file = URI . parse ( uri ) . path
1071
+
1022
1072
cond do
1023
1073
type == GenLSP.Enumerations.FileChangeType . created ( ) ->
1024
- with { :ok , text } <- File . read ( URI . parse ( uri ) . path ) do
1074
+ with { :ok , text } <- File . read ( file ) do
1025
1075
put_in ( lsp . assigns . documents [ uri ] , String . split ( text , "\n " ) )
1026
1076
else
1027
1077
_ -> lsp
1028
1078
end
1029
1079
1030
1080
type == GenLSP.Enumerations.FileChangeType . changed ( ) ->
1031
- with { :ok , text } <- File . read ( URI . parse ( uri ) . path ) do
1081
+ with { :ok , text } <- File . read ( file ) do
1032
1082
put_in ( lsp . assigns . documents [ uri ] , String . split ( text , "\n " ) )
1033
1083
else
1034
1084
_ -> lsp
1035
1085
end
1036
1086
1037
1087
type == GenLSP.Enumerations.FileChangeType . deleted ( ) ->
1038
- dispatch ( lsp . assigns . registry , :databases , fn entries ->
1039
- for { pid , _ } <- entries do
1040
- file = URI . parse ( uri ) . path
1041
-
1042
- NextLS.DB . query (
1043
- pid ,
1044
- ~Q"""
1045
- DELETE FROM symbols
1046
- WHERE symbols.file = ?;
1047
- """ ,
1048
- [ file ]
1049
- )
1050
-
1051
- NextLS.DB . query (
1052
- pid ,
1053
- ~Q"""
1054
- DELETE FROM 'references' AS refs
1055
- WHERE refs.file = ?;
1056
- """ ,
1057
- [ file ]
1058
- )
1059
- end
1060
- end )
1088
+ if not File . exists? ( file ) do
1089
+ dispatch ( lsp . assigns . registry , :databases , fn entries ->
1090
+ for { pid , _ } <- entries do
1091
+ NextLS.DB . query (
1092
+ pid ,
1093
+ ~Q"""
1094
+ DELETE FROM symbols
1095
+ WHERE symbols.file = ?;
1096
+ """ ,
1097
+ [ file ]
1098
+ )
1099
+
1100
+ NextLS.DB . query (
1101
+ pid ,
1102
+ ~Q"""
1103
+ DELETE FROM 'references' AS refs
1104
+ WHERE refs.file = ?;
1105
+ """ ,
1106
+ [ file ]
1107
+ )
1108
+ end
1109
+ end )
1061
1110
1062
- update_in ( lsp . assigns . documents , & Map . drop ( & 1 , [ uri ] ) )
1111
+ update_in ( lsp . assigns . documents , & Map . drop ( & 1 , [ uri ] ) )
1112
+ else
1113
+ lsp
1114
+ end
1063
1115
end
1064
1116
end
1065
1117
@@ -1136,25 +1188,28 @@ defmodule NextLS do
1136
1188
end
1137
1189
1138
1190
def handle_info ( { :runtime_ready , name , runtime_pid } , lsp ) do
1139
- token = Progress . token ( )
1140
- Progress . start ( lsp , token , "Compiling #{ name } ..." )
1191
+ case NextLS.Registry . dispatch ( lsp . assigns . registry , :databases , fn entries ->
1192
+ Enum . find ( entries , fn { _ , % { runtime: runtime } } -> runtime == name end )
1193
+ end ) do
1194
+ { _ , % { mode: mode } } ->
1195
+ token = Progress . token ( )
1196
+ Progress . start ( lsp , token , "Compiling #{ name } ..." )
1141
1197
1142
- { _ , % { mode: mode } } =
1143
- dispatch ( lsp . assigns . registry , :databases , fn entries ->
1144
- Enum . find ( entries , fn { _ , % { runtime: runtime } } -> runtime == name end )
1145
- end )
1198
+ ref = make_ref ( )
1199
+ Runtime . compile ( runtime_pid , caller_ref: ref , force: mode == :reindex )
1146
1200
1147
- ref = make_ref ( )
1148
- Runtime . compile ( runtime_pid , caller_ref: ref , force: mode == :reindex )
1201
+ refresh_refs = Map . put ( lsp . assigns . refresh_refs , ref , { token , "Compiled #{ name } !" } )
1149
1202
1150
- refresh_refs = Map . put ( lsp . assigns . refresh_refs , ref , { token , "Compiled #{ name } !" } )
1203
+ { :noreply , assign ( lsp , ready: true , refresh_refs: refresh_refs ) }
1151
1204
1152
- { :noreply , assign ( lsp , ready: true , refresh_refs: refresh_refs ) }
1205
+ nil ->
1206
+ { :noreply , assign ( lsp , ready: true ) }
1207
+ end
1153
1208
end
1154
1209
1155
1210
def handle_info ( { :runtime_failed , name , status } , lsp ) do
1156
1211
{ pid , % { init_arg: init_arg } } =
1157
- dispatch ( lsp . assigns . registry , :runtime_supervisors , fn entries ->
1212
+ NextLS.Registry . dispatch ( lsp . assigns . registry , :runtime_supervisors , fn entries ->
1158
1213
Enum . find ( entries , fn { _pid , % { name: n } } -> n == name end )
1159
1214
end )
1160
1215
@@ -1186,6 +1241,7 @@ defmodule NextLS do
1186
1241
)
1187
1242
1188
1243
File . rm_rf! ( Path . join ( init_arg [ :runtime ] [ :working_dir ] , ".elixir-tools/_build" ) )
1244
+ File . rm_rf! ( Path . join ( init_arg [ :runtime ] [ :working_dir ] , ".elixir-tools/_build2" ) )
1189
1245
1190
1246
case System . cmd ( "mix" , [ "deps.get" ] ,
1191
1247
env: [ { "MIX_ENV" , "dev" } , { "MIX_BUILD_ROOT" , ".elixir-tools/_build" } ] ,
@@ -1267,6 +1323,9 @@ defmodule NextLS do
1267
1323
1268
1324
receive do
1269
1325
{ ^ ref , result } -> result
1326
+ after
1327
+ 1000 ->
1328
+ :timeout
1270
1329
end
1271
1330
end
1272
1331
@@ -1441,6 +1500,7 @@ defmodule NextLS do
1441
1500
1442
1501
defstruct mix_target: "host" ,
1443
1502
mix_env: "dev" ,
1503
+ elixir_bin_path: nil ,
1444
1504
experimental: % NextLS.InitOpts.Experimental { } ,
1445
1505
extensions: % NextLS.InitOpts.Extensions { }
1446
1506
@@ -1450,6 +1510,8 @@ defmodule NextLS do
1450
1510
schema ( __MODULE__ , % {
1451
1511
optional ( :mix_target ) => str ( ) ,
1452
1512
optional ( :mix_env ) => str ( ) ,
1513
+ optional ( :mix_env ) => str ( ) ,
1514
+ optional ( :elixir_bin_path ) => str ( ) ,
1453
1515
optional ( :experimental ) =>
1454
1516
schema ( NextLS.InitOpts.Experimental , % {
1455
1517
optional ( :completions ) =>
0 commit comments