@@ -2,16 +2,16 @@ use std::borrow::Cow;
22use std:: path:: PathBuf ;
33use std:: str:: FromStr ;
44
5- use serde_json:: { Value , json } ;
5+ use serde_json:: Value ;
66use tokio:: sync:: RwLock ;
77use tower_lsp:: LanguageServer ;
88use tower_lsp:: jsonrpc:: { Error , ErrorCode , Result } ;
99use tower_lsp:: lsp_types:: {
1010 CodeActionOrCommand , CodeActionParams , CodeActionProviderCapability , CodeActionResponse ,
1111 CodeLens , CodeLensOptions , CodeLensParams , Command , DidChangeConfigurationParams ,
1212 DidChangeTextDocumentParams , DidOpenTextDocumentParams , ExecuteCommandOptions ,
13- ExecuteCommandParams , InitializeParams , InitializeResult , InitializedParams , MessageType ,
14- Range , ServerCapabilities , TextDocumentSyncCapability , TextDocumentSyncKind ,
13+ ExecuteCommandParams , InitializeParams , InitializeResult , InitializedParams , Location ,
14+ MessageType , Range , ServerCapabilities , TextDocumentSyncCapability , TextDocumentSyncKind ,
1515} ;
1616use tracing:: { debug, info} ;
1717
@@ -21,6 +21,9 @@ use super::queries::QueryExecutor;
2121use super :: { InMemoryDocumentDatabase , LSPClient } ;
2222use crate :: infra:: { parse_compose_file, parse_dockerfile} ;
2323
24+ mod supported_commands;
25+ use supported_commands:: SupportedCommands ;
26+
2427pub struct LSPServer < C > {
2528 command_executor : CommandExecutor < C > ,
2629 query_executor : QueryExecutor ,
5861 }
5962}
6063
61- pub enum SupportedCommands {
62- ExecuteBaseImageScan ,
63- ExecuteBuildAndScan ,
64- }
65-
66- impl std:: fmt:: Display for SupportedCommands {
67- fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
68- f. write_str ( match self {
69- Self :: ExecuteBaseImageScan => "sysdig-lsp.execute-scan" ,
70- Self :: ExecuteBuildAndScan => "sysdig-lsp.execute-build-and-scan" ,
71- } )
72- }
73- }
74-
75- impl TryFrom < & str > for SupportedCommands {
76- type Error = String ;
77-
78- fn try_from ( value : & str ) -> std:: result:: Result < Self , Self :: Error > {
79- match value {
80- "sysdig-lsp.execute-scan" => Ok ( SupportedCommands :: ExecuteBaseImageScan ) ,
81- "sysdig-lsp.execute-build-and-scan" => Ok ( SupportedCommands :: ExecuteBuildAndScan ) ,
82- _ => Err ( format ! ( "command not supported: {value}" ) ) ,
83- }
84- }
85- }
86-
8764struct CommandInfo {
8865 title : String ,
8966 command : String ,
@@ -115,22 +92,19 @@ where
11592
11693 fn generate_compose_commands (
11794 & self ,
118- uri : & tower_lsp:: lsp_types:: Url ,
95+ url : & tower_lsp:: lsp_types:: Url ,
11996 content : & str ,
12097 ) -> Vec < CommandInfo > {
12198 let mut commands = vec ! [ ] ;
12299 if let Ok ( instructions) = parse_compose_file ( content) {
123100 for instruction in instructions {
124- commands. push ( CommandInfo {
125- title : "Scan base image" . to_string ( ) ,
126- command : SupportedCommands :: ExecuteBaseImageScan . to_string ( ) ,
127- arguments : Some ( vec ! [
128- json!( uri) ,
129- json!( instruction. range) ,
130- json!( instruction. image_name) ,
131- ] ) ,
132- range : instruction. range ,
133- } ) ;
101+ commands. push (
102+ SupportedCommands :: ExecuteBaseImageScan {
103+ location : Location :: new ( url. clone ( ) , instruction. range ) ,
104+ image : instruction. image_name ,
105+ }
106+ . into ( ) ,
107+ ) ;
134108 }
135109 }
136110 commands
@@ -149,21 +123,20 @@ where
149123 . next_back ( )
150124 {
151125 let range = last_from_instruction. range ;
152- let line = last_from_instruction. range . start . line ;
153- commands. push ( CommandInfo {
154- title : "Build and scan" . to_string ( ) ,
155- command : SupportedCommands :: ExecuteBuildAndScan . to_string ( ) ,
156- arguments : Some ( vec ! [ json!( uri) , json!( line) ] ) ,
157- range,
158- } ) ;
159-
160- if let Some ( image_name) = last_from_instruction. arguments . first ( ) {
161- commands. push ( CommandInfo {
162- title : "Scan base image" . to_string ( ) ,
163- command : SupportedCommands :: ExecuteBaseImageScan . to_string ( ) ,
164- arguments : Some ( vec ! [ json!( uri) , json!( range) , json!( image_name) ] ) ,
165- range,
166- } ) ;
126+ commands. push (
127+ SupportedCommands :: ExecuteBuildAndScan {
128+ location : Location :: new ( uri. clone ( ) , range) ,
129+ }
130+ . into ( ) ,
131+ ) ;
132+ if let Some ( image) = last_from_instruction. arguments . first ( ) {
133+ commands. push (
134+ SupportedCommands :: ExecuteBaseImageScan {
135+ location : Location :: new ( uri. clone ( ) , range) ,
136+ image : image. to_owned ( ) ,
137+ }
138+ . into ( ) ,
139+ ) ;
167140 }
168141 }
169142 commands
@@ -196,10 +169,7 @@ where
196169 resolve_provider : Some ( false ) ,
197170 } ) ,
198171 execute_command_provider : Some ( ExecuteCommandOptions {
199- commands : vec ! [
200- SupportedCommands :: ExecuteBaseImageScan . to_string( ) ,
201- SupportedCommands :: ExecuteBuildAndScan . to_string( ) ,
202- ] ,
172+ commands : SupportedCommands :: all_supported_commands_as_string ( ) ,
203173 ..Default :: default ( )
204174 } ) ,
205175 ..Default :: default ( )
@@ -296,20 +266,25 @@ where
296266 }
297267
298268 async fn execute_command ( & self , params : ExecuteCommandParams ) -> Result < Option < Value > > {
299- let command: SupportedCommands = params. command . as_str ( ) . try_into ( ) . map_err ( |e| {
300- Error :: internal_error ( ) . with_message ( format ! ( "unable to parse command: {e}" ) )
301- } ) ?;
269+ let command: SupportedCommands = params. try_into ( ) ?;
270+
271+ let result = match command. clone ( ) {
272+ SupportedCommands :: ExecuteBaseImageScan { location, image } => {
273+ execute_command_scan_base_image (
274+ self ,
275+ location. uri . to_string ( ) ,
276+ location. range ,
277+ image,
278+ )
279+ . await
280+ . map ( |_| None )
281+ }
302282
303- let result = match command {
304- SupportedCommands :: ExecuteBaseImageScan => {
305- execute_command_scan_base_image ( self , & params)
283+ SupportedCommands :: ExecuteBuildAndScan { location } => {
284+ execute_command_build_and_scan ( self , location. uri . to_string ( ) , location. range )
306285 . await
307286 . map ( |_| None )
308287 }
309-
310- SupportedCommands :: ExecuteBuildAndScan => execute_command_build_and_scan ( self , & params)
311- . await
312- . map ( |_| None ) ,
313288 } ;
314289
315290 match result {
@@ -331,32 +306,10 @@ where
331306
332307async fn execute_command_scan_base_image < C : LSPClient > (
333308 server : & LSPServer < C > ,
334- params : & ExecuteCommandParams ,
309+ file : String ,
310+ range : Range ,
311+ image : String ,
335312) -> Result < ( ) > {
336- let Some ( uri) = params. arguments . first ( ) else {
337- return Err ( Error :: internal_error ( ) . with_message ( "no uri was provided" ) ) ;
338- } ;
339-
340- let Some ( uri) = uri. as_str ( ) else {
341- return Err ( Error :: internal_error ( ) . with_message ( "uri is not a string" ) ) ;
342- } ;
343-
344- let Some ( range) = params. arguments . get ( 1 ) else {
345- return Err ( Error :: internal_error ( ) . with_message ( "no range was provided" ) ) ;
346- } ;
347-
348- let Ok ( range) = serde_json:: from_value :: < Range > ( range. clone ( ) ) else {
349- return Err ( Error :: internal_error ( ) . with_message ( "range is not a Range object" ) ) ;
350- } ;
351-
352- let Some ( image_name) = params. arguments . get ( 2 ) else {
353- return Err ( Error :: internal_error ( ) . with_message ( "no image name was provided" ) ) ;
354- } ;
355-
356- let Some ( image_name) = image_name. as_str ( ) else {
357- return Err ( Error :: internal_error ( ) . with_message ( "image name is not a string" ) ) ;
358- } ;
359-
360313 let image_scanner = {
361314 let mut lock = server. component_factory . write ( ) . await ;
362315 lock. image_scanner ( ) . map_err ( |e| {
@@ -366,32 +319,17 @@ async fn execute_command_scan_base_image<C: LSPClient>(
366319
367320 server
368321 . command_executor
369- . scan_image ( uri , range, image_name , & image_scanner)
322+ . scan_image ( & file , range, & image , & image_scanner)
370323 . await ?;
371324
372325 Ok ( ( ) )
373326}
374327
375328async fn execute_command_build_and_scan < C : LSPClient > (
376329 server : & LSPServer < C > ,
377- params : & ExecuteCommandParams ,
330+ file : String ,
331+ range : Range ,
378332) -> Result < ( ) > {
379- let Some ( uri) = params. arguments . first ( ) else {
380- return Err ( Error :: internal_error ( ) . with_message ( "no uri was provided" ) ) ;
381- } ;
382-
383- let Some ( uri) = uri. as_str ( ) else {
384- return Err ( Error :: internal_error ( ) . with_message ( "uri is not a string" ) ) ;
385- } ;
386-
387- let Some ( line) = params. arguments . get ( 1 ) else {
388- return Err ( Error :: internal_error ( ) . with_message ( "no line was provided" ) ) ;
389- } ;
390-
391- let Some ( line) = line. as_u64 ( ) . and_then ( |x| u32:: try_from ( x) . ok ( ) ) else {
392- return Err ( Error :: internal_error ( ) . with_message ( "line is not a u32" ) ) ;
393- } ;
394-
395333 let ( image_scanner, image_builder) = {
396334 let mut factory = server. component_factory . write ( ) . await ;
397335
@@ -408,8 +346,8 @@ async fn execute_command_build_and_scan<C: LSPClient>(
408346 server
409347 . command_executor
410348 . build_and_scan_from_file (
411- & PathBuf :: from_str ( uri ) . unwrap ( ) ,
412- line,
349+ & PathBuf :: from_str ( & file ) . unwrap ( ) ,
350+ range . start . line ,
413351 & image_builder,
414352 & image_scanner,
415353 )
0 commit comments