Strip a single layer of balanced outer parentheses from an expression. `"($a + $b)"` → `"$a + $b"`, but `"foo($x)"` is left unchanged because the parens are part of the call syntax, not a redundant wrapper.
(s: &str)
| 22 | /// `"($a + $b)"` → `"$a + $b"`, but `"foo($x)"` is left unchanged |
| 23 | /// because the parens are part of the call syntax, not a redundant wrapper. |
| 24 | fn strip_outer_parens(s: &str) -> &str { |
| 25 | let bytes = s.as_bytes(); |
| 26 | if bytes.len() < 2 || bytes[0] != b'(' || bytes[bytes.len() - 1] != b')' { |
| 27 | return s; |
| 28 | } |
| 29 | // Walk the interior and verify the opening '(' at position 0 is |
| 30 | // the one that matches the closing ')' at the end. If the depth |
| 31 | // drops to zero before we reach the last character, the outer |
| 32 | // parens are not a matched wrapper (e.g. `(a) + (b)`). |
| 33 | let mut depth: u32 = 0; |
| 34 | for (i, &b) in bytes.iter().enumerate() { |
| 35 | match b { |
| 36 | b'(' => depth += 1, |
| 37 | b')' => { |
| 38 | depth -= 1; |
| 39 | if depth == 0 && i < bytes.len() - 1 { |
| 40 | // Closed before the final character — not an outer wrapper. |
| 41 | return s; |
| 42 | } |
| 43 | } |
| 44 | _ => {} |
| 45 | } |
| 46 | } |
| 47 | // The parens wrap the entire expression — strip them. |
| 48 | s[1..s.len() - 1].trim() |
| 49 | } |
| 50 | |
| 51 | /// Returns `true` when the selected text parses as a valid, self-contained |
| 52 | /// PHP expression. We wrap it in `<?php $__x = <selection>;` and check |
no test coverage detected