github.com/stackb/rules_proto@v0.0.0-20240221195024-5428336c51f1/pkg/protoc/rewrite.go (about) 1 package protoc 2 3 import ( 4 "fmt" 5 // "log" 6 "regexp" 7 "strings" 8 ) 9 10 // Rewrite is a replacement specification 11 type Rewrite struct { 12 Match *regexp.Regexp 13 Replace string 14 } 15 16 func (r *Rewrite) ReplaceAll(src string) string { 17 if r.Match == nil { 18 return "" 19 } 20 replaced := r.Match.ReplaceAllString(src, r.Replace) 21 if src == replaced { 22 return "" 23 } 24 return replaced 25 } 26 27 func ParseRewrite(spec string) (*Rewrite, error) { 28 parts := strings.Fields(spec) 29 if len(parts) != 2 { 30 return nil, fmt.Errorf("rewrite specification should be two space-separated fields [REGEXP REPLACEMENT], got %d: %v", len(parts), parts) 31 } 32 match, err := regexp.Compile(parts[0]) 33 if err != nil { 34 return nil, err 35 } 36 return &Rewrite{match, parts[1]}, nil 37 } 38 39 // ResolveRewrites takes a list of rewrite rules and returns the first match of 40 // the given input string. 41 func ResolveRewrites(rewrites []Rewrite, in string) string { 42 if len(rewrites) == 0 { 43 return "" 44 } 45 for _, rw := range rewrites { 46 if match := rw.ReplaceAll(in); match != "" { 47 // log.Printf("SUCCESS match rewrite %q for %v", in, rw) 48 return match 49 } 50 // log.Printf("failed to match rewrite %q for %v", in, rw) 51 } 52 return "" 53 } 54 55 // ResolveFileRewrites takes a proto File object and returns a list of matching 56 // rewrites of the import statements. The list if neither sorted or 57 // deduplicated. 58 func ResolveFileRewrites(rewrites []Rewrite, file *File) []string { 59 if len(rewrites) == 0 { 60 return nil 61 } 62 resolved := make([]string, 0) 63 for _, i := range file.Imports() { 64 if m := ResolveRewrites(rewrites, i.Filename); m != "" { 65 resolved = append(resolved, m) 66 } 67 } 68 return resolved 69 } 70 71 // ResolveLibraryRewrites takes a proto_library object and returns a list 72 // of matching rewrites of all the the transitive import statements. 73 func ResolveLibraryRewrites(rewrites []Rewrite, library ProtoLibrary) []string { 74 if len(rewrites) == 0 { 75 return nil 76 } 77 resolved := make([]string, 0) 78 for _, file := range library.Files() { 79 resolved = append(resolved, ResolveFileRewrites(rewrites, file)...) 80 } 81 return DeduplicateAndSort(resolved) 82 }