@@ -163,7 +163,7 @@ fn update_expect() -> bool {
163163 env:: var ( "UPDATE_EXPECT" ) . is_ok ( )
164164}
165165
166- /// Creates an instance of `Expect` from string literal:
166+ /// Creates an instance of `Expect` from a string literal:
167167///
168168/// ```
169169/// # use expect_test::expect;
@@ -190,6 +190,61 @@ macro_rules! expect {
190190 [ [ ] ] => { $crate:: expect![ [ "" ] ] } ;
191191}
192192
193+ /// Creates an instance of `Expect` from a string literal:
194+ ///
195+ /// ```
196+ /// # use expect_test::expect;
197+ /// expect!("
198+ /// Foo { value: 92 }
199+ /// ");
200+ /// expect!(r#"{"Foo": 92}"#);
201+ /// ```
202+ ///
203+ /// Leading indentation is stripped.
204+ ///
205+ /// This uses the `#[track_caller]` attribute to resolve relative file paths.
206+ /// This [may not work as expected][1] if this is called from a function which als uses `#[track_caller]`,
207+ /// or if the toolchain is [configured to strip caller information][2].
208+ /// In these cases you may use the macro form, [`expect!`].
209+ ///
210+ /// [1]: https://github.com/rust-analyzer/expect-test/issues/15#issuecomment-939308821
211+ /// [2]: https://doc.rust-lang.org/beta/unstable-book/compiler-flags/location-detail.html
212+ #[ track_caller]
213+ pub fn expect ( data : impl ExpectedData ) -> Expect {
214+ let location = std:: panic:: Location :: caller ( ) ;
215+ Expect {
216+ position : Position {
217+ file : location. file ( ) ,
218+ line : location. line ( ) ,
219+ column : location. column ( ) ,
220+ } ,
221+ data : data. str ( ) ,
222+ indent : true ,
223+ }
224+ }
225+
226+ pub trait ExpectedData {
227+ fn str ( & self ) -> & ' static str ;
228+ }
229+
230+ impl ExpectedData for & ' static str {
231+ fn str ( & self ) -> & ' static str {
232+ self
233+ }
234+ }
235+
236+ impl ExpectedData for [ & ' static str ; 1 ] {
237+ fn str ( & self ) -> & ' static str {
238+ self [ 0 ]
239+ }
240+ }
241+
242+ impl ExpectedData for [ & ' static str ; 0 ] {
243+ fn str ( & self ) -> & ' static str {
244+ ""
245+ }
246+ }
247+
193248/// Creates an instance of `ExpectFile` from relative or absolute path:
194249///
195250/// ```
@@ -212,9 +267,9 @@ macro_rules! expect_file {
212267/// ```
213268///
214269/// This uses the `#[track_caller]` attribute to resolve relative file paths.
215- /// They [won't work correctly ][1] if this is called from a function which also uses `#[track_caller]`,
270+ /// This [may not work as expected ][1] if this is called from a function which als uses `#[track_caller]`,
216271/// or if the toolchain is [configured to strip caller information][2].
217- /// In these cases you must use the macro form, [`expect_file!`].
272+ /// In these cases you may use the macro form, [`expect_file!`].
218273///
219274/// [1]: https://github.com/rust-analyzer/expect-test/issues/15#issuecomment-939308821
220275/// [2]: https://doc.rust-lang.org/beta/unstable-book/compiler-flags/location-detail.html
@@ -330,22 +385,19 @@ impl Expect {
330385 let mut line_start = 0 ;
331386 for ( i, line) in lines_with_ends ( file) . enumerate ( ) {
332387 if i == self . position . line as usize - 1 {
333- // `column` points to the first character of the macro invocation:
388+ // `column` points to the first character of the macro invocation/function call :
334389 //
335- // expect![[r#""#]] expect! [""]
336- // ^ ^ ^ ^
337- // column offset offset
390+ // expect![[r#""#]] expect![""] expect("") expect( [""])
391+ // ^ ^ ^ ^ ^ ^ ^ ^
392+ // column offset
338393 //
339- // Seek past the exclam, then skip any whitespace and
340- // the macro delimiter to get to our argument.
394+ // we seek until we find the first character of the string literal, if present.
341395 let byte_offset = line
342396 . char_indices ( )
343397 . skip ( ( self . position . column - 1 ) . try_into ( ) . unwrap ( ) )
344- . skip_while ( |& ( _, c) | c != '!' )
345- . skip ( 1 ) // !
346- . skip_while ( |& ( _, c) | c. is_whitespace ( ) )
347- . skip ( 1 ) // [({
348- . skip_while ( |& ( _, c) | c. is_whitespace ( ) )
398+ . skip_while ( |& ( _, c) | !matches ! ( c, '[' | '(' | '{' ) )
399+ // .skip_while(|&(_, c)| matches!(c, '[' | '(' | '{') || c.is_whitespace())
400+ . skip ( 1 )
349401 . next ( )
350402 . expect ( "Failed to parse macro invocation" )
351403 . 0 ;
@@ -365,29 +417,35 @@ impl Expect {
365417 let literal_start = literal_start + ( lit_to_eof. len ( ) - lit_to_eof_trimmed. len ( ) ) ;
366418
367419 let literal_len =
368- locate_end ( lit_to_eof_trimmed) . expect ( "Couldn't find closing delimiter for `expect! `." ) ;
420+ locate_end ( lit_to_eof_trimmed) . expect ( "Couldn't find closing delimiter for `expect`." ) ;
369421 let literal_range = literal_start..literal_start + literal_len;
370422 Location { line_indent, literal_range }
371423 }
372424}
373425
374426fn locate_end ( arg_start_to_eof : & str ) -> Option < usize > {
375- match arg_start_to_eof. chars ( ) . next ( ) ? {
376- c if c. is_whitespace ( ) => panic ! ( "skip whitespace before calling `locate_end`" ) ,
377-
378- // expect![[]]
379- '[' => {
427+ let c = arg_start_to_eof. chars ( ) . next ( ) ?;
428+ if c. is_whitespace ( ) {
429+ panic ! ( "skip whitespace before calling `locate_end`" )
430+ }
431+ match c {
432+ // expect![["..."]] | expect!(["..."])
433+ '[' | '(' => {
434+ let end = if c == '[' { ']' } else { ')' } ;
380435 let str_start_to_eof = arg_start_to_eof[ 1 ..] . trim_start ( ) ;
436+ if str_start_to_eof. chars ( ) . next ( ) == Some ( end) {
437+ return Some ( 2 ) ;
438+ }
381439 let str_len = find_str_lit_len ( str_start_to_eof) ?;
382440 let str_end_to_eof = & str_start_to_eof[ str_len..] ;
383- let closing_brace_offset = str_end_to_eof. find ( ']' ) ?;
441+ let closing_brace_offset = str_end_to_eof. find ( end ) ?;
384442 Some ( ( arg_start_to_eof. len ( ) - str_end_to_eof. len ( ) ) + closing_brace_offset + 1 )
385443 }
386444
387445 // expect![] | expect!{} | expect!()
388446 ']' | '}' | ')' => Some ( 0 ) ,
389447
390- // expect!["..."] | expect![r#"..."#]
448+ // expect!["..."] | expect![r#"..."#] | expect("...")
391449 _ => find_str_lit_len ( arg_start_to_eof) ,
392450 }
393451}
@@ -746,7 +804,14 @@ mod tests {
746804
747805 #[ test]
748806 fn test_trivial_assert ( ) {
749- expect ! [ "5" ] . assert_eq ( "5" ) ;
807+ expect ! [ "1" ] . assert_eq ( "1" ) ;
808+ expect ! [ "2" ] . assert_eq ( "2" ) ;
809+ }
810+
811+ #[ test]
812+ fn test_trivial_assert_fn ( ) {
813+ expect ( "3" ) . assert_eq ( "3" ) ;
814+ expect ( "4" ) . assert_eq ( "4" ) ;
750815 }
751816
752817 #[ test]
@@ -766,15 +831,15 @@ mod tests {
766831 expect ! [ [ r##"[r#"{"foo": 42}"#]"## ] ] . assert_eq ( & patch) ;
767832
768833 let patch = format_patch ( Some ( 0 ) , "hello\n world\n " ) ;
769- expect ! [ [ r##"
834+ expect ( [ r##"
770835 [r#"
771836 hello
772837 world
773- "#]"## ] ]
838+ "#]"## ] )
774839 . assert_eq ( & patch) ;
775840
776841 let patch = format_patch ( Some ( 4 ) , "single line" ) ;
777- expect ! [ [ r#""single line""# ] ] . assert_eq ( & patch) ;
842+ expect ( [ r#""single line""# ] ) . assert_eq ( & patch) ;
778843 }
779844
780845 #[ test]
0 commit comments