Ctags: As ctags universais inserem caracteres `utf-8` inválidos para certos arquivos

Criado em 30 jul. 2018  ·  7Comentários  ·  Fonte: universal-ctags/ctags

(
Obrigado por nos contatar.

Se você estiver relatando um problema com o resultado da análise, preencha
o seguinte modelo. Como sua configuração CTags personalizada pode
afetar os resultados, use sempre --options=NONE como o primeiro
opção ao executar ctags .

Caso contrário, exclua o modelo e escreva seu problema do zero.
Os exemplos podem ajudar os desenvolvedores a entender melhor o seu problema.

Use a interface da web do GitHub e a notação de marcação.
Usar a renderização de texto quebrado dos resultados de e-mail que torna
os desenvolvedores enlouquecem.
)


O nome do analisador:

A linha de comando que você usou para executar ctags:

$ ctags -R

Não tenho nenhuma configuração especial em .ctags ou em qualquer outro lugar. Esta é uma nova VM em que este teste foi executado.

O conteúdo do arquivo de entrada: https://github.com/pallets/jinja/blob/master/jinja2/_identifier.py

A saída das tags com a qual você não está satisfeito:

Universal-ctags insere utf-8 caracteres inválidos em certas circunstâncias.

A saída de tags que você espera:

Saída de tag esperada com todos os caracteres valide utf-8 .

A versão das ctags:

$ ctags --version
Universal Ctags 0.0.0(3522685), Copyright (C) 2015 Universal Ctags Team
Universal Ctags is derived from Exuberant Ctags.
Ctags 5.8, Copyright (C) 1996-2009 Darren Hiebert
  Compiled: July 27 1018, 23:16:36
  URL: https://ctags.io/
  Optional compiled features: +wildcards, +regex, +iconv, +option-directory, +xpath

Como você obtém o binário ctags:

(
O binário ctags é construído em ubuntu-16.04 VM sem nenhuma modificação além da instalação de bibliotecas necessárias, como automate , autoreconf para compilar ctags e bibliotecas necessárias para compilar vim base em https://github.com/Valloric/YouCompleteMe/wiki/Building-Vim-from-source#a-for-a-debian-like-linux-distribution-like-ubuntu-type
)

@lilydjwg apontou para mim que ctags estava inserindo utf-8 caracteres inválidos, embora o arquivo usado para gerar as tags tenha todos os caracteres utf-8 válidos aqui:
https://github.com/vim/vim/issues/3213#issuecomment -406961075

A versão compilada de ctags funciona muito bem em geral.

Descobri recentemente que ctags tem um bug devido ao qual o
Execuberant ctags antigo instalado por sudo apt-get install ctags no Ubuntu
16.04 não insere nenhum caractere utf-8 inválido, mas se eu compilar
Universal-ctags da fonte e instale-o com base nas instruções aqui:
https://github.com/universal-ctags/ctags/blob/master/docs/autotools.rst , it
irá inserir utf-8 caracteres inválidos. Aqui está a evidência:

Com exuberant-ctags instalado usando apenas sudo apt-get install ctags :

2018-07-29_19-03-44

Com Universal-ctags compilado da fonte (último commit) a partir deste post,
compilado com instruções a partir daqui:
https://github.com/universal-ctags/ctags/blob/master/docs/autotools.rst :

2018-07-29_19-10-22

Isso causa muitos problemas no vim, porque se utf-8 inválidos, os caracteres são
passado para vim.eval , vim.eval quebras e isso não leva a nenhuma tag retornada em
tudo. Atualmente, há apenas uma maneira de transferir dados contidos em um viml
variável para o espaço python-name , usando vim.eval . Então, qualquer outro plugin em
vim ou onde terá problemas semelhantes também. @ludovicchabant para
exemplo teve que pós-processar seu arquivo de tags para impedir tais problemas:
https://ludovic.chabant.com/devblog/2017/02/25/aaa-gamedev-with-vim/

Ele também teve que alterar ctrl-py-matcher para detectar esse problema.
https://github.com/ludovicchabant/ctrlp-py-matcher/blob/2f6947480203b734b069e5d9f69ba440db6b4698/autoload/pymatcher.py#L22

Existem vários outros arquivos que eu vi que têm problemas semelhantes, mas eu
acabei de fornecer um aqui para diminuir o problema.

