Atualmente, o Perl é estendido com Moose, Mouse, Moo e Mo e semelhantes. Todos esses módulos têm uma semelhança - seus seletores de atributo são estabelecidos com has
. Acredito que podemos supor que tudo o que segue a convenção estabelecida por Moose de,
has $name|@$names => %options
é um atributo formado corretamente para um dos muitos sistemas de construção de objetos que existem.
Teríamos que cobrir coisas como
has "foo" => ()
has ("foo" => ())
has [qw/foo bar/] => ()
has ([qw/foo bar/] => ())
@dtikhonov , você poderia olhar para isso?
Moose et al. são apenas módulos e has
é uma chamada de função, não uma palavra-chave Perl. Incluir suporte para Moose no analisador ctags Perl nos colocaria em uma ladeira escorregadia, pois há muitos módulos Perl que introduzem chamadas de função que parecem palavras-chave.
... Estou muito interessado neste tópico. Nos últimos 3 anos, melhorei ctags para lidar com DSLs.
Consulte http://docs.ctags.io/en/latest/running-multi-parsers.html?highlight=subparser#tagging -definitions-of-mais-alto-nível-superior-sub-base de linguagem sobre minha visão.
O subparser Moose pode ser executado no parser 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);
};
Quando o analisador Perl encontra uma palavra-chave "usar", o analisador Perl a notifica aos subparsers registrados.
Moose subparser é um subparser.
O subparser Moose se ativa se o nome do módulo notificado for "Moose".
O subparser Moose examina a tabela de símbolos internos de ctags chamada cork para encontrar um objeto de linguagem Perl
marcado como "pacote" pelo analisador Perl. O subparser Moose pode encontrar "Point" na tabela de símbolos.
Já está marcado pelo analisador Perl. No entanto, o analisador Moose cria uma nova tag para "Point" com "classe", uma espécie de linguagem "Moose".
O subparser Moose empurra o "Ponto" para a pilha de escopo.
O subparser Moose encontra "has" como uma palavra-chave. O subparser Moose cria uma tag para "x" encontrada como o próximo token para "tem". A criação da tag para "x", " scope: class : Point language: Moose " é anexada a "x" ...
Sobre o analisador C ++, já implementei essa ideia.
O subparser QtMoc é para analisar código C ++ usando Qt. O subparser QtMoc reconhece o sinal e o slot, que são introduzidos como um dialeto da linguagem C ++.
Para implementar um sub-analisador, preciso obter permissão do mantenedor de seu analisador base.
Eu acho que @dtikhonov não é tão positivo porque a introdução de um subparser torna o código do parser de base complicado.
Se houver conflito entre um mantenedor do parser e eu, que deseja introduzir um subparser ao parser, desistirei de implementar o subparser porque ter um mantenedor do parser é a coisa mais importante no projeto u-ctags.
@dtikhonov , se você estiver interessado na ideia de implementar o Moose como um subparser, me avise.
Vou fazer um protótipo para mostrar o impacto no código-fonte do analisador Perl.
Obrigado por ler.
Eu percebo que é uma função, por baixo do capô. Mas, isso é um detalhe de implementação. No mesmo sentido, pacotes são "classes" quando você está programando de maneira orientada a objetos, e "subs" são métodos. Toda essa nomenclatura muda quando você usa perl Orientado a Objetos, mas em cada caso você pode fazer uso da terminologia não OO. Em todos os casos acima, porém, há complexidades adicionais em inferir para qual paradigma o usuário escreveu o código. Dito isso, "tem" carece dessas complexidades. Se você o vir, terá duas interpretações possíveis (a) você está chamando uma função "tem", caso em que o comportamento desejado seria não fazer nada, como fazemos agora; ou (b) você está usando uma declaração de atributo no estilo Moose.
A citação "Moose et al" de sua resposta mostra o quão forte é essa convenção em Perl para usar essas estruturas construtoras de módulo (que abrangem a declaração has
-atributo). Moose é facilmente um dos módulos mais populares para Perl (tem mais estrelas no metacpan do que DBI e LWP).
Não estou dizendo que não poderíamos ter nenhum falso-positivo, mas não conheço ninguém que publicou um módulo que não segue esta convenção e que ajudará muita gente. Além disso, eu realmente duvido que esse ctags seja teoricamente correto, e não apenas prático.
@masatake a ideia do subparser soa melhor e mais completa do que minha implementação, e perl na verdade já faz algo semelhante testando use
e invocando semânticas diferentes para alguns desses módulos internamente.
https://github.com/universal-ctags/ctags/blob/master/parsers/perl.c#L348
Acho que o problema é que você teria que enumerar a lista de módulos que acionam o analisador Moose, o que não seria tão ruim. Você também teria que assumir que ninguém está executando uma subclasse de Moose, o que é complicado, mas se eles estivessem fazendo isso, o pior cenário seria perderiam o subparser Moose. E, estou bem com isso - não seria pior do que o que eles têm.
Se você quiser ajuda para escrever um analisador C para Moose, eu posso ajudar com isso também.
Estou quase convencido de que esse tipo de analisador estático para Perl e Moose também seria útil fora dos ctags. Atualmente, a análise de perl não é segura e não há garantias. Isso permitiria que outros projetos executassem com segurança a cobertura de teste no Perl, por exemplo.
@masatake , Perl 5 é um alvo tão lento que não há muito o que manter, então meu trabalho como mantenedor de perl.c
tem sido fácil. Eu examinei a documentação do subparser que você referiu - tudo o que posso dizer é: uau! Para ser franco, não tenho acompanhado o desenvolvimento do Universal Ctags de perto e vejo que você fez grandes avanços.
@EvanCarroll , código fala: sinta-se à vontade para tentar. Também não sou casado com perl.c
. Algumas partes são francamente feias e, em retrospectiva, algumas coisas deveriam ter sido implementadas de forma diferente. No que diz respeito ao uso de "usar": touche, ponto tomado.
Legal legal. Vou ver o que posso fazer neste fim de semana então. Vou verificar o trabalho na estrutura do subparser também.
Um protótipo funciona.
@EvanCarroll , você pode começar do # 2070.
Estou me concentrando no analisador TypeScript. Portanto, não vou trabalhar no # 2070 por um tempo.
Hack como quiser.
[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
Um protótipo funciona. @EvanCarroll , você pode começar do # 2070.
Isso foi rápido! 👍
@masatake impressionante. Há mais trabalho a fazer? Vejo que você implementou findAttribute
e a referência de retorno de chamada do idioma?
@masatake impressionante. Há mais trabalho a fazer?
É isso que gostaria de saber :-).
Se eu perdi o que você queria, por favor, me avise.
Eu li apenas algumas partes do documento de Moose.
@masatake bom negócio, eu revisei o patch com o github. Se você não puder fazer isso, vou dar uma olhada neste fim de semana. =) Mas você provavelmente terá feito em 0,0001 segundos.
Mas você provavelmente terá feito isso em 0,0001 segundos.
Não é verdade.
Para melhorar o analisador, precisamos de 4 coisas: conhecimento sobre a API interna ctags, conhecimento sobre a linguagem alvo, Moose, tempo e paixão :-P.
Não tenho conhecimento sobre Moose. Este é o mais importante.
por exemplo, o analisador atual não captura uma regra anexada a uma classe com with
e definida com "use Moose :: Rule". O que eu sei é apenas "regra". No entanto, você pode saber mais itens que as ctags devem capturar.
Você não espera que as ctags capturem essas regras?
Se uma regra for anexada a uma classe, acho que a tag da classe deve ter um campo chamado "regra:
Essas solicitações de uma pessoa que conhece o idioma de destino são necessárias para desenvolver este projeto.
Posso implementar alguns deles. Você pode implementar outros. Podemos implementar mais tarde se essas solicitações forem.
Podemos estender a implementação atual para oferecer suporte a Mouse, Moo e Mo. Podemos fazer qualquer coisa que você
deseja SEM modificar o analisador Perl original.
Desculpe, descobri que você já me fez comentários importantes em # 2070. Obrigada.