vscode: PHP Syntax Color Error

Issue Type: Bug

When i want to use trying using JS on HEREDOC and set the mark to “JS”, all syntax color below that HEREDOC become error…

Example:

$jsfunc=<<<JS
                $(document).ready(function(){
                    ...
                });
JS;

//Below this line the Syntax color become error

.....

report_1

VS Code version: Code 1.45.1 (5763d909d5f12fe19f215cbfdd29a91c0fa9208a, 2020-05-14T08:27:35.169Z) OS version: Windows_NT x64 6.3.9600

System Info
Item Value
CPUs Intel® Celeron® CPU N2920 @ 1.86GHz (4 x 1867)
GPU Status 2d_canvas: enabled
flash_3d: enabled
flash_stage3d: enabled
flash_stage3d_baseline: enabled
gpu_compositing: enabled
multiple_raster_threads: enabled_on
oop_rasterization: disabled_off
protected_video_decode: unavailable_off
rasterization: enabled
skia_renderer: disabled_off_ok
video_decode: enabled
viz_display_compositor: enabled_on
viz_hit_test_surface_layer: disabled_off_ok
webgl: enabled
webgl2: enabled
Load (avg) undefined
Memory (System) 3.75GB (1.22GB free)
Process Argv
Screen Reader no
VM 0%
Extensions (2)
Extension Author (truncated) Version
php-debug fel 1.13.0
vscode-counter uct 1.3.5

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 18 (8 by maintainers)

Most upvoted comments

@lewisconklin You’re more or less correct until this sentence:

When a {$} is encountered in a JavaScript heredoc, a match is found using both the #interpolation and the source.js grammar rules. From the TextMate docs:

When TM is in any syntax block it is checking only the rules defined or included via include: #whatever in that exact block. You can reference $self, but this would only include the top-level rules from the source.js. There is no practical way to include the #interpolation rules when there are blocks involved. On the other hand, the SQL have a very limited amount of blocks, so you could just replace the string definition with your own, which is exactly what is done, but this also is not perfect and you can find many issues related to broken SQL syntax in language-php.


I’d strongly advice you to avoid injections all together, for the SQL you can use a prepared statements, for the JS/CSS I’d send a single JSON object with necessary data for a separate JS to deal with, and for HTML use a template system of some sort. There is no real point in mixing languages these days.

@roblourens Thanks. I believe you are correct, as it seems I have hit a wall in my progress with this issue. Here is what I have so far:

  1. In PHP, inside of double-quoted strings and heredocs, {} must be used to surround complex variables. In the above example, they are needed due to the array with quoted index.

  2. In the above example, using the scope inspector, it is clear that TextMate does not recognize {$_SESSION['ans_draft_post']} as a PHP variable. This is what breaks the syntax highlighting.

  3. Using a heredoc with a language such as SQL, where {} do not naturally occur, this bug does not appear.

  4. This bug does not occur within a JavaScript heredoc unless it is used inside a function call, as a variable assignment, etc. I have provided the following, simpler example to demonstrate this.

<?php

$arr = array('foo' => 'bar');

$test=<<<JS
    {$arr['foo']};  // works fine
    let bar = {$arr['foo']};  // breaks syntax highlighting
JS;

print "syntax highlighting test";

?>

I believe the reason for this is due to TextMate’s scope selecting rules. In the php.tmLanguage.json file, under the heredoc section for JavaScript, we have

"name": "meta.embedded.js",
"patterns": [
    {
        "include": "#interpolation"
    },
    {
        "include": "source.js"
    }
]

When a {$} is encountered in a JavaScript heredoc, a match is found using both the #interpolation and the source.js grammar rules. From the TextMate docs:

If more than one scope selector matches the current scope then they are ranked 
according to how “good” a match they each are.

The winner is the scope selector which (in order of precedence):

1. Match the element deepest down in the scope e.g. string wins over source.php 
when the scope is source.php string.quoted.

2. Match most of the deepest element e.g. string.quoted wins over string.

In my provided example, the first case works because both the interpolated PHP and JavaScript are on a equal level of scope, and I believe that since #interpolation is included first in the patterns array, it has precedence. In the second case, the JavaScript scope is now deeper due to the variable assignment, and thus wins over the PHP grammar. Perhaps this is a case where we need scope exclusion?