in build/rewrite.go [150:270]
func fixLabels(f *File) {
joinLabel := func(p *Expr) {
add, ok := (*p).(*BinaryExpr)
if !ok || add.Op != "+" {
return
}
str1, ok := add.X.(*StringExpr)
if !ok || !strings.HasPrefix(str1.Value, "//") || strings.Contains(str1.Value, " ") {
return
}
str2, ok := add.Y.(*StringExpr)
if !ok || strings.Contains(str2.Value, " ") {
return
}
str1.Value += str2.Value
// Deleting nodes add and str2.
// Merge comments from add, str1, and str2 and save in str1.
com1 := add.Comment()
com2 := str1.Comment()
com3 := str2.Comment()
com1.Before = append(com1.Before, com2.Before...)
com1.Before = append(com1.Before, com3.Before...)
com1.Suffix = append(com1.Suffix, com2.Suffix...)
com1.Suffix = append(com1.Suffix, com3.Suffix...)
*str1.Comment() = *com1
*p = str1
}
labelPrefix := "//"
if tables.StripLabelLeadingSlashes {
labelPrefix = ""
}
// labelRE matches label strings, e.g. @r//x/y/z:abc
// where $1 is @r//x/y/z, $2 is @r//, $3 is r, $4 is z, $5 is abc.
labelRE := regexp.MustCompile(`^(((?:@(\w+))?//|` + labelPrefix + `)(?:.+/)?([^:]*))(?::([^:]+))?$`)
shortenLabel := func(v Expr) {
str, ok := v.(*StringExpr)
if !ok {
return
}
if tables.StripLabelLeadingSlashes && strings.HasPrefix(str.Value, "//") {
if filepath.Dir(f.Path) == "." || !strings.HasPrefix(str.Value, "//:") {
str.Value = str.Value[2:]
}
}
if tables.ShortenAbsoluteLabelsToRelative {
thisPackage := labelPrefix + filepath.Dir(f.Path)
// filepath.Dir on Windows uses backslashes as separators, while labels always have slashes.
if filepath.Separator != '/' {
thisPackage = strings.Replace(thisPackage, string(filepath.Separator), "/", -1)
}
if str.Value == thisPackage {
str.Value = ":" + path.Base(str.Value)
} else if strings.HasPrefix(str.Value, thisPackage+":") {
str.Value = str.Value[len(thisPackage):]
}
}
m := labelRE.FindStringSubmatch(str.Value)
if m == nil {
return
}
if m[4] != "" && m[4] == m[5] { // e.g. //foo:foo
str.Value = m[1]
} else if m[3] != "" && m[4] == "" && m[3] == m[5] { // e.g. @foo//:foo
str.Value = "@" + m[3]
}
}
Walk(f, func(v Expr, stk []Expr) {
switch v := v.(type) {
case *CallExpr:
if leaveAlone(stk, v) {
return
}
for i := range v.List {
if leaveAlone1(v.List[i]) {
continue
}
as, ok := v.List[i].(*AssignExpr)
if !ok {
continue
}
key, ok := as.LHS.(*Ident)
if !ok || !tables.IsLabelArg[key.Name] || tables.LabelDenylist[callName(v)+"."+key.Name] {
continue
}
if leaveAlone1(as.RHS) {
continue
}
if list, ok := as.RHS.(*ListExpr); ok {
for i := range list.List {
if leaveAlone1(list.List[i]) {
continue
}
joinLabel(&list.List[i])
shortenLabel(list.List[i])
}
}
if set, ok := as.RHS.(*SetExpr); ok {
for i := range set.List {
if leaveAlone1(set.List[i]) {
continue
}
joinLabel(&set.List[i])
shortenLabel(set.List[i])
}
} else {
joinLabel(&as.RHS)
shortenLabel(as.RHS)
}
}
}
})
}