Git Product home page Git Product logo

varnamelen's Introduction

GoDoc

varnamelen

A Go Analyzer that checks that the length of a variable's name matches its usage scope:

Variables with short names can be hard to use if the variable is used over a longer span of lines of code. A longer variable name may be easier to comprehend.

The analyzer also checks constants, parameters, named return values, method receivers, and type parameters.

Arbitrary declarations such as f *foo can be ignored, as well as idiomatic ok variables. Conventional Go parameters such as ctx context.Context or t *testing.T will always be ignored.

Example output

test.go:4:2: variable name 'x' is too short for the scope of its usage (varnamelen)
        x := 123
        ^
test.go:6:2: variable name 'i' is too short for the scope of its usage (varnamelen)
        i := 10
        ^

golangci-lint Integration

varnamelen is integrated into golangci-lint (though it may not always be the most recent version.)

Example configuration for golangci-lint:

linters-settings:
  varnamelen:
    # The longest distance, in source lines, that is being considered a "small scope." (defaults to 5)
    # Variables used in at most this many lines will be ignored.
    max-distance: 5
    # The minimum length of a variable's name that is considered "long." (defaults to 3)
    # Variable names that are at least this long will be ignored.
    min-name-length: 3
    # Check method receivers. (defaults to false)
    check-receiver: false
    # Check named return values. (defaults to false)
    check-return: false
    # Check type parameters. (defaults to false)
    check-type-param: false
    # Ignore "ok" variables that hold the bool return value of a type assertion. (defaults to false)
    ignore-type-assert-ok: false
    # Ignore "ok" variables that hold the bool return value of a map index. (defaults to false)
    ignore-map-index-ok: false
    # Ignore "ok" variables that hold the bool return value of a channel receive. (defaults to false)
    ignore-chan-recv-ok: false
    # Optional list of variable names that should be ignored completely. (defaults to empty list)
    ignore-names:
      - err
    # Optional list of variable declarations that should be ignored completely. (defaults to empty list)
    # Entries must be in one of the following forms (see below for examples):
    # - for variables, parameters, named return values, method receivers, or type parameters:
    #   <name> <type>  (<type> can also be a pointer/slice/map/chan/...)
    # - for constants: const <name>
    ignore-decls:
      - c echo.Context
      - t testing.T
      - f *foo.Bar
      - e error
      - i int
      - const C
      - T any
      - m map[string]int

Standalone Usage

The cmd/ folder provides a standalone command line utility. You can build it like this:

go build -o varnamelen ./cmd/

Usage

varnamelen: checks that the length of a variable's name matches its scope

Usage: varnamelen [-flag] [package]

A variable with a short name can be hard to use if the variable is used
over a longer span of lines of code. A longer variable name may be easier
to comprehend.

Flags:
  -V	print version and exit
  -all
    	no effect (deprecated)
  -c int
    	display offending line with this many lines of context (default -1)
  -checkReceiver
    	check method receiver names
  -checkReturn
    	check named return values
  -checkTypeParam
    	check type parameter names
  -cpuprofile string
    	write CPU profile to this file
  -debug string
    	debug flags, any subset of "fpstv"
  -fix
    	apply all suggested fixes
  -flags
    	print analyzer flags in JSON
  -ignoreChanRecvOk
    	ignore 'ok' variables that hold the bool return value of a channel receive
  -ignoreDecls value
    	comma-separated list of ignored variable declarations
  -ignoreMapIndexOk
    	ignore 'ok' variables that hold the bool return value of a map index
  -ignoreNames value
    	comma-separated list of ignored variable names
  -ignoreTypeAssertOk
    	ignore 'ok' variables that hold the bool return value of a type assertion
  -json
    	emit JSON output
  -maxDistance int
    	maximum number of lines of variable usage scope considered 'short' (default 5)
  -memprofile string
    	write memory profile to this file
  -minNameLength int
    	minimum length of variable name considered 'long' (default 3)
  -source
    	no effect (deprecated)
  -tags string
    	no effect (deprecated)
  -trace string
    	write trace log to this file
  -v	no effect (deprecated)

License

This package is licensed under the MIT license.

varnamelen's People

Contributors

blizzy78 avatar dependabot[bot] avatar jiriprox avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

Forkers

jiriprox jiajie99

