@@ -743,10 +743,11 @@ defmodule NextLS do
743
743
744
744
GenLSP . log ( lsp , "[NextLS] Booting runtimes..." )
745
745
746
+ parent = self ( )
747
+
746
748
for % { uri: uri , name: name } <- lsp . assigns . workspace_folders do
747
749
token = Progress . token ( )
748
750
Progress . start ( lsp , token , "Initializing NextLS runtime for folder #{ name } ..." )
749
- parent = self ( )
750
751
working_dir = URI . parse ( uri ) . path
751
752
752
753
{ :ok , _ } =
@@ -778,6 +779,9 @@ defmodule NextLS do
778
779
send ( parent , msg )
779
780
else
780
781
Progress . stop ( lsp , token )
782
+
783
+ send ( parent , { :runtime_failed , name , status } )
784
+
781
785
GenLSP . error ( lsp , "[NextLS] Runtime for folder #{ name } failed to initialize" )
782
786
end
783
787
end ,
@@ -865,47 +869,47 @@ defmodule NextLS do
865
869
parent = self ( )
866
870
working_dir = URI . parse ( uri ) . path
867
871
868
- # TODO: probably extract this to the Runtime module
869
872
{ :ok , _ } =
870
- DynamicSupervisor . start_child (
871
- lsp . assigns . dynamic_supervisor ,
872
- { NextLS.Runtime.Supervisor ,
873
- path: Path . join ( working_dir , ".elixir-tools" ) ,
874
- name: name ,
875
- registry: lsp . assigns . registry ,
876
- runtime: [
877
- task_supervisor: lsp . assigns . runtime_task_supervisor ,
878
- working_dir: working_dir ,
879
- uri: uri ,
880
- mix_env: lsp . assigns . init_opts . mix_env ,
881
- mix_target: lsp . assigns . init_opts . mix_target ,
882
- on_initialized: fn status ->
883
- if status == :ready do
884
- Progress . stop ( lsp , token , "NextLS runtime for folder #{ name } has initialized!" )
885
- GenLSP . log ( lsp , "[NextLS] Runtime for folder #{ name } is ready..." )
886
- msg = { :runtime_ready , name , self ( ) }
887
-
888
- dispatch ( lsp . assigns . registry , :extensions , fn entries ->
889
- for { pid , _ } <- entries , do: send ( pid , msg )
890
- end )
891
-
892
- send ( parent , msg )
893
- else
894
- Progress . stop ( lsp , token )
895
- GenLSP . error ( lsp , "[NextLS] Runtime for folder #{ name } failed to initialize" )
896
- end
897
- end ,
898
- logger: lsp . assigns . logger
899
- ] }
873
+ NextLS.Runtime . boot ( lsp . assigns . dynamic_supervisor ,
874
+ path: Path . join ( working_dir , ".elixir-tools" ) ,
875
+ name: name ,
876
+ registry: lsp . assigns . registry ,
877
+ runtime: [
878
+ task_supervisor: lsp . assigns . runtime_task_supervisor ,
879
+ working_dir: working_dir ,
880
+ uri: uri ,
881
+ mix_env: lsp . assigns . init_opts . mix_env ,
882
+ mix_target: lsp . assigns . init_opts . mix_target ,
883
+ on_initialized: fn status ->
884
+ if status == :ready do
885
+ Progress . stop ( lsp , token , "NextLS runtime for folder #{ name } has initialized!" )
886
+ GenLSP . log ( lsp , "[NextLS] Runtime for folder #{ name } is ready..." )
887
+
888
+ msg = { :runtime_ready , name , self ( ) }
889
+
890
+ dispatch ( lsp . assigns . registry , :extensions , fn entries ->
891
+ for { pid , _ } <- entries , do: send ( pid , msg )
892
+ end )
893
+
894
+ send ( parent , msg )
895
+ else
896
+ Progress . stop ( lsp , token )
897
+
898
+ send ( parent , { :runtime_failed , name , status } )
899
+
900
+ GenLSP . error ( lsp , "[NextLS] Runtime for folder #{ name } failed to initialize" )
901
+ end
902
+ end ,
903
+ logger: lsp . assigns . logger
904
+ ]
900
905
)
901
906
end
902
907
903
908
names = Enum . map ( removed , & & 1 . name )
904
909
905
910
for { pid , % { name: name } } <- entries , name in names do
906
911
GenLSP . log ( lsp , "[NextLS] Removing workspace folder #{ name } " )
907
- # TODO: probably extract this to the Runtime module
908
- DynamicSupervisor . terminate_child ( lsp . assigns . dynamic_supervisor , pid )
912
+ NextLS.Runtime . stop ( lsp . assigns . dynamic_supervisor , pid )
909
913
end
910
914
end )
911
915
@@ -995,6 +999,72 @@ defmodule NextLS do
995
999
{ :noreply , assign ( lsp , ready: true , refresh_refs: refresh_refs ) }
996
1000
end
997
1001
1002
+ def handle_info ( { :runtime_failed , name , status } , lsp ) do
1003
+ { pid , % { init_arg: init_arg } } =
1004
+ dispatch ( lsp . assigns . registry , :runtime_supervisors , fn entries ->
1005
+ Enum . find ( entries , fn { _pid , % { name: n } } -> n == name end )
1006
+ end )
1007
+
1008
+ :ok = DynamicSupervisor . terminate_child ( lsp . assigns . dynamic_supervisor , pid )
1009
+
1010
+ if status == { :error , :deps } do
1011
+ resp =
1012
+ GenLSP . request (
1013
+ lsp ,
1014
+ % GenLSP.Requests.WindowShowMessageRequest {
1015
+ id: System . unique_integer ( [ :positive ] ) ,
1016
+ params: % GenLSP.Structures.ShowMessageRequestParams {
1017
+ type: GenLSP.Enumerations.MessageType . error ( ) ,
1018
+ message: "The NextLS runtime failed with errors on dependencies. Would you like to re-fetch them?" ,
1019
+ actions: [
1020
+ % GenLSP.Structures.MessageActionItem { title: "yes" } ,
1021
+ % GenLSP.Structures.MessageActionItem { title: "no" }
1022
+ ]
1023
+ }
1024
+ } ,
1025
+ :infinity
1026
+ )
1027
+
1028
+ case resp do
1029
+ % GenLSP.Structures.MessageActionItem { title: "yes" } ->
1030
+ NextLS.Logger . info (
1031
+ lsp . assigns . logger ,
1032
+ "Running `mix deps.get` in directory #{ init_arg [ :runtime ] [ :working_dir ] } "
1033
+ )
1034
+
1035
+ File . rm_rf! ( Path . join ( init_arg [ :runtime ] [ :working_dir ] , ".elixir-tools/_build" ) )
1036
+
1037
+ case System . cmd ( "mix" , [ "deps.get" ] ,
1038
+ env: [ { "MIX_ENV" , "dev" } , { "MIX_BUILD_ROOT" , ".elixir-tools/_build" } ] ,
1039
+ cd: init_arg [ :runtime ] [ :working_dir ] ,
1040
+ stderr_to_stdout: true
1041
+ ) do
1042
+ { msg , 0 } ->
1043
+ NextLS.Logger . info (
1044
+ lsp . assigns . logger ,
1045
+ "Restarting runtime #{ name } for directory #{ init_arg [ :runtime ] [ :working_dir ] } "
1046
+ )
1047
+
1048
+ NextLS.Logger . info ( lsp . assigns . logger , msg )
1049
+
1050
+ { :ok , _ } =
1051
+ DynamicSupervisor . start_child ( lsp . assigns . dynamic_supervisor , { NextLS.Runtime.Supervisor , init_arg } )
1052
+
1053
+ { msg , _ } ->
1054
+ NextLS.Logger . warning (
1055
+ lsp . assigns . logger ,
1056
+ "Failed to run `mix deps.get` in directory #{ init_arg [ :runtime ] [ :working_dir ] } with message: #{ msg } "
1057
+ )
1058
+ end
1059
+
1060
+ _ ->
1061
+ NextLS.Logger . info ( lsp . assigns . logger , "Not running `mix deps.get`" )
1062
+ end
1063
+ end
1064
+
1065
+ { :noreply , lsp }
1066
+ end
1067
+
998
1068
def handle_info ( { ref , _resp } , % { assigns: % { refresh_refs: refs } } = lsp ) when is_map_key ( refs , ref ) do
999
1069
Process . demonitor ( ref , [ :flush ] )
1000
1070
{ { token , msg } , refs } = Map . pop ( refs , ref )
0 commit comments