mirror of
				https://github.com/mgechev/revive.git
				synced 2025-10-30 23:37:49 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			118 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			118 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package ifelse
 | |
| 
 | |
| import (
 | |
| 	"fmt"
 | |
| 	"go/ast"
 | |
| 	"go/token"
 | |
| )
 | |
| 
 | |
| // Branch contains information about a branch within an if-else chain.
 | |
| type Branch struct {
 | |
| 	BranchKind
 | |
| 	Call  // The function called at the end for kind Panic or Exit.
 | |
| 	block []ast.Stmt
 | |
| }
 | |
| 
 | |
| // BlockBranch gets the Branch of an ast.BlockStmt.
 | |
| func BlockBranch(block *ast.BlockStmt) Branch {
 | |
| 	blockLen := len(block.List)
 | |
| 	if blockLen == 0 {
 | |
| 		return Empty.Branch()
 | |
| 	}
 | |
| 
 | |
| 	branch := StmtBranch(block.List[blockLen-1])
 | |
| 	branch.block = block.List
 | |
| 	return branch
 | |
| }
 | |
| 
 | |
| // StmtBranch gets the Branch of an ast.Stmt.
 | |
| func StmtBranch(stmt ast.Stmt) Branch {
 | |
| 	switch stmt := stmt.(type) {
 | |
| 	case *ast.ReturnStmt:
 | |
| 		return Return.Branch()
 | |
| 	case *ast.BlockStmt:
 | |
| 		return BlockBranch(stmt)
 | |
| 	case *ast.BranchStmt:
 | |
| 		switch stmt.Tok {
 | |
| 		case token.BREAK:
 | |
| 			return Break.Branch()
 | |
| 		case token.CONTINUE:
 | |
| 			return Continue.Branch()
 | |
| 		case token.GOTO:
 | |
| 			return Goto.Branch()
 | |
| 		}
 | |
| 	case *ast.ExprStmt:
 | |
| 		fn, ok := ExprCall(stmt)
 | |
| 		if !ok {
 | |
| 			break
 | |
| 		}
 | |
| 		kind, ok := DeviatingFuncs[fn]
 | |
| 		if ok {
 | |
| 			return Branch{BranchKind: kind, Call: fn}
 | |
| 		}
 | |
| 	case *ast.EmptyStmt:
 | |
| 		return Empty.Branch()
 | |
| 	case *ast.LabeledStmt:
 | |
| 		return StmtBranch(stmt.Stmt)
 | |
| 	}
 | |
| 	return Regular.Branch()
 | |
| }
 | |
| 
 | |
| // String returns a brief string representation.
 | |
| func (b Branch) String() string {
 | |
| 	switch b.BranchKind {
 | |
| 	case Empty:
 | |
| 		return "{ }"
 | |
| 	case Regular:
 | |
| 		return "{ ... }"
 | |
| 	case Panic, Exit:
 | |
| 		return fmt.Sprintf("{ ... %v() }", b.Call)
 | |
| 	}
 | |
| 	return fmt.Sprintf("{ ... %v }", b.BranchKind)
 | |
| }
 | |
| 
 | |
| // LongString returns a longer form string representation.
 | |
| func (b Branch) LongString() string {
 | |
| 	switch b.BranchKind {
 | |
| 	case Panic, Exit:
 | |
| 		return fmt.Sprintf("call to %v function", b.Call)
 | |
| 	}
 | |
| 	return b.BranchKind.LongString()
 | |
| }
 | |
| 
 | |
| // HasDecls returns whether the branch has any top-level declarations.
 | |
| func (b Branch) HasDecls() bool {
 | |
| 	for _, stmt := range b.block {
 | |
| 		switch stmt := stmt.(type) {
 | |
| 		case *ast.DeclStmt:
 | |
| 			return true
 | |
| 		case *ast.AssignStmt:
 | |
| 			if stmt.Tok == token.DEFINE {
 | |
| 				return true
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 	return false
 | |
| }
 | |
| 
 | |
| // IsShort returns whether the branch is empty or consists of a single statement.
 | |
| func (b Branch) IsShort() bool {
 | |
| 	switch len(b.block) {
 | |
| 	case 0:
 | |
| 		return true
 | |
| 	case 1:
 | |
| 		return isShortStmt(b.block[0])
 | |
| 	case 2:
 | |
| 		return isShortStmt(b.block[1])
 | |
| 	}
 | |
| 	return false
 | |
| }
 | |
| 
 | |
| func isShortStmt(stmt ast.Stmt) bool {
 | |
| 	switch stmt.(type) {
 | |
| 	case *ast.BlockStmt, *ast.IfStmt, *ast.SwitchStmt, *ast.TypeSwitchStmt, *ast.SelectStmt, *ast.ForStmt, *ast.RangeStmt:
 | |
| 		return false
 | |
| 	}
 | |
| 	return true
 | |
| }
 |