11local log = require (' java-core.utils.log' )
2- local lsp = require (' java-core.utils.lsp' )
2+ local adapters = require (' java-core.ls.adapters.test-adapter' )
3+ local List = require (' java-core.utils.list' )
34local JavaDebug = require (' java-core.ls.clients.java-debug-client' )
45local Promise = require (' java-core.utils.promise' )
56
7+ --- @class JavaCoreDap
8+ --- @field client LSPClient
9+ --- @field java_debug JavaCoreDebugClient
610local M = {}
711
8- function M .setup_dap_on_attach ()
9- vim .api .nvim_create_autocmd (' LspAttach' , {
10- pattern = ' *' ,
11- callback = function (a )
12- local client = vim .lsp .get_client_by_id (a .data .client_id )
13-
14- if client .name == ' jdtls' then
15- Promise .all ({
16- M .set_dap_config (),
17- M .set_dap_adapter (),
18- }):catch (function (err )
19- local msg = [[ Faild to set DAP configuration & adapter]]
20-
21- error (msg , err )
22- log .error (msg , err )
23- end )
24- end
25- end ,
26- })
27- end
28-
29- function M .set_dap_config ()
30- log .info (' setting dap configurations for java' )
31-
32- local dap = require (' dap' )
33-
34- return M .get_dap_config ():thenCall (
35- --- @type JavaDapConfigurationList
36- function (res )
37- dap .configurations .java = res
38- end
39- )
40- end
41-
42- function M .set_dap_adapter ()
43- log .info (' setting dap adapter for java' )
12+ --- Returns a new dap instance
13+ --- @param args { client : LSPClient }
14+ --- @return JavaCoreDap
15+ function M :new (args )
16+ local o = {
17+ client = args .client ,
18+ }
4419
45- local dap = require (' dap' )
20+ o .java_debug = JavaDebug :new ({
21+ client = args .client ,
22+ })
4623
47- return M .get_dap_adapter ():thenCall (
48- --- @type JavaDapAdapter
49- function (res )
50- log .debug (' adapter settings: ' , res )
51- dap .adapters .java = res
52- end
53- )
24+ setmetatable (o , self )
25+ self .__index = self
26+ return o
5427end
5528
5629--- @class JavaDapAdapter
6033
6134--- Returns the dap adapter config
6235--- @return Promise
63- function M . get_dap_adapter ()
36+ function M : get_dap_adapter ()
6437 log .info (' creating dap adapter for java' )
6538
66- local client = lsp .get_jdtls_client ()
67-
68- -- @TODO when thrown from the function instead of the promise,
69- -- error handling has to be done in two places
70- if not client then
71- local msg = ' no active jdtls client was found'
72-
73- log .error (msg )
74- error (msg )
75- end
76-
77- local jdtlsClient = JavaDebug :new ({
78- client = client ,
79- })
80-
81- return jdtlsClient :start_debug_session ():thenCall (
39+ return self .java_debug :start_debug_session ():thenCall (
8240 --- @param port JavaDebugStartDebugSessionResponse
8341 function (port )
8442 return {
@@ -90,106 +48,92 @@ function M.get_dap_adapter()
9048 )
9149end
9250
93- --- @class JavaDapConfiguration
94- --- @field name string
95- --- @field projectName string
96- --- @field mainClass string
97- --- @field javaExec string
98- --- @field modulePaths string[]
99- --- @field classPaths string[]
100- --- @field request string
101-
10251--- @alias JavaDapConfigurationList JavaDapConfiguration[]
10352
10453--- Returns the dap configuration for the current project
10554--- @return Promise
106- function M . get_dap_config ()
55+ function M : get_dap_config ()
10756 log .info (' creating dap configuration for java' )
10857
109- local client = lsp .get_jdtls_client ()
58+ return self .java_debug :resolve_main_class ():thenCall (
59+ --- @param mains JavaDebugResolveMainClassResponse
60+ function (mains )
61+ local config_promises = List :new (mains ):map (function (main )
62+ return self :get_dap_config_record (main )
63+ end )
11064
111- if not client then
112- local msg = ' no active jdtls client was found'
65+ return Promise .all (config_promises )
66+ end
67+ )
68+ end
11369
114- log .error (msg )
115- error (msg )
116- end
70+ --- Returns the dap config for the given main class
71+ --- @param main JavaDebugResolveMainClassRecord
72+ --- @return Promise
73+ function M :get_dap_config_record (main )
74+ return Promise .all ({
75+ self .java_debug :resolve_classpath (main .mainClass , main .projectName ),
76+ self .java_debug :resolve_java_executable (main .mainClass , main .projectName ),
77+ }):thenCall (function (res )
78+ --- @type JavaDebugResolveClasspathResponse
79+ local classpaths = res [1 ]
80+
81+ --- @type JavaDebugResolveJavaExecutableResponse
82+ local java_exec = res [2 ]
83+
84+ return adapters .get_dap_config (main , classpaths , java_exec )
85+ end )
86+ end
11787
118- local jdtlsClient = JavaDebug :new ({
119- client = client ,
120- })
88+ --- Dap run with given config
89+ --- @param config JavaDapConfiguration
90+ function M .dap_run (config )
91+ log .info (' running dap with config: ' , config )
92+
93+ local function get_stream_reader (conn )
94+ return vim .schedule_wrap (function (err , buffer )
95+ assert (not err , err )
12196
122- --- @type JavaDebugResolveMainClassResponse
123- local main_classes_info_list
124-
125- return jdtlsClient
126- :resolve_main_class ()
127- :thenCall (
128- --- @param main_classes_info JavaDebugResolveMainClassResponse
129- function (main_classes_info )
130- main_classes_info_list = main_classes_info
131-
132- --- @type Promise[]
133- local classpath_promises = {}
134- --- @type Promise[]
135- local java_exec_promises = {}
136-
137- for _ , single_class_info in ipairs (main_classes_info ) do
138- table.insert (
139- classpath_promises ,
140- jdtlsClient :resolve_classpath (
141- single_class_info .mainClass ,
142- single_class_info .projectName
143- )
144- )
145-
146- table.insert (
147- java_exec_promises ,
148- jdtlsClient :resolve_java_executable (
149- single_class_info .mainClass ,
150- single_class_info .projectName
151- )
152- )
153- end
154-
155- return Promise .all ({
156- Promise .all (classpath_promises ),
157- Promise .all (java_exec_promises ),
158- })
97+ if buffer then
98+ vim .print (buffer )
99+ else
100+ conn :close ()
159101 end
160- )
161- :thenCall (function (result )
162- return M .__get_dap_java_config (
163- main_classes_info_list ,
164- result [1 ],
165- result [2 ]
166- )
167102 end )
168- end
169-
170- function M .__get_dap_java_config (main_classes , classpaths , java_execs )
171- local len = # main_classes
172- local dap_config_list = {}
173-
174- for i = 1 , len do
175- local main_class = main_classes [i ].mainClass
176- local project_name = main_classes [i ].projectName
177- local module_paths = classpaths [i ][1 ]
178- local class_paths = classpaths [i ][2 ]
179-
180- table.insert (dap_config_list , {
181- name = string.format (' %s -> %s' , project_name , main_class ),
182- projectName = project_name ,
183- mainClass = main_class ,
184- javaExec = java_execs [i ],
185- request = ' launch' ,
186- type = ' java' ,
187- modulePaths = module_paths ,
188- classPaths = class_paths ,
189- })
190103 end
191104
192- return dap_config_list
105+ --- @type uv_tcp_t
106+ local server
107+
108+ require (' dap' ).run (config , {
109+ before = function (conf )
110+ log .debug (' running before dap callback' )
111+
112+ server = assert (vim .loop .new_tcp (), ' uv.new_tcp() must return handle' )
113+ server :bind (' 127.0.0.1' , 0 )
114+ server :listen (128 , function (err )
115+ assert (not err , err )
116+
117+ local sock = assert (vim .loop .new_tcp (), ' uv.new_tcp must return handle' )
118+ server :accept (sock )
119+ sock :read_start (get_stream_reader (sock ))
120+ end )
121+
122+ conf .args =
123+ conf .args :gsub (' -port ([0-9]+)' , ' -port ' .. server :getsockname ().port )
124+
125+ return conf
126+ end ,
127+
128+ after = function ()
129+ vim .debug (' running after dap callback' )
130+
131+ if server then
132+ server :shutdown ()
133+ server :close ()
134+ end
135+ end ,
136+ })
193137end
194138
195139return M
0 commit comments