Swiftlint: A correção automática para "dois pontos" corrompe o arquivo quando macros do pré-processador estão presentes

Criado em 16 mar. 2018  ·  3Comentários  ·  Fonte: realm/SwiftLint

Lista de verificação de novo problema

Relatório de erro

Saída completa ao executar o SwiftLint, incluindo o rastreamento de pilha e o comando usado
$ swiftlint autocorrect --path Foo.swift
Correcting Swift files at path Foo.swift
Correcting 'Foo.swift' (1/1)
Foo.swift:4:21 Corrected Colon
Foo.swift:4:21 Corrected Colon
Done correcting 1 files!

Ambiente

  • Versão do SwiftLint (execute swiftlint version para ter certeza)? 0.25.0 não encontra nada para corrigir automaticamente (devido a # 2050), no entanto, qualquer coisa após dddb0f6 mostra o problema
  • Método de instalação usado (Homebrew, CocoaPods, compilação a partir da fonte, etc)? Homebrew para 0.25.0, desenvolvido a partir da fonte em 6584b4f5
  • Cole seu arquivo de configuração:
whitelist_rules:
  - colon
  • Você está usando configurações aninhadas ? Nesse caso, cole seus caminhos relativos e respectivos conteúdos. não
  • Qual versão do Xcode você está usando (verifique xcode-select -p )? 9,2

Passos para reproduzir

Arquivo fonte

class Foo {
    #if false
    #else
    let bar = ["key"   : "value"]
    #endif
}

Execute autocorrect

$ swiftlint autocorrect --path Foo.swift
Corrigindo arquivos Swift no caminho Foo.swift
Corrigindo 'Foo.swift' (1/1)
Foo. rápido: 4 : 21 Cólon corrigido
Foo. rápido: 4 : 21 Cólon corrigido
Concluída a correção de 1 arquivo!

Arquivo corrigido

A correção duplicada acaba truncando o dicionário de forma que ele não compile. A quantidade de truncamento é sempre igual ao número de espaços extras entre o final da chave e os dois pontos.

class Foo {
    #if false
    #else
    let bar = ["key": lue"]
    #endif
}

Tentativas de variações

O problema só é reproduzível com um literal de dicionário, substituindo a 4ª linha por

let bar   :   String = ""

ou

func bar(arg   :  String) {}

funciona conforme o esperado.

Remover as macros do pré-processador inteiramente também corrige o problema, mas isso não é possível no caso do mundo real que descobriu esse bug.


O melhor que posso dizer é que o SourceKitten está ficando confuso com as macros do pré-processador, mas apenas no caso literal do dicionário. Examinar file.structure em ColonRule.correctionRanges(in:) mostra duas entradas idênticas, o que faz com que o swiftlint emita duas correções no mesmo local.


saída da estrutura

{
  "key.diagnostic_stage" : "source.diagnostic.stage.swift.parse",
  "key.length" : 84,
  "key.offset" : 0,
  "key.substructure" : [
    {
      "key.accessibility" : "source.lang.swift.accessibility.internal",
      "key.bodylength" : 70,
      "key.bodyoffset" : 11,
      "key.kind" : "source.lang.swift.decl.class",
      "key.length" : 82,
      "key.name" : "Foo",
      "key.namelength" : 3,
      "key.nameoffset" : 6,
      "key.offset" : 0,
      "key.runtime_name" : "_TtC8__main__3Foo",
      "key.substructure" : [
        {
          "key.accessibility" : "source.lang.swift.accessibility.internal",
          "key.kind" : "source.lang.swift.decl.var.instance",
          "key.length" : 29,
          "key.name" : "bar",
          "key.namelength" : 3,
          "key.nameoffset" : 44,
          "key.offset" : 40
        },
        {
          "key.bodylength" : 17,
          "key.bodyoffset" : 51,
          "key.elements" : [
            {
              "key.kind" : "source.lang.swift.structure.elem.expr",
              "key.length" : 5,
              "key.offset" : 51
            },
            {
              "key.kind" : "source.lang.swift.structure.elem.expr",
              "key.length" : 7,
              "key.offset" : 61
            }
          ],
          "key.kind" : "source.lang.swift.expr.dictionary",
          "key.length" : 19,
          "key.namelength" : 0,
          "key.nameoffset" : 0,
          "key.offset" : 50
        },
        {
          "key.accessibility" : "source.lang.swift.accessibility.internal",
          "key.kind" : "source.lang.swift.decl.var.instance",
          "key.length" : 29,
          "key.name" : "bar",
          "key.namelength" : 3,
          "key.nameoffset" : 44,
          "key.offset" : 40
        },
        {
          "key.bodylength" : 17,
          "key.bodyoffset" : 51,
          "key.elements" : [
            {
              "key.kind" : "source.lang.swift.structure.elem.expr",
              "key.length" : 5,
              "key.offset" : 51
            },
            {
              "key.kind" : "source.lang.swift.structure.elem.expr",
              "key.length" : 7,
              "key.offset" : 61
            }
          ],
          "key.kind" : "source.lang.swift.expr.dictionary",
          "key.length" : 19,
          "key.namelength" : 0,
          "key.nameoffset" : 0,
          "key.offset" : 50
        }
      ]
    }
  ]
}

bug

Todos 3 comentários

@jszumski Parece que podemos contornar isso excluindo as violações antes de corrigir.

Mas o SourceKit não deve retornar duas entradas idênticas também. Você pode registrar um bug no JIRA do Swift ?

Na verdade, isso já parece corrigido no Swift 4.1, então não há necessidade de registrar um bug 💯

Obrigado pela resposta rápida!

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