Ctags: PHP heredoc (<<

Созданный на 20 нояб. 2020  ·  8Комментарии  ·  Источник: universal-ctags/ctags

РЕЗЮМЕ:

Генерация тегов останавливается, когда в файле встречается синтаксис PHP heredoc ( <<< ). Поскольку синтаксис nowdoc PHP в основном тот же, это еще один языковой элемент, который нарушает синтаксический анализ файла.

Имя парсера:

не уверен в этом. Предполагая, что PHP

Командная строка, которую вы использовали для запуска ctags:
$ ctags --options=NONE foo.php
Содержимое входного файла:
<?php

class LivingBeings {

    public function doSomething()
    {
        $foo = <<<FOO
        FOO;
    }

    public function doSomethingElse()
    {
    }
}
Вывод тегов вас не устраивает:

Метод doSomethingElse не указан в файле. Как только я закомментирую часть heredoc , метод индексируется нормально, как вы можете видеть в разделе «Ожидаемый результат» впереди.

!_TAG_FILE_FORMAT   2   /extended format; --format=1 will not append ;" to lines/
!_TAG_FILE_SORTED   1   /0=unsorted, 1=sorted, 2=foldcase/
!_TAG_OUTPUT_EXCMD  mixed   /number, pattern, mixed, or combine/
!_TAG_OUTPUT_FILESEP    slash   /slash or backslash/
!_TAG_OUTPUT_MODE   u-ctags /u-ctags or e-ctags/
!_TAG_PATTERN_LENGTH_LIMIT  96  /0 for no limit/
!_TAG_PROC_CWD  /tmp/   //
!_TAG_PROGRAM_AUTHOR    Universal Ctags Team    //
!_TAG_PROGRAM_NAME  Universal Ctags /Derived from Exuberant Ctags/
!_TAG_PROGRAM_URL   https://ctags.io/   /official site/
!_TAG_PROGRAM_VERSION   5.9.0   /5a136315/
LivingBeings    foo.php /^class LivingBeings {$/;"  c
doSomething foo.php /^    public function doSomething()$/;" f   class:LivingBeings
Ожидаемый результат тегов:
!_TAG_FILE_FORMAT   2   /extended format; --format=1 will not append ;" to lines/
!_TAG_FILE_SORTED   1   /0=unsorted, 1=sorted, 2=foldcase/
!_TAG_OUTPUT_EXCMD  mixed   /number, pattern, mixed, or combine/
!_TAG_OUTPUT_FILESEP    slash   /slash or backslash/
!_TAG_OUTPUT_MODE   u-ctags /u-ctags or e-ctags/
!_TAG_PATTERN_LENGTH_LIMIT  96  /0 for no limit/
!_TAG_PROC_CWD  /tmp/   //
!_TAG_PROGRAM_AUTHOR    Universal Ctags Team    //
!_TAG_PROGRAM_NAME  Universal Ctags /Derived from Exuberant Ctags/
!_TAG_PROGRAM_URL   https://ctags.io/   /official site/
!_TAG_PROGRAM_VERSION   5.9.0   /5a136315/
LivingBeings    foo.php /^class LivingBeings {$/;"  c
doSomething foo.php /^    public function doSomething()$/;" f   class:LivingBeings
doSomethingElse foo.php /^    public function doSomethingElse()$/;" f   class:LivingBeings
Версия ctags:
$ ctags --version
Universal Ctags 5.9.0(5a136315), Copyright (C) 2015 Universal Ctags Team
Universal Ctags is derived from Exuberant Ctags.
Exuberant Ctags 5.8, Copyright (C) 1996-2009 Darren Hiebert
  Compiled: Nov 20 2020, 11:46:20
  URL: https://ctags.io/
  Optional compiled features: +wildcards, +regex, +iconv, +option-directory, +xpath, +yaml, +packcc
Как получить двоичный файл ctags:

Сборка локально:

$ cd ctags_source
$ make clean && make distclean
$ ./autogen.sh
$ ./configure --prefix=$HOME
$ make
$ make install
Parser buenhancement

Все 8 Комментарий

@jespinal , вы говорите об этом изменении: https://wiki.php.net/rfc/f flexible_heredoc_nowdoc_syntaxes ?

$ git diff |cat
git diff |cat
diff --git a/parsers/php.c b/parsers/php.c
index e3fdc241..ace25561 100644
--- a/parsers/php.c
+++ b/parsers/php.c
@@ -682,6 +682,8 @@ static void parseHeredoc (vString *const string)
            int extra = EOF;

            c = getcFromInputFile ();
+           if (c == ' ' || c == '\t')
+               c = getcFromInputFile ();
            for (len = 0; c != 0 && (c - delimiter[len]) == 0; len++)
                c = getcFromInputFile ();

$ cat input.php
cat input.php
<?php
// Taken from https://github.com/universal-ctags/ctags/issues/2717
// submitted by <strong i="5">@jespinal</strong>
class LivingBeings {

    public function doSomething()
    {
        $foo = <<<FOO
        FOO;
    }

    public function doSomethingElse()
    {
    }
}
$ u-ctags -o - input.php
u-ctags -o - input.php
LivingBeings    input.php   /^class LivingBeings {$/;"  c
doSomething input.php   /^    public function doSomething()$/;" f   class:LivingBeings
$

@masatake этого недостаточно, потому что конечный маркер раньше должен был находиться на отдельной строке , а в новой версии это ограничение снимается. Я не нахожу объяснение очень ясным:

Предлагаемая мной реализация позволяет избежать этой проблемы, проверяя, существует ли продолжение найденного маркера, и если да, то формирует ли он действительный идентификатор.

но я бы сказал, что это означает, что если после строки с префиксом завершающего маркера нет символа идентификатора, это действительно конечный маркер. Итак, END; - это завершение (учитывая, что маркер - END ), а ENDFOO - нет.

Кстати, поскольку это обратно несовместимое синтаксическое изменение, я не знаю, что мы хотим с этим делать. Но я думаю, что если PHP будет рад сломать его, мы тоже сможем, тем более что это вряд ли вызовет проблемы. В идеале, я думаю, мы бы использовали текущий синтаксис для *.php[1-6] и новый для остальных, но это может быть слишком большой проблемой для того, чего он стоит.

@jespinal , вы говорите об этом изменении: https://wiki.php.net/rfc/f flexible_heredoc_nowdoc_syntaxes ?

Извините, @masatake , по какой-то причине меня не уведомили о вашем вопросе.

Да, я говорю об этом изменении. Но на самом деле это было реализовано в PHP 7.3 (текущая стабильная версия - 7.4, и версия 8 уже под рукой). Я не уверен, почему об этом не сообщалось ранее, учитывая обширную базу пользователей как ctags, так и PHP.

Я добавляю несколько скриншотов фрагментов кода, взятых из предыдущего примера, чтобы (надеюсь) пролить свет на то, что они считают допустимым / недопустимым синтаксисом в отношении нового синтаксиса heredoc / nowdoc (RFC недостаточно ясен, я считать).

В этом примере ' TEXT ' (второй) - конечный маркер. Итак, третья строка ' TEXT; является синтаксически недопустимой строкой в ​​представлении парсера, так как она ожидает только точку с запятой или запятую:

test-001-2020-11-24 22-33-30

Случай, аналогичный предыдущему:
test-003-2020-11-24 22-37-04

Будь то точка с запятой или запятая, парсер php был бы счастлив. Например

        echo <<<TEXT
            some string 
        TEXT, 'some other string';

В глазах парсера это то же самое, что:

    echo 'some string', 'some other string';

Ниже приведен допустимый пример, поскольку синтаксический анализатор знает, что « TEXT » и « TEXTUAL - это две разные строки:

test-002-2020-11-24 22-36-25

Вот пара недействительных фрагментов из-за неправильного отступа. В частности, к заявлению RFC: «Если закрывающий маркер смещен дальше, чем любая строка тела, то будет выдано исключение ParseError:»

test-004-2020-11-24 22-38-11

test-005-2020-11-24 22-39-38

@jespinal, спасибо, но если у вас есть нормативный текст, это будет еще лучше :) Всегда сложно угадать логику, основанную исключительно на нескольких случаях, тогда как, если у нас есть нормативный текст, мы можем просто реализовать это, и мы надеемся, что это сработает. На самом деле, я думаю, нам достаточно ссылки @masatake и вашей информации: +1:

@masatake Я ничего не обещаю, учитывая то небольшое количество времени, которое я нахожу в последнее время, но я постараюсь в ближайшее время взглянуть на это, если - вы меня не опередите :)

Кстати, @jespinal, если никто не жаловался, я действительно думаю, это потому, что этот синтаксис используется очень мало, и мы поддерживаем синтаксис до 7.3, поэтому единственные случаи, когда можно было бы увидеть проблему, - это использование синтаксиса 7.3+, что подразумевает использование neredoc / nowdoc в первую очередь :)

Вы какое-то время бездействовали. Так что я не ожидал получить от вас комментарий.
Но, теперь мы получаем от вас знак "самопровозглашенный". @ b4n , спасибо за предложение.

@masatake, вы

Тем не менее, см. # 2734 для исправления проблемы :)

Спасибо!

Была ли эта страница полезной?
0 / 5 - 0 рейтинги

Смежные вопросы

lvc picture lvc  ·  3Комментарии

blueyed picture blueyed  ·  4Комментарии

jagjordi picture jagjordi  ·  9Комментарии

sparkcanon picture sparkcanon  ·  3Комментарии

cweagans picture cweagans  ·  13Комментарии