diff options
author | Amaan Qureshi <amaanq12@gmail.com> | 2023-09-20 09:47:24 -0400 |
---|---|---|
committer | Amaan Qureshi <amaanq12@gmail.com> | 2023-09-20 11:31:53 -0400 |
commit | ef9cabd4b5e1eda9d5d3b9377f2bee4e781dafdf (patch) | |
tree | c7b885d3c0b738c04aadbbdd5fd34a90730e1941 | |
parent | e0f54611ad5eda618a91b5410cf41383e759229a (diff) |
fix: update javascript tests and use cpp/javascript master for fixtures
-rw-r--r-- | cli/src/tests/highlight_test.rs | 42 | ||||
-rw-r--r-- | cli/src/tests/parser_test.rs | 12 | ||||
-rw-r--r-- | cli/src/tests/query_test.rs | 70 | ||||
-rw-r--r-- | cli/src/tests/test_highlight_test.rs | 7 | ||||
-rwxr-xr-x | script/fetch-fixtures | 4 | ||||
-rw-r--r-- | test/fixtures/error_corpus/javascript_errors.txt | 8 |
6 files changed, 72 insertions, 71 deletions
diff --git a/cli/src/tests/highlight_test.rs b/cli/src/tests/highlight_test.rs index e400b047..12c120ab 100644 --- a/cli/src/tests/highlight_test.rs +++ b/cli/src/tests/highlight_test.rs @@ -62,7 +62,7 @@ lazy_static! { fn test_highlighting_javascript() { let source = "const a = function(b) { return b + c; }"; assert_eq!( - &to_token_vector(&source, &JS_HIGHLIGHT).unwrap(), + &to_token_vector(source, &JS_HIGHLIGHT).unwrap(), &[vec![ ("const", vec!["keyword"]), (" ", vec![]), @@ -72,14 +72,14 @@ fn test_highlighting_javascript() { (" ", vec![]), ("function", vec!["keyword"]), ("(", vec!["punctuation.bracket"]), - ("b", vec!["variable.parameter"]), + ("b", vec!["variable"]), (")", vec!["punctuation.bracket"]), (" ", vec![]), ("{", vec!["punctuation.bracket"]), (" ", vec![]), ("return", vec!["keyword"]), (" ", vec![]), - ("b", vec!["variable.parameter"]), + ("b", vec!["variable"]), (" ", vec![]), ("+", vec!["operator"]), (" ", vec![]), @@ -93,7 +93,7 @@ fn test_highlighting_javascript() { #[test] fn test_highlighting_injected_html_in_javascript() { - let source = vec!["const s = html `<div>${a < b}</div>`;"].join("\n"); + let source = ["const s = html `<div>${a < b}</div>`;"].join("\n"); assert_eq!( &to_token_vector(&source, &JS_HIGHLIGHT).unwrap(), @@ -157,7 +157,7 @@ fn test_highlighting_injected_javascript_in_html_mini() { #[test] fn test_highlighting_injected_javascript_in_html() { - let source = vec![ + let source = [ "<body>", " <script>", " const x = new Thing();", @@ -212,7 +212,7 @@ fn test_highlighting_injected_javascript_in_html() { #[test] fn test_highlighting_multiline_nodes_to_html() { - let source = vec![ + let source = [ "const SOMETHING = `", " one ${", " two()", @@ -236,7 +236,7 @@ fn test_highlighting_multiline_nodes_to_html() { #[test] fn test_highlighting_with_local_variable_tracking() { - let source = vec![ + let source = [ "module.exports = function a(b) {", " const module = c;", " console.log(module, b);", @@ -258,7 +258,7 @@ fn test_highlighting_with_local_variable_tracking() { (" ", vec![]), ("a", vec!["function"]), ("(", vec!["punctuation.bracket"]), - ("b", vec!["variable.parameter"]), + ("b", vec!["variable"]), (")", vec!["punctuation.bracket"]), (" ", vec![]), ("{", vec!["punctuation.bracket"]) @@ -285,7 +285,7 @@ fn test_highlighting_with_local_variable_tracking() { (",", vec!["punctuation.delimiter"]), (" ", vec![]), // A parameter, because `b` was defined as a parameter above. - ("b", vec!["variable.parameter"]), + ("b", vec!["variable"]), (")", vec!["punctuation.bracket"]), (";", vec!["punctuation.delimiter"]), ], @@ -296,7 +296,7 @@ fn test_highlighting_with_local_variable_tracking() { #[test] fn test_highlighting_empty_lines() { - let source = vec![ + let source = [ "class A {", "", " b(c) {", @@ -314,7 +314,7 @@ fn test_highlighting_empty_lines() { &[ "<span class=keyword>class</span> <span class=constructor>A</span> <span class=punctuation.bracket>{</span>\n".to_string(), "\n".to_string(), - " <span class=function>b</span><span class=punctuation.bracket>(</span><span class=variable.parameter>c</span><span class=punctuation.bracket>)</span> <span class=punctuation.bracket>{</span>\n".to_string(), + " <span class=function>b</span><span class=punctuation.bracket>(</span><span class=variable>c</span><span class=punctuation.bracket>)</span> <span class=punctuation.bracket>{</span>\n".to_string(), "\n".to_string(), " <span class=function>d</span><span class=punctuation.bracket>(</span><span class=variable>e</span><span class=punctuation.bracket>)</span>\n".to_string(), "\n".to_string(), @@ -330,7 +330,7 @@ fn test_highlighting_carriage_returns() { let source = "a = \"a\rb\"\r\nb\r"; assert_eq!( - &to_html(&source, &JS_HIGHLIGHT).unwrap(), + &to_html(source, &JS_HIGHLIGHT).unwrap(), &[ "<span class=variable>a</span> <span class=operator>=</span> <span class=string>"a<span class=carriage-return></span>b"</span>\n", "<span class=variable>b</span>\n", @@ -340,7 +340,7 @@ fn test_highlighting_carriage_returns() { #[test] fn test_highlighting_ejs_with_html_and_javascript() { - let source = vec!["<div><% foo() %></div><script> bar() </script>"].join("\n"); + let source = ["<div><% foo() %></div><script> bar() </script>"].join("\n"); assert_eq!( &to_token_vector(&source, &EJS_HIGHLIGHT).unwrap(), @@ -377,7 +377,7 @@ fn test_highlighting_ejs_with_html_and_javascript() { fn test_highlighting_javascript_with_jsdoc() { // Regression test: the middle comment has no highlights. This should not prevent // later injections from highlighting properly. - let source = vec!["a /* @see a */ b; /* nothing */ c; /* @see b */"].join("\n"); + let source = ["a /* @see a */ b; /* nothing */ c; /* @see b */"].join("\n"); assert_eq!( &to_token_vector(&source, &JS_HIGHLIGHT).unwrap(), @@ -405,7 +405,7 @@ fn test_highlighting_javascript_with_jsdoc() { #[test] fn test_highlighting_with_content_children_included() { - let source = vec!["assert!(", " a.b.c() < D::e::<F>()", ");"].join("\n"); + let source = ["assert!(", " a.b.c() < D::e::<F>()", ");"].join("\n"); assert_eq!( &to_token_vector(&source, &RUST_HIGHLIGHT).unwrap(), @@ -483,7 +483,7 @@ fn test_highlighting_cancellation() { #[test] fn test_highlighting_via_c_api() { - let highlights = vec![ + let highlights = [ "class=tag\0", "class=function\0", "class=string\0", @@ -622,11 +622,11 @@ fn test_highlighting_with_all_captures_applied() { [ \"{\" \"}\" \"(\" \")\" ] @punctuation.bracket "}; let mut rust_highlight_reverse = - HighlightConfiguration::new(language, "rust", &highlights_query, "", "", true).unwrap(); + HighlightConfiguration::new(language, "rust", highlights_query, "", "", true).unwrap(); rust_highlight_reverse.configure(&HIGHLIGHT_NAMES); assert_eq!( - &to_token_vector(&source, &rust_highlight_reverse).unwrap(), + &to_token_vector(source, &rust_highlight_reverse).unwrap(), &[[ ("fn", vec!["keyword"]), (" ", vec![]), @@ -743,20 +743,20 @@ fn to_token_vector<'a>( } HighlightEvent::Source { start, end } => { let s = str::from_utf8(&src[start..end]).unwrap(); - for (i, l) in s.split("\n").enumerate() { + for (i, l) in s.split('\n').enumerate() { let l = l.trim_end_matches('\r'); if i > 0 { lines.push(line); line = Vec::new(); } - if l.len() > 0 { + if !l.is_empty() { line.push((l, highlights.clone())); } } } } } - if line.len() > 0 { + if !line.is_empty() { lines.push(line); } Ok(lines) diff --git a/cli/src/tests/parser_test.rs b/cli/src/tests/parser_test.rs index d490b78f..99616f56 100644 --- a/cli/src/tests/parser_test.rs +++ b/cli/src/tests/parser_test.rs @@ -148,7 +148,7 @@ fn test_parsing_with_custom_utf8_input() { ) ); assert_eq!(root.kind(), "source_file"); - assert_eq!(root.has_error(), false); + assert!(!root.has_error()); assert_eq!(root.child(0).unwrap().kind(), "function_item"); } @@ -187,7 +187,7 @@ fn test_parsing_with_custom_utf16_input() { "(source_file (function_item (visibility_modifier) name: (identifier) parameters: (parameters) body: (block (integer_literal))))" ); assert_eq!(root.kind(), "source_file"); - assert_eq!(root.has_error(), false); + assert!(!root.has_error()); assert_eq!(root.child(0).unwrap().kind(), "function_item"); } @@ -834,7 +834,7 @@ fn test_parsing_with_one_included_range() { concat!( "(program (expression_statement (call_expression ", "function: (member_expression object: (identifier) property: (property_identifier)) ", - "arguments: (arguments (string)))))", + "arguments: (arguments (string (string_fragment))))))", ) ); assert_eq!( @@ -1183,7 +1183,7 @@ fn test_parsing_with_a_newly_included_range() { .set_included_ranges(&[simple_range(range1_start, range1_end)]) .unwrap(); let tree = parser - .parse_with(&mut chunked_input(&source_code, 3), None) + .parse_with(&mut chunked_input(source_code, 3), None) .unwrap(); assert_eq!( tree.root_node().to_sexp(), @@ -1202,7 +1202,7 @@ fn test_parsing_with_a_newly_included_range() { ]) .unwrap(); let tree2 = parser - .parse_with(&mut chunked_input(&source_code, 3), Some(&tree)) + .parse_with(&mut chunked_input(source_code, 3), Some(&tree)) .unwrap(); assert_eq!( tree2.root_node().to_sexp(), @@ -1226,7 +1226,7 @@ fn test_parsing_with_a_newly_included_range() { simple_range(range3_start, range3_end), ]) .unwrap(); - let tree3 = parser.parse(&source_code, Some(&tree)).unwrap(); + let tree3 = parser.parse(source_code, Some(&tree)).unwrap(); assert_eq!( tree3.root_node().to_sexp(), concat!( diff --git a/cli/src/tests/query_test.rs b/cli/src/tests/query_test.rs index 5fb33e01..13e4f8d0 100644 --- a/cli/src/tests/query_test.rs +++ b/cli/src/tests/query_test.rs @@ -323,16 +323,16 @@ fn test_query_errors_on_impossible_patterns() { assert_eq!( Query::new( js_lang, - "(binary_expression left: (identifier) left: (identifier))" + "(binary_expression left: (expression (identifier)) left: (expression (identifier)))" ), Err(QueryError { kind: QueryErrorKind::Structure, row: 0, - offset: 38, - column: 38, + offset: 51, + column: 51, message: [ - "(binary_expression left: (identifier) left: (identifier))", - " ^" + "(binary_expression left: (expression (identifier)) left: (expression (identifier)))", + " ^", ] .join("\n"), }) @@ -437,19 +437,19 @@ fn test_query_errors_on_impossible_patterns() { Query::new( js_lang, "(if_statement - condition: (parenthesized_expression (_expression) @cond))", + condition: (parenthesized_expression (expression) @cond))", ) .unwrap(); assert_eq!( - Query::new(js_lang, "(if_statement condition: (_expression))",), + Query::new(js_lang, "(if_statement condition: (expression))",), Err(QueryError { kind: QueryErrorKind::Structure, row: 0, offset: 14, column: 14, message: [ - "(if_statement condition: (_expression))", // + "(if_statement condition: (expression))", // " ^", ] .join("\n") @@ -1726,7 +1726,7 @@ fn test_query_matches_with_too_many_permutations_to_track() { collect_matches(matches, &query, source.as_str())[0], (0, vec![("pre", "hello"), ("post", "hello")]), ); - assert_eq!(cursor.did_exceed_match_limit(), true); + assert!(cursor.did_exceed_match_limit()); }); } @@ -1775,7 +1775,7 @@ fn test_query_sibling_patterns_dont_match_children_of_an_error() { let mut parser = Parser::new(); parser.set_language(language).unwrap(); - let tree = parser.parse(&source, None).unwrap(); + let tree = parser.parse(source, None).unwrap(); let mut cursor = QueryCursor::new(); let matches = cursor.matches(&query, tree.root_node(), source.as_bytes()); assert_eq!( @@ -1825,7 +1825,7 @@ fn test_query_matches_with_alternatives_and_too_many_permutations_to_track() { collect_matches(matches, &query, source.as_str()), vec![(1, vec![("method", "b")]); 50], ); - assert_eq!(cursor.did_exceed_match_limit(), true); + assert!(cursor.did_exceed_match_limit()); }); } @@ -1956,7 +1956,7 @@ fn test_query_matches_within_byte_range() { let mut parser = Parser::new(); parser.set_language(language).unwrap(); - let tree = parser.parse(&source, None).unwrap(); + let tree = parser.parse(source, None).unwrap(); let mut cursor = QueryCursor::new(); @@ -2086,7 +2086,7 @@ fn test_query_captures_within_byte_range() { let mut parser = Parser::new(); parser.set_language(language).unwrap(); - let tree = parser.parse(&source, None).unwrap(); + let tree = parser.parse(source, None).unwrap(); let mut cursor = QueryCursor::new(); let captures = @@ -2122,7 +2122,7 @@ fn test_query_matches_with_unrooted_patterns_intersecting_byte_range() { let mut parser = Parser::new(); parser.set_language(language).unwrap(); - let tree = parser.parse(&source, None).unwrap(); + let tree = parser.parse(source, None).unwrap(); let mut cursor = QueryCursor::new(); // within the type parameter list @@ -2260,14 +2260,14 @@ fn test_query_captures_within_byte_range_assigned_after_iterating() { let mut parser = Parser::new(); parser.set_language(language).unwrap(); - let tree = parser.parse(&source, None).unwrap(); + let tree = parser.parse(source, None).unwrap(); let mut cursor = QueryCursor::new(); let mut captures = cursor.captures(&query, tree.root_node(), source.as_bytes()); // Retrieve some captures let mut results = Vec::new(); for (mat, capture_ix) in captures.by_ref().take(5) { - let capture = mat.captures[capture_ix as usize]; + let capture = mat.captures[capture_ix]; results.push(( query.capture_names()[capture.index as usize], &source[capture.node.byte_range()], @@ -2290,7 +2290,7 @@ fn test_query_captures_within_byte_range_assigned_after_iterating() { results.clear(); captures.set_byte_range(source.find("Ok").unwrap()..source.len()); for (mat, capture_ix) in captures { - let capture = mat.captures[capture_ix as usize]; + let capture = mat.captures[capture_ix]; results.push(( query.capture_names()[capture.index as usize], &source[capture.node.byte_range()], @@ -2393,7 +2393,7 @@ fn test_query_matches_different_queries_same_cursor() { let mut cursor = QueryCursor::new(); parser.set_language(language).unwrap(); - let tree = parser.parse(&source, None).unwrap(); + let tree = parser.parse(source, None).unwrap(); let matches = cursor.matches(&query1, tree.root_node(), source.as_bytes()); assert_eq!( @@ -2436,7 +2436,7 @@ fn test_query_matches_with_multiple_captures_on_a_node() { let mut cursor = QueryCursor::new(); parser.set_language(language).unwrap(); - let tree = parser.parse(&source, None).unwrap(); + let tree = parser.parse(source, None).unwrap(); let matches = cursor.matches(&query, tree.root_node(), source.as_bytes()); assert_eq!( @@ -2524,7 +2524,7 @@ fn test_query_matches_with_captured_wildcard_at_root() { let mut parser = Parser::new(); let mut cursor = QueryCursor::new(); parser.set_language(language).unwrap(); - let tree = parser.parse(&source, None).unwrap(); + let tree = parser.parse(source, None).unwrap(); let match_capture_names_and_rows = cursor .matches(&query, tree.root_node(), source.as_bytes()) @@ -2790,7 +2790,7 @@ fn test_query_captures_basic() { let mut parser = Parser::new(); parser.set_language(language).unwrap(); - let tree = parser.parse(&source, None).unwrap(); + let tree = parser.parse(source, None).unwrap(); let mut cursor = QueryCursor::new(); let matches = cursor.matches(&query, tree.root_node(), source.as_bytes()); @@ -2873,7 +2873,7 @@ fn test_query_captures_with_text_conditions() { let mut parser = Parser::new(); parser.set_language(language).unwrap(); - let tree = parser.parse(&source, None).unwrap(); + let tree = parser.parse(source, None).unwrap(); let mut cursor = QueryCursor::new(); let captures = cursor.captures(&query, tree.root_node(), source.as_bytes()); @@ -3019,7 +3019,7 @@ fn test_query_captures_with_duplicates() { let mut parser = Parser::new(); parser.set_language(language).unwrap(); - let tree = parser.parse(&source, None).unwrap(); + let tree = parser.parse(source, None).unwrap(); let mut cursor = QueryCursor::new(); let captures = cursor.captures(&query, tree.root_node(), source.as_bytes()); @@ -3221,11 +3221,11 @@ fn test_query_captures_with_too_many_nested_results() { let mut parser = Parser::new(); parser.set_language(language).unwrap(); - let tree = parser.parse(&source, None).unwrap(); + let tree = parser.parse(source, None).unwrap(); let mut cursor = QueryCursor::new(); cursor.set_match_limit(32); let captures = cursor.captures(&query, tree.root_node(), source.as_bytes()); - let captures = collect_captures(captures, &query, &source); + let captures = collect_captures(captures, &query, source); assert_eq!( &captures[0..4], @@ -3284,7 +3284,7 @@ fn test_query_captures_with_definite_pattern_containing_many_nested_matches() { let mut parser = Parser::new(); parser.set_language(language).unwrap(); - let tree = parser.parse(&source, None).unwrap(); + let tree = parser.parse(source, None).unwrap(); let mut cursor = QueryCursor::new(); let captures = cursor.captures(&query, tree.root_node(), source.as_bytes()); @@ -3320,7 +3320,7 @@ fn test_query_captures_ordered_by_both_start_and_end_positions() { let mut parser = Parser::new(); parser.set_language(language).unwrap(); - let tree = parser.parse(&source, None).unwrap(); + let tree = parser.parse(source, None).unwrap(); let mut cursor = QueryCursor::new(); let captures = cursor.captures(&query, tree.root_node(), source.as_bytes()); @@ -3361,7 +3361,7 @@ fn test_query_captures_with_matches_removed() { let mut parser = Parser::new(); parser.set_language(language).unwrap(); - let tree = parser.parse(&source, None).unwrap(); + let tree = parser.parse(source, None).unwrap(); let mut cursor = QueryCursor::new(); let mut captured_strings = Vec::new(); @@ -3405,7 +3405,7 @@ fn test_query_captures_with_matches_removed_before_they_finish() { let mut parser = Parser::new(); parser.set_language(language).unwrap(); - let tree = parser.parse(&source, None).unwrap(); + let tree = parser.parse(source, None).unwrap(); let mut cursor = QueryCursor::new(); let mut captured_strings = Vec::new(); @@ -3447,7 +3447,7 @@ fn test_query_captures_and_matches_iterators_are_fused() { let mut parser = Parser::new(); parser.set_language(language).unwrap(); - let tree = parser.parse(&source, None).unwrap(); + let tree = parser.parse(source, None).unwrap(); let mut cursor = QueryCursor::new(); let mut captures = cursor.captures(&query, tree.root_node(), source.as_bytes()); @@ -3521,7 +3521,7 @@ fn test_query_text_callback_returns_chunks() { let mut parser = Parser::new(); parser.set_language(language).unwrap(); - let tree = parser.parse(&source, None).unwrap(); + let tree = parser.parse(source, None).unwrap(); let mut cursor = QueryCursor::new(); let captures = cursor.captures(&query, tree.root_node(), |node: Node| { chunks_in_range(node.byte_range()) @@ -3619,7 +3619,7 @@ fn test_query_lifetime_is_separate_from_nodes_lifetime() { let language = get_language("javascript"); let mut parser = Parser::new(); parser.set_language(language).unwrap(); - let tree = parser.parse(&source, None).unwrap(); + let tree = parser.parse(source, None).unwrap(); fn take_first_node_from_captures<'tree>( source: &str, @@ -3932,10 +3932,10 @@ fn test_query_is_pattern_guaranteed_at_step() { Row { description: "a guaranteed step with a field", language: get_language("javascript"), - pattern: r#"(binary_expression left: (identifier) right: (_))"#, + pattern: r#"(binary_expression left: (expression) right: (_))"#, results_by_substring: &[ ("binary_expression", false), - ("(identifier)", false), + ("(expression)", false), ("(_)", true), ], }, @@ -4002,7 +4002,7 @@ fn test_query_is_pattern_guaranteed_at_step() { "#, results_by_substring: &[ ("identifier", false), - ("property_identifier", true), + ("property_identifier", false), ("[", true), ], }, diff --git a/cli/src/tests/test_highlight_test.rs b/cli/src/tests/test_highlight_test.rs index d9b2c43a..06ad7d59 100644 --- a/cli/src/tests/test_highlight_test.rs +++ b/cli/src/tests/test_highlight_test.rs @@ -12,7 +12,7 @@ fn test_highlight_test_with_basic_test() { Some("injections.scm"), &[ "function".to_string(), - "variable.parameter".to_string(), + "variable".to_string(), "keyword".to_string(), ], ); @@ -22,7 +22,7 @@ fn test_highlight_test_with_basic_test() { " // ^ function", " // ^ keyword", " return d + e;", - " // ^ variable.parameter", + " // ^ variable", " // ^ !variable", "};", ] @@ -35,7 +35,7 @@ fn test_highlight_test_with_basic_test() { &[ Assertion::new(1, 5, false, String::from("function")), Assertion::new(1, 11, false, String::from("keyword")), - Assertion::new(4, 9, false, String::from("variable.parameter")), + Assertion::new(4, 9, false, String::from("variable")), Assertion::new(4, 11, true, String::from("variable")), ] ); @@ -53,6 +53,7 @@ fn test_highlight_test_with_basic_test() { (Point::new(1, 19), Point::new(1, 20), Highlight(1)), // "d" (Point::new(4, 2), Point::new(4, 8), Highlight(2)), // "return" (Point::new(4, 9), Point::new(4, 10), Highlight(1)), // "d" + (Point::new(4, 13), Point::new(4, 14), Highlight(1)), // "e" ] ); } diff --git a/script/fetch-fixtures b/script/fetch-fixtures index eb66d314..1eec16ee 100755 --- a/script/fetch-fixtures +++ b/script/fetch-fixtures @@ -23,12 +23,12 @@ fetch_grammar() { fetch_grammar bash master fetch_grammar c master -fetch_grammar cpp 670404d7c689be1c868a46f919ba2a3912f2b7ef +fetch_grammar cpp master fetch_grammar embedded-template master fetch_grammar go master fetch_grammar html master fetch_grammar java master -fetch_grammar javascript partial-order-precedences +fetch_grammar javascript master fetch_grammar jsdoc master fetch_grammar json master fetch_grammar php master diff --git a/test/fixtures/error_corpus/javascript_errors.txt b/test/fixtures/error_corpus/javascript_errors.txt index 4359ae68..e2f21176 100644 --- a/test/fixtures/error_corpus/javascript_errors.txt +++ b/test/fixtures/error_corpus/javascript_errors.txt @@ -74,8 +74,8 @@ if ({a: 'b'} {c: 'd'}) { (program (if_statement (parenthesized_expression - (ERROR (object (pair (property_identifier) (string)))) - (object (pair (property_identifier) (string)))) + (ERROR (object (pair (property_identifier) (string (string_fragment))))) + (object (pair (property_identifier) (string (string_fragment))))) (statement_block (expression_statement (assignment_expression @@ -178,12 +178,12 @@ function main(x) { (expression_statement (call_expression (member_expression (identifier) (property_identifier)) - (arguments (string)))) + (arguments (string (string_fragment))))) (expression_statement (binary_expression (identifier) (ERROR) (call_expression (member_expression (identifier) (property_identifier)) - (arguments (string))))) + (arguments (string (string_fragment)))))) (return_statement (object))))) |