diff --git a/Cargo.toml b/Cargo.toml index 7d1e6a5c..b9b242cf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cssparser" -version = "0.20.2" +version = "0.21.0" authors = [ "Simon Sapin " ] description = "Rust implementation of CSS Syntax Level 3" diff --git a/src/parser.rs b/src/parser.rs index 4887becd..3c3482db 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -35,7 +35,7 @@ impl ParserState { pub fn source_location(&self) -> SourceLocation { SourceLocation { line: self.current_line_number, - column: (self.position - self.current_line_start_position) as u32, + column: (self.position - self.current_line_start_position + 1) as u32, } } } diff --git a/src/tests.rs b/src/tests.rs index 24242d5f..3f275a5e 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -498,29 +498,29 @@ fn line_numbers() { "b\"" )); let mut input = Parser::new(&mut input); - assert_eq!(input.current_source_location(), SourceLocation { line: 0, column: 0 }); + assert_eq!(input.current_source_location(), SourceLocation { line: 0, column: 1 }); assert_eq!(input.next_including_whitespace(), Ok(&Token::Ident("fo00o".into()))); - assert_eq!(input.current_source_location(), SourceLocation { line: 1, column: 2 }); - assert_eq!(input.next_including_whitespace(), Ok(&Token::WhiteSpace(" "))); assert_eq!(input.current_source_location(), SourceLocation { line: 1, column: 3 }); + assert_eq!(input.next_including_whitespace(), Ok(&Token::WhiteSpace(" "))); + assert_eq!(input.current_source_location(), SourceLocation { line: 1, column: 4 }); assert_eq!(input.next_including_whitespace(), Ok(&Token::Ident("bar".into()))); - assert_eq!(input.current_source_location(), SourceLocation { line: 1, column: 6 }); + assert_eq!(input.current_source_location(), SourceLocation { line: 1, column: 7 }); assert_eq!(input.next_including_whitespace_and_comments(), Ok(&Token::Comment("\n"))); - assert_eq!(input.current_source_location(), SourceLocation { line: 2, column: 2 }); + assert_eq!(input.current_source_location(), SourceLocation { line: 2, column: 3 }); assert_eq!(input.next_including_whitespace(), Ok(&Token::Ident("baz".into()))); - assert_eq!(input.current_source_location(), SourceLocation { line: 2, column: 5 }); + assert_eq!(input.current_source_location(), SourceLocation { line: 2, column: 6 }); let state = input.state(); assert_eq!(input.next_including_whitespace(), Ok(&Token::WhiteSpace("\r\n\n"))); - assert_eq!(input.current_source_location(), SourceLocation { line: 4, column: 0 }); + assert_eq!(input.current_source_location(), SourceLocation { line: 4, column: 1 }); - assert_eq!(state.source_location(), SourceLocation { line: 2, column: 5 }); + assert_eq!(state.source_location(), SourceLocation { line: 2, column: 6 }); assert_eq!(input.next_including_whitespace(), Ok(&Token::UnquotedUrl("u".into()))); - assert_eq!(input.current_source_location(), SourceLocation { line: 6, column: 1 }); + assert_eq!(input.current_source_location(), SourceLocation { line: 6, column: 2 }); assert_eq!(input.next_including_whitespace(), Ok(&Token::QuotedString("ab".into()))); - assert_eq!(input.current_source_location(), SourceLocation { line: 7, column: 2 }); + assert_eq!(input.current_source_location(), SourceLocation { line: 7, column: 3 }); assert!(input.next_including_whitespace().is_err()); } @@ -1000,14 +1000,14 @@ fn parser_maintains_current_line() { fn parser_with_line_number_offset() { let mut input = ParserInput::new_with_line_number_offset("ident\nident", 72); let mut parser = Parser::new(&mut input); - assert_eq!(parser.current_source_location(), SourceLocation { line: 72, column: 0 }); + assert_eq!(parser.current_source_location(), SourceLocation { line: 72, column: 1 }); assert_eq!(parser.next_including_whitespace_and_comments(), Ok(&Token::Ident("ident".into()))); - assert_eq!(parser.current_source_location(), SourceLocation { line: 72, column: 5 }); + assert_eq!(parser.current_source_location(), SourceLocation { line: 72, column: 6 }); assert_eq!(parser.next_including_whitespace_and_comments(), Ok(&Token::WhiteSpace("\n".into()))); - assert_eq!(parser.current_source_location(), SourceLocation { line: 73, column: 0 }); + assert_eq!(parser.current_source_location(), SourceLocation { line: 73, column: 1 }); assert_eq!(parser.next_including_whitespace_and_comments(), Ok(&Token::Ident("ident".into()))); - assert_eq!(parser.current_source_location(), SourceLocation { line: 73, column: 5 }); + assert_eq!(parser.current_source_location(), SourceLocation { line: 73, column: 6 }); } #[test] @@ -1088,24 +1088,24 @@ fn utf16_columns() { // the column is in units of UTF-16, the 4-byte sequence results // in two columns. let tests = vec![ - ("", 0), - ("ascii", 5), - ("/*Qฮกโœˆ๐Ÿ†’*/", 9), - ("'Qฮกโœˆ๐Ÿ†’*'", 8), - ("\"\\\"'Qฮกโœˆ๐Ÿ†’*'", 11), - ("\\Q\\ฮก\\โœˆ\\๐Ÿ†’", 9), - ("Qฮกโœˆ๐Ÿ†’", 5), - ("Qฮกโœˆ๐Ÿ†’\\Q\\ฮก\\โœˆ\\๐Ÿ†’", 14), - ("newline\r\nQฮกโœˆ๐Ÿ†’", 5), - ("url(Qฮกโœˆ๐Ÿ†’\\Q\\ฮก\\โœˆ\\๐Ÿ†’)", 19), - ("url(Qฮกโœˆ๐Ÿ†’)", 10), - ("url(\r\nQฮกโœˆ๐Ÿ†’\\Q\\ฮก\\โœˆ\\๐Ÿ†’)", 15), - ("url(\r\nQฮกโœˆ๐Ÿ†’\\Q\\ฮก\\โœˆ\\๐Ÿ†’", 14), - ("url(\r\nQฮกโœˆ๐Ÿ†’\\Q\\ฮก\\โœˆ\\๐Ÿ†’ x", 16), - ("Qฮกโœˆ๐Ÿ†’()", 7), + ("", 1), + ("ascii", 6), + ("/*Qฮกโœˆ๐Ÿ†’*/", 10), + ("'Qฮกโœˆ๐Ÿ†’*'", 9), + ("\"\\\"'Qฮกโœˆ๐Ÿ†’*'", 12), + ("\\Q\\ฮก\\โœˆ\\๐Ÿ†’", 10), + ("Qฮกโœˆ๐Ÿ†’", 6), + ("Qฮกโœˆ๐Ÿ†’\\Q\\ฮก\\โœˆ\\๐Ÿ†’", 15), + ("newline\r\nQฮกโœˆ๐Ÿ†’", 6), + ("url(Qฮกโœˆ๐Ÿ†’\\Q\\ฮก\\โœˆ\\๐Ÿ†’)", 20), + ("url(Qฮกโœˆ๐Ÿ†’)", 11), + ("url(\r\nQฮกโœˆ๐Ÿ†’\\Q\\ฮก\\โœˆ\\๐Ÿ†’)", 16), + ("url(\r\nQฮกโœˆ๐Ÿ†’\\Q\\ฮก\\โœˆ\\๐Ÿ†’", 15), + ("url(\r\nQฮกโœˆ๐Ÿ†’\\Q\\ฮก\\โœˆ\\๐Ÿ†’ x", 17), + ("Qฮกโœˆ๐Ÿ†’()", 8), // Test that under/over-flow of current_line_start_position is // handled properly; see the special case in consume_4byte_intro. - ("๐Ÿ†’", 2), + ("๐Ÿ†’", 3), ]; for test in tests { diff --git a/src/tokenizer.rs b/src/tokenizer.rs index d9060fb7..9eb94f3e 100644 --- a/src/tokenizer.rs +++ b/src/tokenizer.rs @@ -276,7 +276,7 @@ impl<'a> Tokenizer<'a> { pub fn current_source_location(&self) -> SourceLocation { SourceLocation { line: self.current_line_number, - column: (self.position - self.current_line_start_position) as u32, + column: (self.position - self.current_line_start_position + 1) as u32, } } @@ -521,8 +521,8 @@ pub struct SourceLocation { /// The line number, starting at 0 for the first line, unless `with_first_line_number` was used. pub line: u32, - /// The column number within a line, starting at 0 for first the character of the line. - /// Column numbers are in units of UTF-16 characters. + /// The column number within a line, starting at 1 for first the character of the line. + /// Column numbers are counted in UTF-16 code units. pub column: u32, }