Skip to content

Commit 7504637

Browse files
committed
fix: new line in heredoc
1 parent c52f1c7 commit 7504637

7 files changed

Lines changed: 231 additions & 47 deletions

File tree

src/parser/scalar.js

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ module.exports = {
2626
return text.replace(/\\\\/g, "\\").replace(/\\'/g, "'");
2727
}
2828
return text
29-
.replace(/\\"/, '"')
29+
.replace(/\\"/g, '"')
3030
.replace(
3131
/\\([\\$nrtfve]|[xX][0-9a-fA-F]{1,2}|[0-7]{1,3}|u{([0-9a-fA-F]+)})/g,
3232
($match, p1, p2) => {
@@ -342,13 +342,16 @@ module.exports = {
342342
"string",
343343
false,
344344
this.version >= 703 && !this.lexer.heredoc_label.finished
345-
? this.remove_heredoc_leading_whitespace_chars(
346-
this.resolve_special_chars(text, isDoubleQuote),
347-
this.lexer.heredoc_label.indentation,
348-
this.lexer.heredoc_label.indentation_uses_spaces,
349-
this.lexer.heredoc_label.first_encaps_node,
345+
? this.resolve_special_chars(
346+
this.remove_heredoc_leading_whitespace_chars(
347+
text,
348+
this.lexer.heredoc_label.indentation,
349+
this.lexer.heredoc_label.indentation_uses_spaces,
350+
this.lexer.heredoc_label.first_encaps_node,
351+
),
352+
isDoubleQuote,
350353
)
351-
: text,
354+
: this.resolve_special_chars(text, isDoubleQuote),
352355
false,
353356
text,
354357
);
@@ -447,6 +450,7 @@ module.exports = {
447450
value.push(this.read_encapsed_string_item(true));
448451
}
449452
if (
453+
type === this.ast.encapsed.TYPE_HEREDOC &&
450454
value.length > 0 &&
451455
value[value.length - 1].kind === "encapsedpart" &&
452456
value[value.length - 1].expression.kind === "string"

test/snapshot/__snapshots__/heredoc.test.js.snap

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,59 @@
11
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
22

3+
exports[`heredoc Can parse HEREDOC with escaped characters #1130 1`] = `
4+
Program {
5+
"children": [
6+
If {
7+
"alternate": null,
8+
"body": Block {
9+
"children": [
10+
Echo {
11+
"expressions": [
12+
Encapsed {
13+
"kind": "encapsed",
14+
"label": "STR",
15+
"raw": "<<<STR
16+
\\na
17+
STR",
18+
"type": "heredoc",
19+
"value": [
20+
EncapsedPart {
21+
"curly": false,
22+
"expression": String {
23+
"isDoubleQuote": false,
24+
"kind": "string",
25+
"raw": " \\na
26+
",
27+
"unicode": false,
28+
"value": "
29+
a",
30+
},
31+
"kind": "encapsedpart",
32+
"syntax": null,
33+
},
34+
],
35+
},
36+
],
37+
"kind": "echo",
38+
"shortForm": false,
39+
},
40+
],
41+
"kind": "block",
42+
},
43+
"kind": "if",
44+
"shortForm": false,
45+
"test": Boolean {
46+
"kind": "boolean",
47+
"raw": "true",
48+
"value": true,
49+
},
50+
},
51+
],
52+
"errors": [],
53+
"kind": "program",
54+
}
55+
`;
56+
357
exports[`heredoc Can't parse multiple flexible nowdoc blocks with different indentation #508 1`] = `
458
Program {
559
"children": [

test/snapshot/__snapshots__/location.test.js.snap

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4860,7 +4860,8 @@ command;
48604860
"value": "
48614861
command;
48624862
command;
4863-
command;",
4863+
command;
4864+
",
48644865
},
48654866
"kind": "encapsedpart",
48664867
"loc": Location {

test/snapshot/__snapshots__/loop.test.js.snap

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,8 @@ Program {
9090
"raw": "
9191
",
9292
"unicode": false,
93-
"value": "",
93+
"value": "
94+
",
9495
},
9596
"kind": "encapsedpart",
9697
"syntax": null,
@@ -195,7 +196,8 @@ Program {
195196
"raw": "
196197
",
197198
"unicode": false,
198-
"value": "",
199+
"value": "
200+
",
199201
},
200202
"kind": "encapsedpart",
201203
"syntax": null,
@@ -458,7 +460,8 @@ Program {
458460
"raw": "
459461
",
460462
"unicode": false,
461-
"value": "",
463+
"value": "
464+
",
462465
},
463466
"kind": "encapsedpart",
464467
"syntax": null,
@@ -535,7 +538,8 @@ Program {
535538
"raw": "
536539
",
537540
"unicode": false,
538-
"value": "",
541+
"value": "
542+
",
539543
},
540544
"kind": "encapsedpart",
541545
"syntax": null,

test/snapshot/__snapshots__/string.test.js.snap

Lines changed: 135 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,52 +2,69 @@
22

33
exports[`Test strings binary cast 1`] = `
44
Program {
5-
"children": Array [
5+
"children": [
66
Echo {
7-
"arguments": Array [
7+
"expressions": [
88
Cast {
9-
"kind": "cast",
10-
"type": "string",
11-
"what": Encapsed {
9+
"expr": Encapsed {
1210
"kind": "encapsed",
13-
"raw": "\\"\\\\colors[1] contains >$colors[1]<\\\\n\\"",
11+
"raw": ""\\colors[1] contains >$colors[1]<\\n"",
1412
"type": "string",
15-
"value": Array [
16-
String {
17-
"isDoubleQuote": false,
18-
"kind": "string",
19-
"raw": "\\\\colors[1] contains >",
20-
"value": "\\\\colors[1] contains >",
21-
},
22-
OffsetLookup {
23-
"kind": "offsetlookup",
24-
"offset": Number {
25-
"kind": "number",
26-
"value": "1",
13+
"value": [
14+
EncapsedPart {
15+
"curly": false,
16+
"expression": String {
17+
"isDoubleQuote": false,
18+
"kind": "string",
19+
"raw": "\\colors[1] contains >",
20+
"unicode": false,
21+
"value": "\\colors[1] contains >",
2722
},
28-
"what": Variable {
29-
"byref": false,
30-
"curly": false,
31-
"kind": "variable",
32-
"name": "colors",
23+
"kind": "encapsedpart",
24+
"syntax": null,
25+
},
26+
EncapsedPart {
27+
"curly": false,
28+
"expression": OffsetLookup {
29+
"kind": "offsetlookup",
30+
"offset": Number {
31+
"kind": "number",
32+
"value": "1",
33+
},
34+
"what": Variable {
35+
"curly": false,
36+
"kind": "variable",
37+
"name": "colors",
38+
},
3339
},
40+
"kind": "encapsedpart",
41+
"syntax": "simple",
3442
},
35-
String {
36-
"isDoubleQuote": false,
37-
"kind": "string",
38-
"raw": "<\\\\n",
39-
"value": "<
43+
EncapsedPart {
44+
"curly": false,
45+
"expression": String {
46+
"isDoubleQuote": false,
47+
"kind": "string",
48+
"raw": "<\\n",
49+
"unicode": false,
50+
"value": "<
4051
",
52+
},
53+
"kind": "encapsedpart",
54+
"syntax": null,
4155
},
4256
],
4357
},
58+
"kind": "cast",
59+
"raw": "(binary)",
60+
"type": "binary",
4461
},
4562
],
4663
"kind": "echo",
4764
"shortForm": false,
4865
},
4966
],
50-
"errors": Array [],
67+
"errors": [],
5168
"kind": "program",
5269
}
5370
`;
@@ -1314,7 +1331,8 @@ Program {
13141331
"kind": "string",
13151332
"raw": "\\n",
13161333
"unicode": false,
1317-
"value": "",
1334+
"value": "
1335+
",
13181336
},
13191337
"kind": "encapsedpart",
13201338
"syntax": null,
@@ -1702,6 +1720,63 @@ Program {
17021720
}
17031721
`;
17041722
1723+
exports[`Test strings heredoc ... 1`] = `
1724+
Program {
1725+
"children": [
1726+
ExpressionStatement {
1727+
"expression": Assign {
1728+
"kind": "assign",
1729+
"left": Variable {
1730+
"curly": false,
1731+
"kind": "variable",
1732+
"name": "fallbackContent",
1733+
},
1734+
"operator": ".=",
1735+
"right": Call {
1736+
"arguments": [
1737+
Encapsed {
1738+
"kind": "encapsed",
1739+
"label": "EOF2",
1740+
"raw": "<<<EOF2
1741+
\\$catalogue%s = new MessageCatalogue('%s', %s);
1742+
\\$catalogue%s->addFallbackCatalogue(\\$catalogue%s);
1743+
EOF2",
1744+
"type": "heredoc",
1745+
"value": [
1746+
EncapsedPart {
1747+
"curly": false,
1748+
"expression": String {
1749+
"isDoubleQuote": false,
1750+
"kind": "string",
1751+
"raw": " \\$catalogue%s = new MessageCatalogue('%s', %s);
1752+
\\$catalogue%s->addFallbackCatalogue(\\$catalogue%s);
1753+
",
1754+
"unicode": false,
1755+
"value": "$catalogue%s = new MessageCatalogue('%s', %s);
1756+
$catalogue%s->addFallbackCatalogue($catalogue%s);",
1757+
},
1758+
"kind": "encapsedpart",
1759+
"syntax": null,
1760+
},
1761+
],
1762+
},
1763+
],
1764+
"kind": "call",
1765+
"what": Name {
1766+
"kind": "name",
1767+
"name": "sprintf",
1768+
"resolution": "uqn",
1769+
},
1770+
},
1771+
},
1772+
"kind": "expressionstatement",
1773+
},
1774+
],
1775+
"errors": [],
1776+
"kind": "program",
1777+
}
1778+
`;
1779+
17051780
exports[`Test strings implement #116 1`] = `
17061781
Program {
17071782
"children": [
@@ -1731,6 +1806,34 @@ bar",
17311806
}
17321807
`;
17331808
1809+
exports[`Test strings multiple escaped double quotes 1`] = `
1810+
Program {
1811+
"children": [
1812+
ExpressionStatement {
1813+
"expression": Assign {
1814+
"kind": "assign",
1815+
"left": Variable {
1816+
"curly": false,
1817+
"kind": "variable",
1818+
"name": "var",
1819+
},
1820+
"operator": "=",
1821+
"right": String {
1822+
"isDoubleQuote": true,
1823+
"kind": "string",
1824+
"raw": ""say \\"hello\\" and \\"bye\\""",
1825+
"unicode": false,
1826+
"value": "say "hello" and "bye"",
1827+
},
1828+
},
1829+
"kind": "expressionstatement",
1830+
},
1831+
],
1832+
"errors": [],
1833+
"kind": "program",
1834+
}
1835+
`;
1836+
17341837
exports[`Test strings single (2) 1`] = `
17351838
Program {
17361839
"children": [
@@ -2346,7 +2449,8 @@ Program {
23462449
"kind": "string",
23472450
"raw": "<\\n",
23482451
"unicode": false,
2349-
"value": "<",
2452+
"value": "<
2453+
",
23502454
},
23512455
"kind": "encapsedpart",
23522456
"syntax": null,

test/snapshot/heredoc.test.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,4 +505,16 @@ $b = <<<'EOT'
505505
),
506506
).toMatchSnapshot();
507507
});
508+
509+
it("Can parse HEREDOC with escaped characters #1130", () => {
510+
expect(
511+
parser.parseEval(`
512+
if (true) {
513+
echo <<<STR
514+
\\na
515+
STR;
516+
}
517+
`),
518+
).toMatchSnapshot();
519+
});
508520
});

0 commit comments

Comments
 (0)