blob: ccf764ef89b4b57ee0a530e971ae596cbd5bdec2 [file] [log] [blame]
Dan Willemsen38f2dba2016-07-08 14:54:35 -07001// Copyright 2013 The Go Authors. All rights reserved.
Dan Willemsen09eb3b12015-09-16 14:34:17 -07002// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package main
6
7import (
8 "bytes"
9 "fmt"
10 "os"
11 "strings"
12 "unicode"
13)
14
15var (
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.
22func 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}