Remove BPA from Makefile
[icn.git] / cmd / bpa-operator / vendor / sigs.k8s.io / controller-tools / pkg / internal / general / util.go
1 /*
2 Copyright 2018 The Kubernetes Authors.
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8     http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17 package general
18
19 import (
20         "fmt"
21         "go/ast"
22         "go/parser"
23         "go/token"
24         "os"
25         "path/filepath"
26         "strings"
27 )
28
29 // isGoFile filters files from parsing.
30 func isGoFile(f os.FileInfo) bool {
31         // ignore non-Go or Go test files
32         name := f.Name()
33         return !f.IsDir() &&
34                 !strings.HasPrefix(name, ".") &&
35                 !strings.HasSuffix(name, "_test.go") &&
36                 strings.HasSuffix(name, ".go")
37 }
38
39 // GetAnnotation extracts the annotation from comment text.
40 // It will return "foo" for comment "+kubebuilder:webhook:foo" .
41 func GetAnnotation(c, name string) string {
42         prefix := fmt.Sprintf("+%s:", name)
43         if strings.HasPrefix(c, prefix) {
44                 return strings.TrimPrefix(c, prefix)
45         }
46         return ""
47 }
48
49 // ParseKV parses key-value string formatted as "foo=bar" and returns key and value.
50 func ParseKV(s string) (key, value string, err error) {
51         kv := strings.Split(s, "=")
52         if len(kv) != 2 {
53                 err = fmt.Errorf("invalid key value pair")
54                 return key, value, err
55         }
56         key, value = kv[0], kv[1]
57         if strings.HasPrefix(value, "\"") && strings.HasSuffix(value, "\"") {
58                 value = value[1 : len(value)-1]
59         }
60         return key, value, err
61 }
62
63 // ParseDir parses the Go files under given directory and parses the annotation by
64 // invoking the parseFn function on each comment group (multi-lines comments).
65 // TODO(droot): extend it to multiple dirs
66 func ParseDir(dir string, parseFn func(string) error) error {
67         fset := token.NewFileSet()
68
69         err := filepath.Walk(dir,
70                 func(path string, info os.FileInfo, _ error) error {
71                         if !isGoFile(info) {
72                                 // TODO(droot): enable this output based on verbose flag
73                                 // fmt.Println("skipping non-go file", path)
74                                 return nil
75                         }
76                         return ParseFile(fset, path, nil, parseFn)
77                 })
78         return err
79 }
80
81 // ParseFile parses given filename or content src and parses annotations by
82 // invoking the parseFn function on each comment group (multi-lines comments).
83 func ParseFile(fset *token.FileSet, filename string, src interface{}, parseFn func(string) error) error {
84         f, err := parser.ParseFile(fset, filename, src, parser.ParseComments)
85         if err != nil {
86                 fmt.Printf("error from parse.ParseFile: %v", err)
87                 return err
88         }
89
90         // using commentMaps here because it sanitizes the comment text by removing
91         // comment markers, compresses newlines etc.
92         cmap := ast.NewCommentMap(fset, f, f.Comments)
93
94         for _, commentGroup := range cmap.Comments() {
95                 err = parseFn(commentGroup.Text())
96                 if err != nil {
97                         fmt.Print("error when parsing annotation")
98                         return err
99                 }
100         }
101         return nil
102 }