Git Product home page Git Product logo

lint's Introduction

lint

GoDoc Build Status

Work in progress. Its API might change before the 1.0 release.

This package intends to define simple interfaces that Go code checkers can implement. This would simplify calling them from Go code, as well as running multiple linters while sharing initial loading work.

metalint

go get -u mvdan.cc/lint/cmd/metalint

The start of a linter that runs many linters leveraging the common interface. Not stable yet.

Linters included:

Related projects

lint's People

Contributors

mvdan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

lint's Issues

Build flags and other options

Quite a number of linters accept flags that change their behavior. The most common case is whether or not to load test files via go/loader.

Others include build tags, or what Go versions to check against (e.g. for new std stuff).

With the current API, none of those are possible. Some ideas:

  • Should a linter somehow report its options via the interface, having ways to use them (e.g. funcs)?
  • Instead of the above, should linters only be allowed to receive options?

Define whether or not the order of the results matter

If the order of the list of issues/warnings that a linter returns matters, the caller should not modify it.

If the order does not matter, the list may well be randomized (this can happen if ssautil.AllFunctions is used) and the caller should take care of sorting. Sorting could be by token.Pos, for example.

I tend to lean towards the latter. Perhaps we could provide code to automatically sort the issues, but it would be fairly trivial.

Use an union of TypeCheckFuncBodies

Right now linter implementations cannot define what func bodies they need type-checked. So at the moment, metacheck and any other tools have to be safe and type-check everything.

This works fine, but especially on packages with lots of dependencies this can lead to lots of wasted time.

I propose that each linter may expose a TypeCheckFuncBodies method. If they don't, it defaults to return true - type-check all func bodies, like we do now. We must be safe if we don't know better.

Either way, when running multiple linters we can use the union of all of these funcs as follows (simplified):

fn := func(path string) bool {
    for _, c := range checkers {
        if c.TypeCheckFuncBodies(path) {
            return true
        }
    }
    return false
}

This way, if none of the linters we're running need to type-check the func bodies of a package, we won't. As soon as one of them does (or hasn't implemented the method), we will.

Get initial package(s) filenames from loader.Program

Assuming a linter implements Checker as follows, but needs the original filenames because it doesn't actually operate on the AST, but rather does raw text operations like checking line-length, spelling etc. Does it really need to get the filenames via token.Position?

func Checker(lprog *loader.Program, prog *ssa.Program) {
       for _, info := range lprog.InitialPackages() {
                for _, file := range info.Files {
                        pkg := file.Package
                        pos := lprog.Fset.Position(pkg)
                        fmt.Println(pos.Filename) // do something with files
                }
        }
}

Am I missing something obvious?

Figure out better names

Should Checker be Linter?

Should Warning be Issue?

Just some ideas. Names aren't set in stone.

Who wants to get involved?

This is a bit of a meta-issue. If anyone wants to help bring this to life, comment here and I'll add you as contributors to the repo.

Please don't commit directly to master - changes should be discussed in PRs. This is more to be able to mention people easier and manage issues without me getting in the way.

Better support for linters that don't require all of go/loader

Some linters don't even need the *loader.Program, for example lll quite happily just opens and scans the raw source files to find overly long lines.

How would such linters integrate with lint? Or to put it the other way around: How would lint integrate with tools from the Go linter ecosystem like gometalinter?

A) lint could attempt to support all kinds of linters, even those that operate on a different level (like line-length, spell-checking etc.) and do not actually benefit from receiving parsed Go code. This way, lint would become kind of a "better" (i.e. more efficient) version of gometalinter.

B) lint could focus on optimizing performance of linters that actually rely on go/loader (and possibly ssa) and become a metalinter for just those linters. In that case, how would lint integrate with already widely used tools like gometalinter?

If A), linters need a way to specify their expectations (see #5). This way, we can decide what we actually need to provide to the requested linters.

If B), I would propose that lint does not only implement a metalinter command that runs all supported linters, but rather also an API that allows for metalinters with broader scope (like gometalinter) to call all linters that lint supports and collect the output in a reasonable way (through the lint interface, not plain text).

General information from each linter

Should the main interface include a method to get bits of general info from the linter? For example, the linter's name:

type Checker interface {
    Name() string
    [...]
}

This raises further questions, like whether names should be unique.

Avoid work with linters that don't need ssa

If a linter doesn't need ssa it's a bit silly to load all of that if no other linters need it.

Right now, the interface doesn't let linters specify what information they need.

For simplicity, let's not include type info here. go/loader has type info at its core, and I don't believe any linter is particularly useful only with go/ast.

Extra information in the Issue struct

I assume token.Pos is enough to point at a certain problem. With the caller's token.FileSet, that's enough to get filename, line and column. I don't think we need end positions for linters.

I wonder if a message string is enough on its own, though. Some linters categorize their warnings. Some others might want to give hints on what the developer should do. Should all of these just be part of the string, or should they be treated separately?

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.