varnamelen's Issues

max-distance: 0 does not work

I would like to use this tool to ban short variable names completely, except the ones explicitly allowed in the configuration.

However, when I set max-distance: 0, it does not trigger an error at all. It seems that the minimal distance is always 1.

http handler context

some HTTP frameworks like echo have context which is different from go context and sometimes we need to have them both so using the variable name c is a pattern for them.

// e.GET("/users/:id", getUser)
func getUser(c echo.Context) error {
  	// User ID from path `users/:id`
  	id := c.Param("id")
	return c.String(http.StatusOK, id)
}

I don't know how, but it would be great if we can consider this for popular frameworks.

Linter raises issues about actual words, for i loops, and range loops for being too short for the scope of usage

Hi!

I just updated a service from go 1.16 to 1.18 and unfortunately recently I have to disable this linter because it is deciding to raise issues of scope of usage, for such things as:

var ad Ad

Ad is an actual noun, which has two characters in it.

For i loop:

Raises the same issue for the "i". I think the iterator's naming is being "i" since the beginning of time, maybe it should be an exception.

Range loop:

For example if you're having a slice named Ads, for which you create a range loop the element will be ad (which is the singular version of ads).

golangci-lint ignore-decls config not working for parameters

My linter is giving me varnamelen warnings for my REST endpoint handler functions which I want to ignore.