Meu palpite é que isso é um bug, e não espero que ctags faça isso por
Projeto. Isso pode ser corrigido, já que costumava funcionar bem em Exuberant Ctags
em que o Universal-ctags é baseado?

Ref: https://github.com/vim/vim/issues/3213#issuecomment -408727629

Todos 7 comentários

Parece # 1275 para mim: a nova opção pattern-length-limit está cortando em uma posição de byte arbitrária, que por acaso está no meio de uma sequência de caracteres. Consulte # 163, # 640 e # 1018.

Algo como https://github.com/universal-ctags/ctags/issues/1275#issuecomment -274489859 provavelmente deve ser implementado para corrigir isso.

@ alphaCTzo7G veja # 1807, isso corrige isso corretamente para você?

@ b4n , obrigado pela sua resposta rápida ...

No arquivo que postei aqui _identifier.py , usando o commit # 1805, ctags não insere mais caracteres / cortes inválidos em um local arbitrário.

Vou experimentar este PR no meu sistema real nos próximos dias para ver se funciona para todos os meus repositórios ou emite outros erros

Como ctrlp e ctrlp-py-matcher são plug-ins muito populares, seria ótimo se o # 1807 fosse mesclado para que vim e outros usuários de editores de texto pudessem usar ctrlp e ctrlp-py-matcher sem ter que se preocupar com este problema.

Outro arquivo que encontrei estava causando problemas, com vim.eval , e continha utf-8 caracteres inválidos, conforme determinado por grep -axv '.*' misc.html ( misc.html em https: / /github.com/alphaCTzo7G/test). O que percebi é que ctags inserirá os caracteres inválidos utf-8 no arquivo de tags de misc.html .

Faz sentido ctags detectar caracteres inválidos em arquivos e substituí-los por algo como @tonymec sugeriu aqui? (substitua a sequência inválida por uma ou mais instâncias do caractere (U + FFFD REPLACEMENT CHARACTER) que se destina exatamente a esse propósito.): https://github.com/vim/vim/issues/3213#issuecomment -405211243 ?

