github.com/karrick/go@v0.0.0-20170817181416-d5b0ec858b37/src/cmd/vet/buildtag.go (about) 1 // Copyright 2013 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 main 6 7 import ( 8 "bytes" 9 "fmt" 10 "os" 11 "strings" 12 "unicode" 13 ) 14 15 var ( 16 nl = []byte("\n") 17 slashSlash = []byte("//") 18 plusBuild = []byte("+build") 19 ) 20 21 // checkBuildTag checks that build tags are in the correct location and well-formed. 22 func checkBuildTag(name string, data []byte) { 23 if !vet("buildtags") { 24 return 25 } 26 lines := bytes.SplitAfter(data, nl) 27 28 // Determine cutpoint where +build comments are no longer valid. 29 // They are valid in leading // comments in the file followed by 30 // a blank line. 31 var cutoff int 32 for i, line := range lines { 33 line = bytes.TrimSpace(line) 34 if len(line) == 0 { 35 cutoff = i 36 continue 37 } 38 if bytes.HasPrefix(line, slashSlash) { 39 continue 40 } 41 break 42 } 43 44 for i, line := range lines { 45 line = bytes.TrimSpace(line) 46 if !bytes.HasPrefix(line, slashSlash) { 47 continue 48 } 49 text := bytes.TrimSpace(line[2:]) 50 if bytes.HasPrefix(text, plusBuild) { 51 fields := bytes.Fields(text) 52 if !bytes.Equal(fields[0], plusBuild) { 53 // Comment is something like +buildasdf not +build. 54 fmt.Fprintf(os.Stderr, "%s:%d: possible malformed +build comment\n", name, i+1) 55 setExit(1) 56 continue 57 } 58 if i >= cutoff { 59 fmt.Fprintf(os.Stderr, "%s:%d: +build comment must appear before package clause and be followed by a blank line\n", name, i+1) 60 setExit(1) 61 continue 62 } 63 // Check arguments. 64 Args: 65 for _, arg := range fields[1:] { 66 for _, elem := range strings.Split(string(arg), ",") { 67 if strings.HasPrefix(elem, "!!") { 68 fmt.Fprintf(os.Stderr, "%s:%d: invalid double negative in build constraint: %s\n", name, i+1, arg) 69 setExit(1) 70 break Args 71 } 72 if strings.HasPrefix(elem, "!") { 73 elem = elem[1:] 74 } 75 for _, c := range elem { 76 if !unicode.IsLetter(c) && !unicode.IsDigit(c) && c != '_' && c != '.' { 77 fmt.Fprintf(os.Stderr, "%s:%d: invalid non-alphanumeric build constraint: %s\n", name, i+1, arg) 78 setExit(1) 79 break Args 80 } 81 } 82 } 83 } 84 continue 85 } 86 // Comment with +build but not at beginning. 87 if bytes.Contains(line, plusBuild) && i < cutoff { 88 fmt.Fprintf(os.Stderr, "%s:%d: possible malformed +build comment\n", name, i+1) 89 setExit(1) 90 continue 91 } 92 } 93 }