diff --git a/package.xml b/package.xml
index 50b562a931..75b78ea153 100644
--- a/package.xml
+++ b/package.xml
@@ -168,6 +168,8 @@ http://pear.php.net/dtd/package-2.0.xsd">
+
+
@@ -2145,6 +2147,8 @@ http://pear.php.net/dtd/package-2.0.xsd">
+
+
@@ -2251,6 +2255,8 @@ http://pear.php.net/dtd/package-2.0.xsd">
+
+
diff --git a/tests/Core/Tokenizer/HeredocStringTest.inc b/tests/Core/Tokenizer/HeredocStringTest.inc
new file mode 100644
index 0000000000..ae43e24a59
--- /dev/null
+++ b/tests/Core/Tokenizer/HeredocStringTest.inc
@@ -0,0 +1,193 @@
+bar
+EOD;
+
+/* testProperty2 */
+$heredoc = <<<"EOD"
+{$foo->bar}
+EOD;
+
+/* testMethod1 */
+$heredoc = <<bar()}
+EOD;
+
+/* testClosure1 */
+$heredoc = <<<"EOD"
+{$foo()}
+EOD;
+
+/* testChain1 */
+$heredoc = <<baz()()}
+EOD;
+
+/* testVariableVar1 */
+$heredoc = <<<"EOD"
+${$bar}
+EOD;
+
+/* testVariableVar2 */
+$heredoc = <<bar}
+EOD;
+
+/* testNested1 */
+$heredoc = <<{$baz}}
+EOD;
+
+/* testNested4 */
+$heredoc = <<<"EOD"
+${foo->{${'a'}}}
+EOD;
+
+/* testNested5 */
+$heredoc = <<{"${'a'}"}}
+EOD;
+
+/* testSimple1Wrapped */
+$heredoc = <<bar Something
+EOD;
+
+/* testProperty2Wrapped */
+$heredoc = <<<"EOD"
+Do {$foo->bar} Something
+EOD;
+
+/* testMethod1Wrapped */
+$heredoc = <<bar()} Something
+EOD;
+
+/* testClosure1Wrapped */
+$heredoc = <<<"EOD"
+Do {$foo()} Something
+EOD;
+
+/* testChain1Wrapped */
+$heredoc = <<baz()()} Something
+EOD;
+
+/* testVariableVar1Wrapped */
+$heredoc = <<<"EOD"
+Do ${$bar} Something
+EOD;
+
+/* testVariableVar2Wrapped */
+$heredoc = <<bar} Something
+EOD;
+
+/* testNested1Wrapped */
+$heredoc = <<{$baz}} Something
+EOD;
+
+/* testNested4Wrapped */
+$heredoc = <<<"EOD"
+Do ${foo->{${'a'}}} Something
+EOD;
+
+/* testNested5Wrapped */
+$heredoc = <<{"${'a'}"}} Something
+EOD;
diff --git a/tests/Core/Tokenizer/HeredocStringTest.php b/tests/Core/Tokenizer/HeredocStringTest.php
new file mode 100644
index 0000000000..2c808be906
--- /dev/null
+++ b/tests/Core/Tokenizer/HeredocStringTest.php
@@ -0,0 +1,153 @@
+
+ * @copyright 2022 Squiz Pty Ltd (ABN 77 084 670 600)
+ * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
+ */
+
+namespace PHP_CodeSniffer\Tests\Core\Tokenizer;
+
+use PHP_CodeSniffer\Tests\Core\AbstractMethodUnitTest;
+
+class HeredocStringTest extends AbstractMethodUnitTest
+{
+
+
+ /**
+ * Test that heredoc strings contain the complete interpolated string.
+ *
+ * @param string $testMarker The comment which prefaces the target token in the test file.
+ * @param string $expectedContent The expected content of the heredoc string.
+ *
+ * @dataProvider dataHeredocString
+ * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize
+ *
+ * @return void
+ */
+ public function testHeredocString($testMarker, $expectedContent)
+ {
+ $tokens = self::$phpcsFile->getTokens();
+
+ $target = $this->getTargetToken($testMarker, T_HEREDOC);
+ $this->assertSame($expectedContent."\n", $tokens[$target]['content']);
+
+ }//end testHeredocString()
+
+
+ /**
+ * Test that heredoc strings contain the complete interpolated string when combined with other texts.
+ *
+ * @param string $testMarker The comment which prefaces the target token in the test file.
+ * @param string $expectedContent The expected content of the heredoc string.
+ *
+ * @dataProvider dataHeredocString
+ * @covers PHP_CodeSniffer\Tokenizers\PHP::tokenize
+ *
+ * @return void
+ */
+ public function testHeredocStringWrapped($testMarker, $expectedContent)
+ {
+ $tokens = self::$phpcsFile->getTokens();
+
+ $testMarker = substr($testMarker, 0, -3).'Wrapped */';
+ $target = $this->getTargetToken($testMarker, T_HEREDOC);
+ $this->assertSame('Do '.$expectedContent." Something\n", $tokens[$target]['content']);
+
+ }//end testHeredocStringWrapped()
+
+
+ /**
+ * Data provider.
+ *
+ * @see testHeredocString()
+ *
+ * @return array
+ */
+ public function dataHeredocString()
+ {
+ return [
+ [
+ 'testMarker' => '/* testSimple1 */',
+ 'expectedContent' => '$foo',
+ ],
+ [
+ 'testMarker' => '/* testSimple2 */',
+ 'expectedContent' => '{$foo}',
+ ],
+ [
+ 'testMarker' => '/* testSimple3 */',
+ 'expectedContent' => '${foo}',
+ ],
+ [
+ 'testMarker' => '/* testDIM1 */',
+ 'expectedContent' => '$foo[bar]',
+ ],
+ [
+ 'testMarker' => '/* testDIM2 */',
+ 'expectedContent' => '{$foo[\'bar\']}',
+ ],
+ [
+ 'testMarker' => '/* testDIM3 */',
+ 'expectedContent' => '${foo[\'bar\']}',
+ ],
+ [
+ 'testMarker' => '/* testProperty1 */',
+ 'expectedContent' => '$foo->bar',
+ ],
+ [
+ 'testMarker' => '/* testProperty2 */',
+ 'expectedContent' => '{$foo->bar}',
+ ],
+ [
+ 'testMarker' => '/* testMethod1 */',
+ 'expectedContent' => '{$foo->bar()}',
+ ],
+ [
+ 'testMarker' => '/* testClosure1 */',
+ 'expectedContent' => '{$foo()}',
+ ],
+ [
+ 'testMarker' => '/* testChain1 */',
+ 'expectedContent' => '{$foo[\'bar\']->baz()()}',
+ ],
+ [
+ 'testMarker' => '/* testVariableVar1 */',
+ 'expectedContent' => '${$bar}',
+ ],
+ [
+ 'testMarker' => '/* testVariableVar2 */',
+ 'expectedContent' => '${(foo)}',
+ ],
+ [
+ 'testMarker' => '/* testVariableVar3 */',
+ 'expectedContent' => '${foo->bar}',
+ ],
+ [
+ 'testMarker' => '/* testNested1 */',
+ 'expectedContent' => '${foo["${bar}"]}',
+ ],
+ [
+ 'testMarker' => '/* testNested2 */',
+ 'expectedContent' => '${foo["${bar[\'baz\']}"]}',
+ ],
+ [
+ 'testMarker' => '/* testNested3 */',
+ 'expectedContent' => '${foo->{$baz}}',
+ ],
+ [
+ 'testMarker' => '/* testNested4 */',
+ 'expectedContent' => '${foo->{${\'a\'}}}',
+ ],
+ [
+ 'testMarker' => '/* testNested5 */',
+ 'expectedContent' => '${foo->{"${\'a\'}"}}',
+ ],
+ ];
+
+ }//end dataHeredocString()
+
+
+}//end class