IIUC, ctags (ctags exuberantes, quero dizer, que é apenas um dos programas ctags disponíveis) é distribuído separadamente do Vim (mesmo que seu autor conheça Bram e mesmo que ocasionalmente trabalhem juntos para fazer o Vim e ctags funcionarem melhor juntos.

Do ponto de vista das ctags, é legítimo tratar o texto do programa apenas como strings de bytes: independentemente de ser UTF-8, Latin1, Latin9 ou algum outro conjunto de caracteres ISO 8859, um espaço é 0x20, uma guia rígida é 0x09, uma quebra de linha é 0x0A possivelmente precedida por 0x0D, etc .; e um byte nulo, que seria 0x00, não deve aparecer em um arquivo de texto. Ctags trata todos os programas da mesma maneira, independentemente da codificação compatível com ASCII em que está escrito e, portanto, não precisa se preocupar com qual é qual. Apenas para alguns conjuntos de caracteres estranhos como EBCDIC é necessário tratar o texto como definitivamente não ASCII (em EBCDIC, IIRC, AI são 0xC1-0xC9, JR são 0xD1-0xD9, SZ são 0xE2-0xE9, 0-9 são 0xF0-0xF9 , e não me lembro quais são os códigos para um espaço, uma tabulação, uma quebra de linha, um travessão, um sublinhado, etc.; mas você vê que do ponto de vista ASCII é realmente estranho).

IMHO, no caso da ctag, o bom e velho princípio se aplica: o lixo entra, o lixo sai.

Atenciosamente,
Tony.

@tonymec .. faz sentido .. Eu percebo que pode haver outros programas de geração de tag, mas universal-ctags é o mais popular, e entre as pessoas que usam universal-ctags meu palpite seria que uma grande parte são vim usuários.

Então, eu me pergunto se esses 2 podem funcionar ou se você tem alguma outra idéia de como lidar com arquivos que possuem utf-8 caracteres ilegais?

  1. Também notei que ctags tem esta opção de +iconv , que permite o uso de libiconv . Quando usado na linha de comando, iconv pode remover utf8 caracteres ilegais. Então, eu me pergunto se eu passar --input-enconding=utf-8 e --output-encoding=utf-8 , então todos os caracteres utf-8 ilegais seriam alterados para caracteres utf-8 legais.

Isso é explicado na seção 1.3.4 de https://media.readthedocs.org/pdf/ctags/latest/ctags.pdf :

Two new options have been introduced (--input-encoding=IN and --output-encoding=OUT). Using the encoding specified with these options ctags converts input from IN to OUT. ctags uses the converted strings when writing the pattern parts of each tag line. As a result the tags output is encoded in OUT encoding. In addition OUT is specified at the top the tags file as the value for the TAG_FILE_ENCODING pseudo tag. The default value of OUT is UTF-8. NOTE: Converted input is NOT passed to language parsers. The parsers still deal with input as a byte sequence. With --input-encoding-<LANG>=IN, you can specify a specific input encoding for LANG. It overrides the global default value given with --input-encoding

  1. deixe para o editor lidar com utf8 caracteres ilegais. Nesse caso, vim.eval deve ser consertado ou deve haver uma função vimL que pode analisar e remover utf-8 caracteres ilegais antes de passá-los para vim.eval ..

@ alphaCTzo7G Concordo com @tonymec e sua conclusão.

Infelizmente, é muito difícil reconhecer a codificação adequada - e insisto na adequada, porque é fácil encontrar uma codificação em que a entrada seja tecnicamente válida, digamos que a maioria, se não todas as codificações de 8 bits, seriam, mas sabendo se é a correta um é complicado ou impossível: digamos, como podemos ter certeza entre, por exemplo, ISO 8859-1 e 8859-15? As soluções incluem heurística complexa sobre frequência de uso e contexto; ou uma ideia mais ingênua aplicável a algumas linguagens como HTML seria extrair a instrução de codificação dentro do arquivo, mas isso também pode estar incorreto.

Além disso, ctags está em uma posição difícil aqui: muitos, senão a maioria, dos consumidores não lidam com codificações e as tags geradas precisam corresponder no nível de byte. Por exemplo, o grep para um padrão de tag ou mesmo nome não converterá as codificações para você, então a tag deve corresponder ao arquivo no nível de byte. Era fácil quando tudo que tínhamos para nos preocupar era o ASCII, mas não temos mais tanta sorte ... UTF-8 não foi adotado cedo o suficiente.
Isso também se aplica à ideia de substituir por caracteres de espaço reservado: o que o consumidor pode fazer com esse caractere de substituição? Deve pelo menos lidar com isso de uma maneira específica.

No entanto, se você estiver satisfeito em substituir UTF-8 inválido por U + FFFD ou removê-los, talvez você possa simplesmente pós-processar a saída de ctags?

@ b4n , agradeço seu comentário. Na verdade, eu lido principalmente com utf-8 arquivos codificados e tenho utf-8 codificados para os arquivos que eu crio. Infelizmente, como você mencionou, eu uso bibliotecas que tendem a ter codificações às vezes arbitrárias.

Eu uso vim-gutentags e fornece uma funcionalidade de pós-processamento. Embora eu pudesse pós-processar manualmente o arquivo de tags para resultar em todos os arquivos em utf-8 caracteres, quando tentei usar a funcionalidade post-processing em vim-gutentags , não funcionou . Então eu pensei que seria melhor descobrir uma solução mais robusta .. mas se isso não existir, terei que olhar para ela novamente ..

Para detectar a codificação do arquivo, você não pode usar as bibliotecas subjacentes por trás de uma dessas opções: https://stackoverflow.com/questions/805418/how-to-find-encoding-of-a-file-in-unix -via-scripts

como enca , file , uchardet , enguess ? Todas essas são utilidades de linha de comando .. mas deve haver alguma biblioteca em algum lugar que possa ser usada internamente por ctags talvez. Meu palpite é que, devido ao número de codificações, como você mencionou, pode nunca ser possível prever perfeitamente a codificação, mas uma solução simples que cubra a maior parte dela pode ser melhor do que nada.

Vou experimentar o --input-encoding (and/or --input-encoding-<LANG>) and --output-encoding options .. Não tenho certeza se vai funcionar o tempo todo, porque é muito possível que certos arquivos tenham codificações diferentes no mesmo repositório, a menos que ctags descubra o corrija a codificação individualmente e divida-a no formato desejado.

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

cweagans picture cweagans  ·  8Comentários

cweagans picture cweagans  ·  4Comentários

softinio picture softinio  ·  6Comentários

trevordmiller picture trevordmiller  ·  9Comentários

jespinal picture jespinal  ·  8Comentários