internal/handler.go:83:35: parameter name 'w' is too short for the scope of its usage (varnamelen)
func GetSignin(w http.ResponseWriter, r *http.Request) {
                                  ^
internal/handler.go:171:33: parameter name 'w' is too short for the scope of its usage (varnamelen)
func Signout(w http.ResponseWriter, r *http.Request) {
                                ^
internal/handler.go:287:58: parameter name 'r' is too short for the scope of its usage (varnamelen)
func Sync(w http.ResponseWriter, r *http.Request) {
                                                         ^

My varnamelen config looks like this:

 varnamelen:
  # The longest distance, in source lines, that is being considered a "small scope." (defaults to 5)
  # Variables used in at most this many lines will be ignored.
  # max-distance: 5
  # The minimum length of a variable's name that is considered "long." (defaults to 3)
  # Variable names that are at least this long will be ignored.
  # min-name-length: 3
  # Check method receiver names. (defaults to false)
  # check-receiver: false
  # Check named return values. (defaults to false)
  # check-return: false
  # Ignore "ok" variables that hold the bool return value of a type assertion. (defaults to false)
  # ignore-type-assert-ok: false
  # Ignore "ok" variables that hold the bool return value of a map index. (defaults to false)
  # ignore-map-index-ok: false
  # Ignore "ok" variables that hold the bool return value of a channel receive. (defaults to false)
  # ignore-chan-recv-ok: false
  # Optional list of variable names that should be ignored completely. (defaults to empty list)
  ignore-names:
   - err
   - c
   - ctx
   - i
  # Optional list of variable declarations that should be ignored completely. (defaults to empty list)
  # Entries must be in the form of "<variable name> <type>" or "<variable name> *<type>" for
  # variables, or "const <name>" for constants.
  ignore-decls:
   - w http.ResponseWriter
   - r *http.Request
   - r http.Request
   - r *net/http/Request
   - r *mux.Router
  #  - t testing.T
  #  - f *foo.Bar
  #  - e error
  #  - i int
  #  - const C

I've had the same problem for other packages too. It seems none of my ignore-decls rules get used. My workaround so far has just been to add the letter to ignore-names, but this is far from ideal.

Here's my golangci-lint version:

golangci-lint --version
golangci-lint has version v1.43.0 built from (unknown, mod sum: "h1:SLwZFEmDgopqZpfP495zCtV9REUf551JJlJ51Ql7NZA=") on (unknown)

I've tried each ignore-decls rule individually just incase one broken rule caused them to all fail.

Any ideas why these rules aren't working?

feature: ability to ignore variables of particular type (results of functions work)

It would be great if linter can find the type of variable as a result of the function assigment. Like in next example.

func main() {
	e := echo.New()
	e.GET("/", func(c echo.Context) error {
		print("1")
		print("1")
		print("1")
		print("1") 
		print("1")
		return c.String(http.StatusOK, "Hello, World!")
	})
	e.Logger.Fatal(e.Start(":1323"))
}

For example this is how we can make it working now.

func main() {
	var e *echo.Echo
	e = echo.New()
	e.GET("/", func(c echo.Context) error {
		print("1")
		print("1")
		print("1")
		print("1") 
		print("1")
		return c.String(http.StatusOK, "Hello, World!")
	})
	e.Logger.Fatal(e.Start(":1323"))
}

I am using it as part of golangci-lint with the next configuration.

linter-settings:
  varnamelen:
    ignore-decls:
    - c echo.Context 
    - e *echo.Echo

Support ignoring const declarations

Constants such as physical values or well-known parameters of mathematical functions may have short names; however, the ignore-decls configs don't allow specifying allowed const declarations.

A code excerpt from one of my projects:

const (
	// C is the speed of light in a vacuum, m/s.
	C = 299792458
	// G is the gravitation constant, m^3/kg/s^2.
	G = 6.67408e-11
	// ...
)

As long as varnamelen checks constants, it should be possible to ignore them just like variables.

treat multi-line definitions as a single line

$ cat main.go
package main

type A struct {
        a1 int
        a2 int
        a3 int
        a4 int
        a5 int
        a6 int
        a7 int
        a8 int
        a9 int
        a0 int
}

func main() {
        i := A{
                a1: 0,
                a2: 0,
                a3: 0,
                a4: 0,
                a5: 0,
                a6: 0,
                a7: 0,
                a8: 0,
                a9: 0,
                a0: 0,
        }
        _ = i
}

expected: no error
actual:

$ golangci-lint run . --enable varnamelen
main.go:17:2: variable name 'i' is too short for the scope of its usage (varnamelen)
        i := A{
        ^

also confirmed with version 0.5.0

Checksum mismatch in go sumdb

I haven't quite worked out the issue but there seems to be a checksum mismatch in the Google sumdb. Raising some initial awareness with this ticket.

Relates to golangci/golangci-lint#2683

$ GOPROXY=direct go get github.com/blizzy78/[email protected]
go: downloading github.com/blizzy78/varnamelen v0.6.1
go: github.com/blizzy78/[email protected]: verifying module: checksum mismatch
        downloaded: h1:iYAU/3A6cpfRm2ZI0P/lece4jsc7GEbzsxTu+vBCChQ=
        sum.golang.org: h1:kttPCLzXFa+0nt++Cw9fb7GrSSM4KkyIAoX/vXsbuqA=

SECURITY ERROR
This download does NOT match the one reported by the checksum server.
The bits may have been replaced on the origin server, or an attacker may
have intercepted the download attempt.

For more information, see 'go help module-auth'.

Add option to ignore specific file patterns

The current linter is not configurable in turns of analysis scope.

It would be amazing to have the ability to switch of analysis for e.g. _test.go files or _generated.go files or alike.

ok pattern

There are cases like:

id, ok := claims["user_id"].(int)
if !ok {
}

which ok is a known pattern.

Ignore i (index) in for loop

Given this main.go file:

package main

func main() {
	for i := range []struct{}{} {
		/*
			Lorem
			ipsum
			dolor
			sit
			amet.
		*/
		_ = i
	}
}

And this config (golangci.yaml):

linters:
  disable-all: true
  enable:
    - varnamelen

linters-settings:
  varnamelen:
    ignore-decls:
      - i int

I should not get an error for main.go:4:6, but I get the following error when running golangci-lint run:

main.go:4:6: variable name 'i' is too short for the scope of its usage (varnamelen)
	for i := range []struct{}{} {
	   ^

ignore comment lines

$ cat main.go
package main

func main() {
        i := 0
        //
        //
        //
        //
        //
        //
        //
        //
        //
        //
        _ = i
}

expected: no error
actual:

$ golangci-lint run . --enable varnamelen
main.go:4:2: variable name 'i' is too short for the scope of its usage (varnamelen)
        i := 0
        ^

I confirmed that this reproduces on version 0.5.0

too short variables in constuctor

Hello. My structure initializing in constructor with options is marked as "too short".

What do you think about option to skip this case.

struct st {
  p1 bool
  p2 bool
  ....
}

type Option func(*st)

func New() st {
   s := st{
     // set default values
   }

   for _, o := range oo {
      o(&s)
   }

   return s
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.