72/100 Dias de Golang - Criando um linter básico com golang - Buscando ifs dentro de ifs
Table of Contents
#
Criando um linter básico com golang - Buscando ifs dentro de ifs
Pensei em criar um função que analisa o código em busca de ifs aninhados. Vamos usar a mesma base do projeto e só adicionar mais duas funções no arquivo de regras.
Vamos fazer o mesmo esquema com o ast.Inspect
e avaliar node por node. Aqui vou fazer um switch
no statement, para no caso de adicionar mais algumas verificações, mas poderia ser um if
para validar se o statement é um if
.
func EstruturasAninhadas(fset *token.FileSet, node *ast.File) {
ast.Inspect(node, func(n ast.Node) bool {
switch stmt := n.(type) {
case *ast.IfStmt:
count := contaIfs(stmt.Body)
if count > 0 {
pos := fset.Position(stmt.Pos())
fmt.Printf("Encontrado %d if(s) aninhado(s) em %s:%d\n", count, pos.Filename, pos.Line)
}
}
return true
})
}
Quando encontramos um if
, passamos o stmt.Body
para uma função contaIfs
. Esse stmt.Body
é o bloco de código que está dentro da estrutura. Veja esse exemplo:
if x > 0 {
fmt.Println("positivo")
if x > 10 {
fmt.Println("maior que 10")
}
}
O stmt.Body
desse primeiro if é:
{
fmt.Println("positivo")
if x > 10 {
fmt.Println("maior que 10")
}
}
E a função contaIfs
é uma função recursiva que verifica a existência de outros ifs no bloco.
func contaIfs(block *ast.BlockStmt) int {
nested := 0
for _, stmt := range block.List {
switch s := stmt.(type) {
case *ast.IfStmt:
nested += 1 + contaIfs(s.Body)
case *ast.BlockStmt:
nested += contaIfs(s)
}
}
return nested
}
Agora podemos analisar nosso arquivo.go
func exemplo() {
x := 20
y := 30
if x > 0 {
if y > 0 {
fmt.Println("Aninhado")
}
}
}
Encontrado 1 if(s) aninhado(s) em arquivo.go:13
Como o contaIfs
é recursivo, ele vai analisar todos os ifs, não importando a profundidade ou a quantidade de níveis aninhados de ifs.