Source File
gover.go
Belonging Package
golang.org/x/tools/internal/versions
// Copyright 2023 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.
// This is a fork of internal/gover for use by x/tools until
// go1.21 and earlier are no longer supported by x/tools.
package versions
import
// A gover is a parsed Go gover: major[.Minor[.Patch]][kind[pre]]
// The numbers are the original decimal strings to avoid integer overflows
// and since there is very little actual math. (Probably overflow doesn't matter in practice,
// but at the time this code was written, there was an existing test that used
// go1.99999999999, which does not fit in an int on 32-bit platforms.
// The "big decimal" representation avoids the problem entirely.)
type gover struct {
major string // decimal
minor string // decimal or ""
patch string // decimal or ""
kind string // "", "alpha", "beta", "rc"
pre string // decimal or ""
}
// compare returns -1, 0, or +1 depending on whether
// x < y, x == y, or x > y, interpreted as toolchain versions.
// The versions x and y must not begin with a "go" prefix: just "1.21" not "go1.21".
// Malformed versions compare less than well-formed versions and equal to each other.
// The language version "1.21" compares less than the release candidate and eventual releases "1.21rc1" and "1.21.0".
func (, string) int {
:= parse()
:= parse()
if := cmpInt(.major, .major); != 0 {
return
}
if := cmpInt(.minor, .minor); != 0 {
return
}
if := cmpInt(.patch, .patch); != 0 {
return
}
if := strings.Compare(.kind, .kind); != 0 { // "" < alpha < beta < rc
return
}
if := cmpInt(.pre, .pre); != 0 {
return
}
return 0
}
// lang returns the Go language version. For example, lang("1.2.3") == "1.2".
func ( string) string {
:= parse()
if .minor == "" || .major == "1" && .minor == "0" {
return .major
}
return .major + "." + .minor
}
// isValid reports whether the version x is valid.
func ( string) bool {
return parse() != gover{}
}
// parse parses the Go version string x into a version.
// It returns the zero version if x is malformed.
func ( string) gover {
var gover
// Parse major version.
var bool
.major, , = cutInt()
if ! {
return gover{}
}
if == "" {
// Interpret "1" as "1.0.0".
.minor = "0"
.patch = "0"
return
}
// Parse . before minor version.
if [0] != '.' {
return gover{}
}
// Parse minor version.
.minor, , = cutInt([1:])
if ! {
return gover{}
}
if == "" {
// Patch missing is same as "0" for older versions.
// Starting in Go 1.21, patch missing is different from explicit .0.
if cmpInt(.minor, "21") < 0 {
.patch = "0"
}
return
}
// Parse patch if present.
if [0] == '.' {
.patch, , = cutInt([1:])
if ! || != "" {
// Note that we are disallowing prereleases (alpha, beta, rc) for patch releases here (x != "").
// Allowing them would be a bit confusing because we already have:
// 1.21 < 1.21rc1
// But a prerelease of a patch would have the opposite effect:
// 1.21.3rc1 < 1.21.3
// We've never needed them before, so let's not start now.
return gover{}
}
return
}
// Parse prerelease.
:= 0
for < len() && ([] < '0' || '9' < []) {
if [] < 'a' || 'z' < [] {
return gover{}
}
++
}
if == 0 {
return gover{}
}
.kind, = [:], [:]
if == "" {
return
}
.pre, , = cutInt()
if ! || != "" {
return gover{}
}
return
}
// cutInt scans the leading decimal number at the start of x to an integer
// and returns that value and the rest of the string.
func ( string) (, string, bool) {
:= 0
for < len() && '0' <= [] && [] <= '9' {
++
}
if == 0 || [0] == '0' && != 1 { // no digits or unnecessary leading zero
return "", "", false
}
return [:], [:], true
}
// cmpInt returns cmp.Compare(x, y) interpreting x and y as decimal numbers.
// (Copied from golang.org/x/mod/semver's compareInt.)
func (, string) int {
if == {
return 0
}
if len() < len() {
return -1
}
if len() > len() {
return +1
}
if < {
return -1
} else {
return +1
}
}
The pages are generated with Golds v0.7.6. (GOOS=linux GOARCH=amd64)