github.com/peggyl/go@v0.0.0-20151008231540-ae315999c2d5/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 continue 56 } 57 if i >= cutoff { 58 fmt.Fprintf(os.Stderr, "%s:%d: +build comment must appear before package clause and be followed by a blank line\n", name, i+1) 59 setExit(1) 60 continue 61 } 62 // Check arguments. 63 Args: 64 for _, arg := range fields[1:] { 65 for _, elem := range strings.Split(string(arg), ",") { 66 if strings.HasPrefix(elem, "!!") { 67 fmt.Fprintf(os.Stderr, "%s:%d: invalid double negative in build constraint: %s\n", name, i+1, arg) 68 setExit(1) 69 break Args 70 } 71 if strings.HasPrefix(elem, "!") { 72 elem = elem[1:] 73 } 74 for _, c := range elem { 75 if !unicode.IsLetter(c) && !unicode.IsDigit(c) && c != '_' && c != '.' { 76 fmt.Fprintf(os.Stderr, "%s:%d: invalid non-alphanumeric build constraint: %s\n", name, i+1, arg) 77 setExit(1) 78 break Args 79 } 80 } 81 } 82 } 83 continue 84 } 85 // Comment with +build but not at beginning. 86 if bytes.Contains(line, plusBuild) && i < cutoff { 87 fmt.Fprintf(os.Stderr, "%s:%d: possible malformed +build comment\n", name, i+1) 88 continue 89 } 90 } 91 }