Source file src/go/types/version.go

     1  // Copyright 2021 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package types
     6  
     7  import (
     8  	"fmt"
     9  	"go/ast"
    10  	"go/token"
    11  	"regexp"
    12  	"strconv"
    13  	"strings"
    14  )
    15  
    16  // langCompat reports an error if the representation of a numeric
    17  // literal is not compatible with the current language version.
    18  func (check *Checker) langCompat(lit *ast.BasicLit) {
    19  	s := lit.Value
    20  	if len(s) <= 2 || check.allowVersion(check.pkg, 1, 13) {
    21  		return
    22  	}
    23  	// len(s) > 2
    24  	if strings.Contains(s, "_") {
    25  		check.errorf(lit, _InvalidLit, "underscores in numeric literals requires go1.13 or later")
    26  		return
    27  	}
    28  	if s[0] != '0' {
    29  		return
    30  	}
    31  	radix := s[1]
    32  	if radix == 'b' || radix == 'B' {
    33  		check.errorf(lit, _InvalidLit, "binary literals requires go1.13 or later")
    34  		return
    35  	}
    36  	if radix == 'o' || radix == 'O' {
    37  		check.errorf(lit, _InvalidLit, "0o/0O-style octal literals requires go1.13 or later")
    38  		return
    39  	}
    40  	if lit.Kind != token.INT && (radix == 'x' || radix == 'X') {
    41  		check.errorf(lit, _InvalidLit, "hexadecimal floating-point literals requires go1.13 or later")
    42  	}
    43  }
    44  
    45  // allowVersion reports whether the given package
    46  // is allowed to use version major.minor.
    47  func (check *Checker) allowVersion(pkg *Package, major, minor int) bool {
    48  	// We assume that imported packages have all been checked,
    49  	// so we only have to check for the local package.
    50  	if pkg != check.pkg {
    51  		return true
    52  	}
    53  	ma, mi := check.version.major, check.version.minor
    54  	return ma == 0 && mi == 0 || ma > major || ma == major && mi >= minor
    55  }
    56  
    57  type version struct {
    58  	major, minor int
    59  }
    60  
    61  // parseGoVersion parses a Go version string (such as "go1.12")
    62  // and returns the version, or an error. If s is the empty
    63  // string, the version is 0.0.
    64  func parseGoVersion(s string) (v version, err error) {
    65  	if s == "" {
    66  		return
    67  	}
    68  	matches := goVersionRx.FindStringSubmatch(s)
    69  	if matches == nil {
    70  		err = fmt.Errorf(`should be something like "go1.12"`)
    71  		return
    72  	}
    73  	v.major, err = strconv.Atoi(matches[1])
    74  	if err != nil {
    75  		return
    76  	}
    77  	v.minor, err = strconv.Atoi(matches[2])
    78  	return
    79  }
    80  
    81  // goVersionRx matches a Go version string, e.g. "go1.12".
    82  var goVersionRx = regexp.MustCompile(`^go([1-9][0-9]*)\.(0|[1-9][0-9]*)$`)
    83  

View as plain text