File: gofumpt_120.go

package info (click to toggle)
golang-golang-x-tools 1%3A0.25.0%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites: experimental, forky, sid, trixie
  • size: 22,724 kB
  • sloc: javascript: 2,027; asm: 1,645; sh: 166; yacc: 155; makefile: 49; ansic: 8
file content (80 lines) | stat: -rw-r--r-- 2,160 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

//go:build go1.20
// +build go1.20

package settings

import (
	"context"
	"fmt"

	"mvdan.cc/gofumpt/format"
)

const GofumptSupported = true

// GofumptFormat allows the gopls module to wire in a call to
// gofumpt/format.Source. langVersion and modulePath are used for some
// Gofumpt formatting rules -- see the Gofumpt documentation for details.
var GofumptFormat = func(ctx context.Context, langVersion, modulePath string, src []byte) ([]byte, error) {
	fixedVersion, err := fixLangVersion(langVersion)
	if err != nil {
		return nil, err
	}
	return format.Source(src, format.Options{
		LangVersion: fixedVersion,
		ModulePath:  modulePath,
	})
}

// fixLangVersion function cleans the input so that gofumpt doesn't panic. It is
// rather permissive, and accepts version strings that aren't technically valid
// in a go.mod file.
//
// More specifically, it looks for an optional 'v' followed by 1-3
// '.'-separated numbers. The resulting string is stripped of any suffix beyond
// this expected version number pattern.
//
// See also golang/go#61692: gofumpt does not accept the new language versions
// appearing in go.mod files (e.g. go1.21rc3).
func fixLangVersion(input string) (string, error) {
	bad := func() (string, error) {
		return "", fmt.Errorf("invalid language version syntax %q", input)
	}
	if input == "" {
		return input, nil
	}
	i := 0
	if input[0] == 'v' { // be flexible about 'v'
		i++
	}
	// takeDigits consumes ascii numerals 0-9 and reports if at least one was
	// consumed.
	takeDigits := func() bool {
		found := false
		for ; i < len(input) && '0' <= input[i] && input[i] <= '9'; i++ {
			found = true
		}
		return found
	}
	if !takeDigits() { // versions must start with at least one number
		return bad()
	}

	// Accept optional minor and patch versions.
	for n := 0; n < 2; n++ {
		if i < len(input) && input[i] == '.' {
			// Look for minor/patch version.
			i++
			if !takeDigits() {
				i--
				break
			}
		}
	}
	// Accept any suffix.
	return input[:i], nil
}