...

Source file src/github.com/bazelbuild/rules_go/go/tools/builders/flags.go

Documentation: github.com/bazelbuild/rules_go/go/tools/builders

     1  // Copyright 2017 The Bazel Authors. All rights reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //    http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package main
    16  
    17  import (
    18  	"errors"
    19  	"fmt"
    20  	"go/build"
    21  	"strings"
    22  	"unicode"
    23  )
    24  
    25  // multiFlag allows repeated string flags to be collected into a slice
    26  type multiFlag []string
    27  
    28  func (m *multiFlag) String() string {
    29  	if m == nil || len(*m) == 0 {
    30  		return ""
    31  	}
    32  	return fmt.Sprint(*m)
    33  }
    34  
    35  func (m *multiFlag) Set(v string) error {
    36  	(*m) = append(*m, v)
    37  	return nil
    38  }
    39  
    40  // quoteMultiFlag allows repeated string flags to be collected into a slice.
    41  // Flags are split on spaces. Single quotes are removed, and spaces within
    42  // quotes are removed. Literal quotes may be escaped with a backslash.
    43  type quoteMultiFlag []string
    44  
    45  func (m *quoteMultiFlag) String() string {
    46  	if m == nil || len(*m) == 0 {
    47  		return ""
    48  	}
    49  	return fmt.Sprint(*m)
    50  }
    51  
    52  func (m *quoteMultiFlag) Set(v string) error {
    53  	fs, err := splitQuoted(v)
    54  	if err != nil {
    55  		return err
    56  	}
    57  	*m = append(*m, fs...)
    58  	return nil
    59  }
    60  
    61  // splitQuoted splits the string s around each instance of one or more consecutive
    62  // white space characters while taking into account quotes and escaping, and
    63  // returns an array of substrings of s or an empty list if s contains only white space.
    64  // Single quotes and double quotes are recognized to prevent splitting within the
    65  // quoted region, and are removed from the resulting substrings. If a quote in s
    66  // isn't closed err will be set and r will have the unclosed argument as the
    67  // last element. The backslash is used for escaping.
    68  //
    69  // For example, the following string:
    70  //
    71  //     a b:"c d" 'e''f'  "g\""
    72  //
    73  // Would be parsed as:
    74  //
    75  //     []string{"a", "b:c d", "ef", `g"`}
    76  //
    77  // Copied from go/build.splitQuoted. Also in Gazelle (where tests are).
    78  func splitQuoted(s string) (r []string, err error) {
    79  	var args []string
    80  	arg := make([]rune, len(s))
    81  	escaped := false
    82  	quoted := false
    83  	quote := '\x00'
    84  	i := 0
    85  	for _, rune := range s {
    86  		switch {
    87  		case escaped:
    88  			escaped = false
    89  		case rune == '\\':
    90  			escaped = true
    91  			continue
    92  		case quote != '\x00':
    93  			if rune == quote {
    94  				quote = '\x00'
    95  				continue
    96  			}
    97  		case rune == '"' || rune == '\'':
    98  			quoted = true
    99  			quote = rune
   100  			continue
   101  		case unicode.IsSpace(rune):
   102  			if quoted || i > 0 {
   103  				quoted = false
   104  				args = append(args, string(arg[:i]))
   105  				i = 0
   106  			}
   107  			continue
   108  		}
   109  		arg[i] = rune
   110  		i++
   111  	}
   112  	if quoted || i > 0 {
   113  		args = append(args, string(arg[:i]))
   114  	}
   115  	if quote != 0 {
   116  		err = errors.New("unclosed quote")
   117  	} else if escaped {
   118  		err = errors.New("unfinished escaping")
   119  	}
   120  	return args, err
   121  }
   122  
   123  // tagFlag adds tags to the build.Default context. Tags are expected to be
   124  // formatted as a comma-separated list.
   125  type tagFlag struct{}
   126  
   127  func (f *tagFlag) String() string {
   128  	return strings.Join(build.Default.BuildTags, ",")
   129  }
   130  
   131  func (f *tagFlag) Set(opt string) error {
   132  	tags := strings.Split(opt, ",")
   133  	build.Default.BuildTags = append(build.Default.BuildTags, tags...)
   134  	return nil
   135  }
   136  

View as plain text