openly-engineering / openlynt

Go lint tool with customizable rules.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

openlynt

openlynt is a lint tool for Go that works on individual ast nodes. This tool is a work-in-progress - we'll add more as we encode our rules. More documentation will follow as well once things are solidified.

Supported rules:

  • required formatting of named import declarations

Install

go get -u go.openly.dev/openlynt/cmd/openlynt

Usage

A sample openlynt.yml file can be found at cmd/openlynt/testdata/openlynt.yml.

You can provide a path to the openlynt.yml file via -rules or place it in the current directory as .openlynt.yml.

To provide a path to the source files to parse, you can either pass -path OR run the following: openlynt path/

Example

For this example, we have package main that must import several other packages that fulfill an interface. For clarity and sanity, we require these packages to be named imports - and to be named following a certain pattern. In this case, we want them named pkg<PREFIX>v<version>.

package main

import (
	"fmt"

	"xyz.org/pkg/prefix/v503"		// unnamed
	INCORRECTv99 "xyz.org/pkg/prefix2/v99"	// wrong name
	pkgOKv1 "xyz.org/pkg/ok/v1"		// correct name
)

func main() {
	fmt.Println("...")
}

Our ruleset (.openlynt.yml) would be:

rules:

  rule_pkgprefix:
    type: import
    name: Named Import Rule
    if:
      # any import path that contains "pkg/[a-z0-9]+/v\d+", ie "pkg/something/v1"
      path: regexp: \/pkg\/(?P<prefix>[a-z0-9]+)\/v(?P<version>[0-9]+)

    require:
      # require the named import to match the following, eg "pkgSOMETHINGv1"
      name: pkg{{ "${prefix}" | upper }}v${version}

Running openlynt against this source file would result in:

$ ./openlynt -path testdata -rules testdata/openlynt.yml && echo "ok"
22:25:51 testdata/incorrect.go: expected import("xyz.org/pkg/prefix/v503") to be named(pkgPREFIXv503), but it was()
22:25:51 testdata/incorrect.go: expected import("xyz.org/pkg/prefix2/v99") to be named(pkgPREFIX2v99), but it was(INCORRECTv99)

After fixing:

$ ./openlynt -path testdata/correct.go -rules testdata/openlynt.yml && echo "ok"
ok

Supported Rules

At the moment, the following rule types are supported.

import

rule_short_name:
  type: import
  name: Friendly Rule Name

  if:
    path: REGEXP

  require:
    name: "custom-import-name-template"

The import rule supports text/template replacements with your regexp, as well as sprig functions - eg, piping a named-regex-match into upper, lower, plural, etc.

comment_group

rule_short_name:
  type: comment_group
  name: Friendly Rule Name

  if:
    text: REGEXP

  require:
    # optional
    text: REGEXP

    # optional
    len: int

The comment_group rule supports regexp matches and requirements for the entire comment group text. It will match both multiple lines of // in succession as well as /*.

The len parameter specifies an optional required minimum-line-count for a matching comment. As an example, if you require a TODO comment to contain a link to an issue tracker and have at least 2 lines of information about the problem:

rule_todo:
  type: comment_group
  name: TODO Requirement
  if:
    text: TODO

  require:
    text: "https?://github.com/your/project/issues/\\d+"
    len: 2

A comment like this would fail to pass:

// TODO: I'm not saying anything useful or linking to the issue.

About

Go lint tool with customizable rules.

License:MIT License


Languages

Language:Go 100.0%