目前 Perl 扩展了 Moose、Mouse、Moo 和 Mo 等。 这些模块都有一个共同点——它们的属性选择器是用has
。 我相信我们可以假设任何遵循 Moose 建立的惯例的东西,
has $name|@$names => %options
是众多对象构建系统之一的正确格式属性。
我们必须涵盖诸如
has "foo" => ()
has ("foo" => ())
has [qw/foo bar/] => ()
has ([qw/foo bar/] => ())
@dtikhonov ,你能看看这个吗?
穆斯等人。 只是模块,而has
是一个函数调用,而不是 Perl 关键字。 在 ctags Perl 解析器中包含对 Moose 的支持会使我们陷入困境,因为有许多 Perl 模块引入了看起来像关键字的函数调用。
……我对这个话题很感兴趣。 过去 3 年,我改进了 ctags 来处理 DSL。
有关我的愿景,请参阅http://docs.ctags.io/en/latest/running-multi-parsers.html?highlight=subparser#tagging -definitions-of-higher-upper-level-language-sub-base。
Moose 子解析器可以在 Perl 解析器上运行。
package Point;
use Moose; # automatically turns on strict and warnings
has 'x' => (is => 'rw', isa => 'Int');
has 'y' => (is => 'rw', isa => 'Int');
sub clear {
my $self = shift;
$self->x(0);
$self->y(0);
}
package Point3D;
use Moose;
extends 'Point';
has 'z' => (is => 'rw', isa => 'Int');
after 'clear' => sub {
my $self = shift;
$self->z(0);
};
当 Perl 解析器发现关键字“use”时,Perl 解析器会将它通知给注册的子解析器。
Moose 子解析器就是这样的子解析器。
如果通知的模块名称是“Moose”,Moose 子解析器会自行激活。
Moose 子解析器扫描名为 cork 的 ctags 内部符号表以查找 Perl 语言对象
Perl 解析器标记为“包”类型。 Moose 子解析器可能会在符号表中找到“Point”。
它已经被 Perl 解析器标记了。 然而,Moose 解析器使用“类”类的“Moose”语言为“Point”创建了一个新标签。
Moose 子解析器将“点”推送到范围堆栈。
Moose 子解析器发现“has”作为关键字。 Moose 子解析器为“x”创建一个标记,作为“has”的下一个标记。 为“x”制作标签,“ scope:class :Point language:Moose ”附加到“x”...
关于C++解析器,我已经实现了这个想法。
QtMoc 子解析器用于使用 Qt 解析 C++ 代码。 QtMoc 子解析器识别信号和槽,它们是作为 C++ 语言的一种方言引入的。
要实现子解析器,我必须从其基本解析器的维护者那里获得许可。
我猜@dtikhonov不是那么积极,因为引入子解析器会使基本解析器的代码变得复杂。
如果解析器维护者和我有冲突,我想在解析器中引入子解析器,我会退出实现子解析器,因为拥有解析器维护者是 u-ctags 项目中最重要的事情。
@dtikhonov ,如果您对将 Moose 实现为子解析器的想法感兴趣,请告诉我。
我将制作一个原型来展示对 Perl 解析器源代码的影响。
感谢您的阅读。
我意识到这是一个功能,在引擎盖下。 但是,这是一个实现细节。 同样,当您以面向对象的方式编程时,包是“类”,而“子”是方法。 当您使用面向对象的 perl 时,所有这些命名法都会发生变化,但在每种情况下,您都可以使用非 OO 术语。 在上述所有情况下,虽然在推断用户为哪个范式编写代码时增加了复杂性。 也就是说,“有”缺乏这些复杂性。 如果你看到它,你有两种可能的解释 (a) 你正在调用一个函数“has”,在这种情况下,期望的行为是不做任何事情,就像我们现在所做的那样; 或者,(b) 您使用的是 Moose-esque 属性声明。
您回复中的“Moose et al”引用显示了 Perl 中使用这些模块构建器框架(包含has
-attribute 声明)的约定有多强。 Moose 很容易成为 Perl 最流行的模块之一(它在 metacpan 上的星数比 DBI 和 LWP 多)。
我不是说我们不能有任何误报,但我不知道是谁发布了不遵循这个惯例模块任何人及其代表,帮助了很多人。 此外,我真的怀疑这个 ctags 在理论上是合理的,而不仅仅是实用的。
@masatake 子解析器的想法听起来比我的实现更好、更完整,而且 perl 实际上已经通过测试use
并在内部为其中一些模块调用不同的语义做了类似的事情。
https://github.com/universal-ctags/ctags/blob/master/parsers/perl.c#L348
我想问题在于您必须枚举触发 Moose-parser 的模块列表,这不会太糟糕。 您还必须假设没有人在运行 Moose 的子类,这很棘手,但如果他们这样做,更糟糕的情况是他们会丢失 Moose-subparser。 而且,我对此表示同意——它不会比他们拥有的更糟糕。
如果您需要帮助为 Moose 编写 C 解析器,我也可以提供帮助。
我几乎认为这种用于 Perl 和 Moose 的静态解析器在 ctags 之外也很有用。 目前解析 perl 是不安全的,并且没有任何保证。 例如,这将允许其他项目在 Perl 上安全地运行测试覆盖率。
@masatake ,Perl 5 是一个缓慢移动的目标,没有太多需要维护的,所以我作为perl.c
维护者的工作很容易。 我浏览了您引用的子解析器文档——我只能说:哇! 坦率地说,我没有密切关注 Universal Ctags 的发展,我看到你已经取得了很大的进步。
@EvanCarroll ,代码对话:随意尝试一下。 我也没有嫁给perl.c
。 它的部分内容非常丑陋,事后看来,有些事情应该以不同的方式实施。 关于“用”的用法:触及,点取。
酷,酷。 我会看看这个周末我能完成什么。 我也会检查子解析器框架的工作。
一个原型工作。
@EvanCarroll ,你可以从#2070 开始。
我专注于 TypeScript 解析器。 所以我暂时不会在#2070 上工作。
随心所欲地破解。
[yamato@slave]~/var/ctags/perl-moose/Units/simple-moose.d% cat input.pl
cat input.pl
# Taken from https://metacpan.org/pod/Moose
package Point;
use Moose; # automatically turns on strict and warnings
has 'x' => (is => 'rw', isa => 'Int');
has 'y' => (is => 'rw', isa => 'Int');
sub clear {
my $self = shift;
$self->x(0);
$self->y(0);
}
package Point3D;
use Moose;
extends 'Point';
has 'z' => (is => 'rw', isa => 'Int');
after 'clear' => sub {
my $self = shift;
$self->z(0);
};
no Moose;
package Line;
[yamato@slave]~/var/ctags/perl-moose/Units/simple-moose.d% ./ctags --fields=+lineK --sort=no -o - --extras=+s ./input.pl
./ctags --fields=+lineK --sort=no -o - --extras=+s ./input.pl
zsh: no such file or directory: ./ctags
[yamato@slave]~/var/ctags/perl-moose/Units/simple-moose.d% ../../ctags --fields=+lineK --sort=no -o - --extras=+s ./input.pl
../../ctags --fields=+lineK --sort=no -o - --extras=+s ./input.pl
Point ./input.pl /^package Point;$/;" package line:2 language:Perl
Point ./input.pl /^package Point;$/;" class line:2 language:Moose
x ./input.pl /^has 'x' => (is => 'rw', isa => 'Int');$/;" attribute line:5 language:Moose class:Point
y ./input.pl /^has 'y' => (is => 'rw', isa => 'Int');$/;" attribute line:6 language:Moose class:Point
clear ./input.pl /^sub clear {$/;" subroutine line:8 language:Perl
clear ./input.pl /^sub clear {$/;" method line:8 language:Moose class:Point
Point3D ./input.pl /^package Point3D;$/;" package line:14 language:Perl
Point3D ./input.pl /^package Point3D;$/;" class line:14 language:Moose inherits:Point end:26
z ./input.pl /^has 'z' => (is => 'rw', isa => 'Int');$/;" attribute line:19 language:Moose class:Point3D
clear ./input.pl /^after 'clear' => sub {$/;" attribute line:21 language:Moose class:Point3D
Line ./input.pl /^package Line;$/;" package line:27 language:Perl
[yamato@slave]~/var/ctags/perl-moose/Units/simple-moose.d% ./ctags --list-subparsers
./ctags --list-subparsers
zsh: no such file or directory: ./ctags
[yamato@slave]~/var/ctags/perl-moose/Units/simple-moose.d% ../../ctags --list-subparsers
../../ctags --list-subparsers
#NAME BASEPARSER DIRECTIONS
AnsiblePlaybook Yaml base <> sub {bidirectional}
Autoconf M4 base <> sub {bidirectional}
Automake Make base <= sub {dedicated}
ITcl Tcl base <> sub {bidirectional}
JAXRS Java base => sub {shared}
LinuxKernel C base => sub {shared}
LinuxOVS C base => sub {shared}
Moose Perl base <> sub {bidirectional}
OpenVSwitch C base => sub {shared}
PythonLoggingConfig Iniconf base <> sub {bidirectional}
PythonMain Python base => sub {shared}
PythonTuned Python base => sub {shared}
QtMoc C++ base <> sub {bidirectional}
RSpec Ruby base => sub {shared}
SystemdUnit Iniconf base <= sub {dedicated}
TclOO Tcl base <> sub {bidirectional}
YumRepo Iniconf base <= sub {dedicated}
selinuxPolicy selinuxPolicyBase base => sub {shared}
servlet Java base => sub {shared}
[yamato@slave]~/var/ctags/perl-moose% ./ctags --list-kinds-full=Moose
#LETTER NAME ENABLED REFONLY NROLES MASTER DESCRIPTION
a attribute yes no 0 NONE attributes
c class yes no 0 NONE classes
m method yes no 0 NONE methods
一个原型工作。 @EvanCarroll ,你可以从#2070 开始。
那太快了! 👍
@masatake令人印象深刻。 还有工作要做吗? 我看到你已经实现了findAttribute
和语言回调参考?
@masatake令人印象深刻。 还有工作要做吗?
这就是我想知道的:-)。
如果我错过了你想要的东西,请告诉我。
我只阅读了 Moose 文档的几个部分。
@masatake很酷,我用 github 查看了补丁。 如果你不能解决它,我这个周末去看看。 =) 但是您可能会在 0.0001 秒内完成。
但您可能会在 0.0001 秒内完成。
这不是真的。
为了改进解析器,我们需要 4 件事:关于 ctags 内部 API 的知识,关于目标语言的知识,Moose,时间和激情:-P。
我对麋鹿一无所知。 这是最重要的。
例如,当前的解析器不捕获附加到带有with
的类的规则,并用“use Moose::Rule”定义。 我所知道的只是“规则”。 但是,您可能知道 ctags 应该捕获的项目更多。
难道你不希望 ctags 捕捉到这样的规则吗?
如果规则附加到一个类,我认为该类的标签应该有一个名为“规则:
需要知道目标语言的人的这些请求来发展这个项目。
我可以实施其中的一些。 你可以实现其他的。 如果有这样的要求,我们可以稍后实施。
我们可以扩展当前的实现以支持 Mouse、Moo 和 Mo。我们可以为您做任何事情
想要不修改原始 Perl 解析器。
抱歉,我发现你已经在#2070 中给了我重要的评论。 谢谢你。