2072 / PHP-Indenting-for-VIm

The official VIm indent script for PHP
http://www.2072productions.com/to/phpindent.txt
128 stars 29 forks source link

Multiline class properties break indentation #47

Closed Ilyes512 closed 7 years ago

Ilyes512 commented 8 years ago

So, today I found out that a multiline class property breaks the indentation for the file. I will try and describe it by giving example's:

I start of with the below, where //[] equals my current cursor position with insert-mode:

<?php

class testing
{
    protected $testing = 'This is a multiline
        property value
        that continues over multiple
        lines';//[]
}

When I hit return the cursor goes to the next line, but the indent is wrong:

<?php

class testing
{
    protected $testing = 'This is a multiline
        property value
        that continues over multiple
        lines';
//[]
}

Note the cursor position. So if I start inserting the next property without hitting tab again I get this:

<?php

class testing
{
    protected $testing = 'This is a multiline
        property value
        that continues over multiple
        lines';

protected $foobar;

}

Even when I manually override the spacing and insert the tabs after the fact like this:

<?php

class testing
{
    protected $testing = 'This is a multiline
        property value
        that continues over multiple
        lines';

    protected $foobar;

    public function __construct() {
        echo 'hello world';
    }
}

Once I hit gg=G to reformat the current file's spacing. It changes it to:

<?php

class testing
{
    protected $testing = 'This is a multiline
        property value
        that continues over multiple
        lines';

protected $foobar;

public function __construct() {
    echo 'hello world';
}
}

I am not really sure if it's my configuration or the plugin it self. My dotfiles can be found in my repository on github right here. More specifically my .vimrc can be found here and my plugin file here.

I can also tell you that vim does recognize the file as php (:set filetype? returns filetype=php). If you need some more info just ask. I can usually answer very quickly (if I can).

h3xx commented 8 years ago

Something I noticed was that the semicolon placement matters:

class testing {
    protected $testing = 'This is a multiline
        property'
;
    protected $foobar;
}

The $foobar property indents correctly.

2072 commented 8 years ago

I'll check this out but you should use heredoc/nowdoc notation which is properly supported and reliable. Multi-line strings are very difficult to identify correctly (without a real parser) and insert an uncontrollable number of spaces in your strings...

Ilyes512 commented 8 years ago

@2072 I understand there is heredoc/nowdoc, but ideally I would still like to use multiline properties anyways.

I understand that this might be hard or even not feasible. I still would like to thank you for you time in any case :)

(BTW I don't know how this plugin works, still a noob with Vim. I will try and understand how it's implemented to get a feeling.)

andrey-utkin commented 8 years ago

Experiencing similar difficulty. In a codebase of a project I'm participating in, we have SQL queries formatted as quoted.

<?php

class A
{
    public function a()
    {
        $query =
            "UPDATE mytable
                SET a = 'a'
          RETURNING *";

        $a = f("a", "b",
               "c");
    }
}

And when you go to edit $a = f("a", "b", to move "b" to next line, you get:

<?php

class A
{
    public function a()
    {
        $query =
            "UPDATE mytable
                SET a = 'a'
          RETURNING *";

$a = f("a",
    "b",
               "c");
    }
}

What is most annoying is that alignment of the beginning of the line, $a = f("a",, gets messed up.

Is there any flag i could tweak?

2072 commented 8 years ago

I have no time to look into this right now or any time soon (not before the end of July).

Besides using here/nowdoc (which also adds the benefit of enabling syntax highlighting if you use the SQL keyword) one could also write this kind of code in the following way:

class A
{
    public function a()
    {
        $query =
            "UPDATE mytable"
            ." SET a = 'a'"
            ." RETURNING *";

        $a = f("a", "b",
            "c");
    }
}

This is quite cleaner and avoids passing random spaces/tabs/line breaks to your query parser...

And with nowdoc style:

class A
{
    public function a()
    {
        $query = <<<'SQL'
            UPDATE mytable
                SET a = 'a'
          RETURNING *
SQL;

        $a = f("a",
            "b",
            "c");
    }
}
2072 commented 7 years ago

OK this is fixed for now but as expected it was quite annoying to do. It may break again depending on what text you write in your multi-line strings... I've added a fail-safe to prevent breaking indentation if the start of the multi-line string declaration cannot be found.

As stated in https://github.com/2072/PHP-Indenting-for-VIm/issues/22#issuecomment-33920352, the safest way to write these is:

class testing
{
    protected $testing = '
        This is an ugly multiline
        property value
        that continues over multiple
        lines';
}

so that, just like with herdoc, there is a way to look for the start of the declaration while safely skipping the string's content...