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  }