From 678ae9fcaf4bda05a804782e0dd717ec570462e4 Mon Sep 17 00:00:00 2001
From: Kailun Qin <kailun.qin@intel.com>
Date: Wed, 23 Jun 2021 11:56:20 +0800
Subject: [PATCH] gofumpt: Add lang-version option (#2069)

---
 .golangci.example.yml          |  3 +++
 pkg/config/linters_settings.go |  6 ++++--
 pkg/golinters/gofumpt.go       | 22 +++++++++++++++++++---
 3 files changed, 26 insertions(+), 5 deletions(-)

diff --git a/.golangci.example.yml b/.golangci.example.yml
index 303f1f67..350029ea 100644
--- a/.golangci.example.yml
+++ b/.golangci.example.yml
@@ -259,6 +259,9 @@ linters-settings:
     simplify: true
 
   gofumpt:
+    # Select the Go version to target. The default is `1.15`.
+    lang-version: "1.15"
+
     # Choose whether or not to use the extra rules that are disabled
     # by default
     extra-rules: false
diff --git a/pkg/config/linters_settings.go b/pkg/config/linters_settings.go
index 7487bbae..0a4d0a5b 100644
--- a/pkg/config/linters_settings.go
+++ b/pkg/config/linters_settings.go
@@ -59,7 +59,8 @@ var defaultLintersSettings = LintersSettings{
 		DefaultSignifiesExhaustive: false,
 	},
 	Gofumpt: GofumptSettings{
-		ExtraRules: false,
+		LangVersion: "",
+		ExtraRules:  false,
 	},
 	ErrorLint: ErrorLintSettings{
 		Errorf:     true,
@@ -232,7 +233,8 @@ type GoFmtSettings struct {
 }
 
 type GofumptSettings struct {
-	ExtraRules bool `mapstructure:"extra-rules"`
+	LangVersion string `mapstructure:"lang-version"`
+	ExtraRules  bool   `mapstructure:"extra-rules"`
 }
 
 type GoHeaderSettings struct {
diff --git a/pkg/golinters/gofumpt.go b/pkg/golinters/gofumpt.go
index e91e54ee..75c08814 100644
--- a/pkg/golinters/gofumpt.go
+++ b/pkg/golinters/gofumpt.go
@@ -11,6 +11,7 @@ import (
 	"golang.org/x/tools/go/analysis"
 	"mvdan.cc/gofumpt/format"
 
+	"github.com/golangci/golangci-lint/pkg/config"
 	"github.com/golangci/golangci-lint/pkg/golinters/goanalysis"
 	"github.com/golangci/golangci-lint/pkg/lint/linter"
 )
@@ -32,6 +33,13 @@ func NewGofumpt() *goanalysis.Linter {
 		[]*analysis.Analyzer{analyzer},
 		nil,
 	).WithContextSetter(func(lintCtx *linter.Context) {
+		settings := lintCtx.Settings().Gofumpt
+
+		options := format.Options{
+			LangVersion: getLangVersion(settings),
+			ExtraRules:  settings.ExtraRules,
+		}
+
 		analyzer.Run = func(pass *analysis.Pass) (interface{}, error) {
 			var fileNames []string
 			for _, f := range pass.Files {
@@ -46,12 +54,12 @@ func NewGofumpt() *goanalysis.Linter {
 				if err != nil {
 					return nil, fmt.Errorf("unable to open file %s: %w", f, err)
 				}
-				output, err := format.Source(input, format.Options{
-					ExtraRules: lintCtx.Settings().Gofumpt.ExtraRules,
-				})
+
+				output, err := format.Source(input, options)
 				if err != nil {
 					return nil, fmt.Errorf("error while running gofumpt: %w", err)
 				}
+
 				if !bytes.Equal(input, output) {
 					out := bytes.Buffer{}
 					_, err = out.WriteString(fmt.Sprintf("--- %[1]s\n+++ %[1]s\n", f))
@@ -90,3 +98,11 @@ func NewGofumpt() *goanalysis.Linter {
 		return resIssues
 	}).WithLoadMode(goanalysis.LoadModeSyntax)
 }
+
+func getLangVersion(settings config.GofumptSettings) string {
+	if settings.LangVersion == "" {
+		// TODO: defaults to "1.15", in the future (v2) must be set by using build.Default.ReleaseTags like staticcheck.
+		return "1.15"
+	}
+	return settings.LangVersion
+}