@@ -9,13 +9,12 @@ use crate::ast::ParsedSqlFile;
99
1010/// Structure for holding a location in the file. Assumes file is first split by
1111/// lines and then split by characters (column)
12- #[ derive( Debug , PartialEq , PartialOrd ) ]
12+ #[ derive( Debug , Eq , PartialEq , PartialOrd ) ]
1313pub struct Location {
1414 line : u64 ,
1515 column : u64 ,
1616}
1717
18-
1918impl Location {
2019 /// Method for instantiating a new [`Location`]
2120 ///
@@ -47,7 +46,7 @@ impl Default for Location {
4746}
4847
4948/// A structure for holding the span of comments found
50- #[ derive( Debug , PartialEq ) ]
49+ #[ derive( Debug , Eq , PartialEq ) ]
5150pub struct Span {
5251 start : Location ,
5352 end : Location ,
@@ -84,10 +83,9 @@ impl Default for Span {
8483 }
8584}
8685
87-
8886/// Enum for holding the comment content, differentiated by single line `--` and
8987/// multiline `/* */`
90- #[ derive( Clone , Debug , PartialEq ) ]
88+ #[ derive( Clone , Debug , Eq , PartialEq ) ]
9189pub enum CommentKind {
9290 /// Enum variant for Multiline Comments
9391 MultiLine ( String ) ,
@@ -223,7 +221,12 @@ impl Comments {
223221 }
224222
225223 /// Build all leading comments from a parsed SQL file
226- #[ must_use]
224+ ///
225+ /// # Parameters
226+ /// - `file`: the [`ParsedSqlFile`] that needs to be parsed for comments
227+ ///
228+ /// # Errors
229+ /// - Will return [`CommentError::UnmatchedBlockCommentStart`] if a comment does not have an opening `/*`
227230 pub fn parse_all_comments_from_file ( file : & ParsedSqlFile ) -> CommentResult < Self > {
228231 let src = file. content ( ) ;
229232 let mut comments = Vec :: new ( ) ;
@@ -238,6 +241,46 @@ impl Comments {
238241 /// - `src` which is the `SQL` file content as a [`str`]
239242 fn scan_comments ( src : & str ) -> CommentResult < Self > {
240243 let mut comments = Vec :: new ( ) ;
244+ let mut current_line = 0u64 ;
245+ let mut current_column = 0u64 ;
246+
247+ let mut start_line = 0u64 ;
248+ let mut start_column = 0u64 ;
249+
250+ let mut current_comment = String :: new ( ) ;
251+ let mut src_state_machine = src. chars ( ) . peekable ( ) ;
252+ while let Some ( c) = src_state_machine. next ( ) {
253+ match c {
254+ '-' => {
255+ if current_column < 2 {
256+ current_comment. push ( c) ;
257+ }
258+ }
259+ '/' => {
260+ if current_column == 0 || current_comment. contains ( "/*" ) {
261+ current_comment. push ( c) ;
262+ }
263+ }
264+ '*' => {
265+ current_comment. push ( c) ;
266+ }
267+ '\n' => {
268+ if !current_comment. is_empty ( ) {
269+ current_comment. clear ( ) ;
270+ }
271+ current_line += 1 ;
272+ current_column = 0 ;
273+ }
274+ _ => {
275+ if current_comment. contains ( "--" ) || current_comment. contains ( "/*" ) {
276+ current_comment. push ( c) ;
277+ }
278+ }
279+ }
280+ if c != '\n' {
281+ current_column += 1 ;
282+ }
283+ }
241284
242285 Ok ( Self { comments } )
243286 }
@@ -254,71 +297,60 @@ impl Comments {
254297}
255298
256299#[ cfg( test) ]
257- use super :: * ;
300+ use super :: * ;
258301
259- #[ test]
260- fn location_new_and_default ( ) {
261- let mut location = Location :: new ( 2 , 5 ) ;
262- location. column = 20 ;
263- location. line = 43 ;
302+ #[ test]
303+ fn location_new_and_default ( ) {
304+ let mut location = Location :: new ( 2 , 5 ) ;
305+ location. column = 20 ;
306+ location. line = 43 ;
264307
265- assert_eq ! (
266- Location { column: 20 , line: 43 } ,
267- location
268- ) ;
269-
270- let location2 = Location :: default ( ) ;
271- assert_eq ! ( location2, Location { line: 0 , column: 0 } ) ;
272- }
308+ assert_eq ! ( Location { column: 20 , line: 43 } , location) ;
273309
274-
275- #[ test]
276- fn span_default_and_updates ( ) {
277- let default = Span :: default ( ) ;
278- assert_eq ! ( default . start, Location :: default ( ) ) ;
279- assert_eq ! ( default . end, Location :: default ( ) ) ;
280-
281- let mut span = Span :: default ( ) ;
282- span. end = Location :: new ( 55 , 100 ) ;
310+ let location2 = Location :: default ( ) ;
311+ assert_eq ! ( location2, Location { line: 0 , column: 0 } ) ;
312+ }
283313
284- assert_eq ! ( span. start, Location :: default ( ) ) ;
285- assert_eq ! ( span. end, Location { line: 55 , column: 100 } ) ;
286- }
314+ #[ test]
315+ fn span_default_and_updates ( ) {
316+ let default = Span :: default ( ) ;
317+ assert_eq ! ( default . start, Location :: default ( ) ) ;
318+ assert_eq ! ( default . end, Location :: default ( ) ) ;
287319
320+ let mut span = Span :: default ( ) ;
321+ span. end = Location :: new ( 55 , 100 ) ;
288322
289- #[ test]
290- fn comments_with_comment_kind ( ) {
291- let raw_comment = "-- a comment" ;
292- let len = raw_comment. len ( ) as u64 ;
323+ assert_eq ! ( span. start, Location :: default ( ) ) ;
324+ assert_eq ! ( span. end, Location { line: 55 , column: 100 } ) ;
325+ }
293326
294- let singleline = CommentKind :: SingleLine ( raw_comment. to_string ( ) ) ;
295- let mut span = Span :: default ( ) ;
296- span. end . column = len - 1 ;
327+ #[ test]
328+ fn comments_with_comment_kind ( ) {
329+ let raw_comment = "-- a comment" ;
330+ let len = raw_comment. len ( ) as u64 ;
297331
298- let comment = Comment :: new ( singleline. clone ( ) , span) ;
332+ let singleline = CommentKind :: SingleLine ( raw_comment. to_string ( ) ) ;
333+ let mut span = Span :: default ( ) ;
334+ span. end . column = len - 1 ;
299335
300- assert_eq ! ( comment . kind , singleline ) ;
336+ let comment = Comment :: new ( singleline . clone ( ) , span ) ;
301337
302- let expected_span = Span :: new (
303- Location { line : 0 , column : 0 } ,
304- Location { line : 0 , column : len - 1 } ,
305- ) ;
338+ assert_eq ! ( comment. kind, singleline) ;
306339
307- assert_eq ! ( comment . span , expected_span) ;
308- }
340+ let expected_span =
341+ Span :: new ( Location { line : 0 , column : 0 } , Location { line : 0 , column : len - 1 } ) ;
309342
310- #[ test]
311- fn multiline_comment_span ( ) {
312- let kind = CommentKind :: MultiLine ( "/* hello\n world */" . to_string ( ) ) ;
313- let span = Span :: new (
314- Location { line : 1 , column : 0 } ,
315- Location { line : 2 , column : 9 } ,
316- ) ;
343+ assert_eq ! ( comment. span, expected_span) ;
344+ }
317345
318- let comment = Comment :: new ( kind. clone ( ) , span) ;
346+ #[ test]
347+ fn multiline_comment_span ( ) {
348+ let kind = CommentKind :: MultiLine ( "/* hello\n world */" . to_string ( ) ) ;
349+ let span = Span :: new ( Location { line : 1 , column : 0 } , Location { line : 2 , column : 9 } ) ;
319350
320- assert_eq ! ( comment. kind, kind) ;
321- assert_eq ! ( comment. span. start. line, 1 ) ;
322- assert_eq ! ( comment. span. end. line, 2 ) ;
323- }
351+ let comment = Comment :: new ( kind. clone ( ) , span) ;
324352
353+ assert_eq ! ( comment. kind, kind) ;
354+ assert_eq ! ( comment. span. start. line, 1 ) ;
355+ assert_eq ! ( comment. span. end. line, 2 ) ;
356+ }
0 commit comments