Skip to content

Commit

Permalink
Add golint support
Browse files Browse the repository at this point in the history
  • Loading branch information
samuelmeuli committed Jan 1, 2020
1 parent 50f23e4 commit ddb234a
Show file tree
Hide file tree
Showing 9 changed files with 177 additions and 2 deletions.
12 changes: 12 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,18 @@ jobs:
with:
go-version: 1.13

# TODO: Remove step once actions/setup-go adds $GOPATH/bin to $PATH by default
# See https://github.com/actions/setup-go/issues/14
- name: Add Go to $PATH
run: |
echo "::set-env name=GOPATH::$(go env GOPATH)"
echo "::add-path::$(go env GOPATH)/bin"
- name: Install Go dependencies
run: |
cd ./test/linters/projects/golint
go get -u golang.org/x/lint/golint
# Node.js

- name: Install Node.js and Yarn
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ This action…

- **Go:**
- [gofmt](https://golang.org/cmd/gofmt)
- [golint](https://github.com/golang/lint)
- **JavaScript:**
- [ESLint](https://eslint.org)
- [Prettier](https://prettier.io)
Expand Down Expand Up @@ -133,7 +134,7 @@ All linters are disabled by default. To enable a linter, simply set the option w
eslint: true # Enables ESLint checks
```

`[linter]` can be one of `black`, `eslint`, `flake8`, `gofmt`, `prettier`, `stylelint`, and `swiftlint`:
`[linter]` can be one of `black`, `eslint`, `flake8`, `gofmt`, `golint`, `prettier`, `stylelint`, and `swiftlint`:

- **`[linter]`:** Enables the linter in your repository. Default: `false`
- **`[linter]_extensions`:** Extensions of files to check with the linter. Example: `eslint_extensions: js,ts` to lint both JavaScript and TypeScript files with ESLint. Default: See [`action.yml`](./action.yml)
Expand Down
12 changes: 12 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,18 @@ inputs:
description: Directory where the gofmt command should be run
required: false

golint:
description: Enable or disable golint checks
required: false
default: false
golint_extensions:
description: Extensions of files to check with golint
required: false
default: "go"
golint_dir:
description: Directory where the golint command should be run
required: false

# JavaScript

eslint:
Expand Down
2 changes: 1 addition & 1 deletion src/linters/flake8.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class Flake8 {
*/
static lint(dir, extensions, fix = false) {
if (fix) {
log(`${this.name} does not support auto-fixing code style issues`, "warning");
log(`${this.name} does not support auto-fixing`, "warning");
}
return run(`flake8 --filename ${extensions.map(ext => `"**${sep}*.${ext}"`).join(",")}`, {
dir,
Expand Down
78 changes: 78 additions & 0 deletions src/linters/golint.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
const commandExists = require("../../vendor/command-exists");
const { log, run } = require("../utils/action");
const { capitalizeFirstLetter } = require("../utils/string");

const PARSE_REGEX = /^(.+):([0-9]+):([0-9]+): (.+)$/gm;

/**
* https://github.com/golang/lint
*/
class Golint {
static get name() {
return "golint";
}

/**
* Verifies that all required programs are installed. Exits the GitHub action if one of the
* programs is missing
*
* @param {string} dir: Directory to run the linting program in
*/
static async verifySetup(dir) {
// Verify that golint is installed
if (!(await commandExists("golint"))) {
throw new Error(`${this.name} is not installed`);
}
}

/**
* Runs the linting program and returns the command output
*
* @param {string} dir: Directory to run the linting program in
* @param {string[]} extensions: Array of file extensions which should be linted
* @param {boolean} fix: Whether the linter should attempt to fix code style issues automatically
* @returns {string}: Results of the linting process
*/
static lint(dir, extensions, fix = false) {
if (extensions.length !== 1 || extensions[0] !== "go") {
throw new Error(`${this.name} error: File extensions are not configurable`);
}

if (fix) {
log(`${this.name} does not support auto-fixing`, "warning");
}
return run(`golint "."`, {
dir,
ignoreErrors: true,
}).stdout;
}

/**
* Parses the results of the linting process and returns it as a processable array
*
* @param {string} dir: Directory in which the linting program has been run
* @param {string} results: Results of the linting process
* @returns {object[]}: Parsed results
*/
static parseResults(dir, results) {
const matches = results.matchAll(PARSE_REGEX);

// Parsed results: [notices, warnings, failures]
const resultsParsed = [[], [], []];

for (const match of matches) {
const [_str, path, line, _column, text] = match;
const lineNr = parseInt(line, 10);
resultsParsed[2].push({
path,
firstLine: lineNr,
lastLine: lineNr,
message: capitalizeFirstLetter(text),
});
}

return resultsParsed;
}
}

module.exports = Golint;
2 changes: 2 additions & 0 deletions test/linters/linters.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const eslintParams = require("./params/eslint");
const eslintTypescriptParams = require("./params/eslint-typescript");
const flake8Params = require("./params/flake8");
const gofmtParams = require("./params/gofmt");
const golintParams = require("./params/golint");
const prettierParams = require("./params/prettier");
const stylelintParams = require("./params/stylelint");
const swiftlintParams = require("./params/swiftlint");
Expand All @@ -16,6 +17,7 @@ const linterParams = [
eslintTypescriptParams,
flake8Params,
gofmtParams,
golintParams,
prettierParams,
stylelintParams,
];
Expand Down
46 changes: 46 additions & 0 deletions test/linters/params/golint.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
const Golint = require("../../../src/linters/golint");

const testName = "golint";
const linter = Golint;
const extensions = ["go"];

const getLintResults = dir => {
const resultsFile1 =
"file1.go:14:9: if block ends with a return statement, so drop this else and outdent its block";
const resultsFile2 =
'file2.go:3:1: comment on exported function Divide should be of the form "Divide ..."';
return [`${resultsFile1}\n${resultsFile2}`, `${resultsFile2}\n${resultsFile1}`];
};

const parsedLintResults = [
[],
[],
[
{
path: "file1.go",
firstLine: 14,
lastLine: 14,
message: `If block ends with a return statement, so drop this else and outdent its block`,
},
{
path: "file2.go",
firstLine: 3,
lastLine: 3,
message: `Comment on exported function Divide should be of the form "Divide ..."`,
},
],
];

const getFixResults = getLintResults;

const parsedFixResults = parsedLintResults;

module.exports = [
testName,
linter,
extensions,
getLintResults,
getFixResults,
parsedLintResults,
parsedFixResults,
];
18 changes: 18 additions & 0 deletions test/linters/projects/golint/file1.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package main

import "fmt"

var str = "world"

func main() {
fmt.Println("hello " + doSomething(str))
}

func doSomething(str string) string {
if str == "" {
return "default"
} else {
// Error for unnecessary "else" statement
return str
}
}
6 changes: 6 additions & 0 deletions test/linters/projects/golint/file2.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package main

// Error for incorrect comment format
func Divide(num1 int, num2 int) int {
return num1 / num2
}

0 comments on commit ddb234a

Please sign in to comment.