// OverwriteStructTag overwrites the struct tag completely func OverwriteStructTag(tag *ast.BasicLit, tagName string, offset *int, data []byte) []byte { val := tag.Value start := int(tag.Pos()) + *offset - 1 end := int(tag.End()) + *offset - 1 length := len(val) oldLength := end - start // Delete the original tag data = DeleteRange(data, start, end) var newTag string if options.AppendMode == Append { oldTag := removeIndex(removeIndex(val, 0), len(val)-2) newTag = fmt.Sprintf("`%s:\"%s\" %s`", options.Tag, tagName, oldTag) } else { newTag = fmt.Sprintf("`%s:\"%s\"`", options.Tag, tagName) } numSpaces := len(newTag) - oldLength - 1 var spaces string // Can't pass a negative number to strings.Repeat() // it will cause a panic because it passes this number directly to make() if numSpaces > 0 { spaces = strings.Repeat(" ", numSpaces) } newTag = fmt.Sprintf("%s%s", spaces, newTag) localOffset := len(newTag) - length *offset += localOffset // Insert new tag data = Insert(data, []byte(newTag), start) return data }
func (check *checker) tag(t *ast.BasicLit) string { if t != nil { if t.Kind == token.STRING { if val, err := strconv.Unquote(t.Value); err == nil { return val } } check.invalidAST(t.Pos(), "incorrect tag syntax: %q", t.Value) } return "" }
// compiles a basic literal, like numbers and strings func (w *World) compileBasicLit(n *ast.BasicLit) Expr { switch n.Kind { default: panic(err(n.Pos(), "not allowed:", n.Value, "(", typ(n), ")")) case token.FLOAT: return floatLit(parseFloat(n.Value)) case token.INT: return intLit(parseInt(n.Value)) case token.STRING: return stringLit(n.Value[1 : len(n.Value)-1]) // remove quotes } }
func (file *File) basicLitToMessage(node *ast.BasicLit) Message { if node.Kind != token.STRING { panic("only call basicLitToMessage with a string node") } val, _ := strconv.Unquote(node.Value) pos := file.FSet.Position(node.Pos()) xcomment := file.cmap.Get(node, pos) return Message{ XComment: xcomment, Reference: []token.Position{pos}, Flags: []string{}, MsgCtxt: nil, MsgID: val, MsgIDPlural: nil, } }
// Visit browses the AST tree for strings that could be potentially // replaced by constants. // A map of existing constants is built as well (-match-constant). func (v *treeVisitor) Visit(node ast.Node) ast.Visitor { if node == nil { return v } // A single case with "ast.BasicLit" would be much easier // but then we wouldn't be able to tell in which context // the string is defined (could be a constant definition). switch t := node.(type) { // Scan for constants in an attempt to match strings with existing constants case *ast.GenDecl: if !v.p.matchConstant { return v } if t.Tok != token.CONST { return v } for _, spec := range t.Specs { val := spec.(*ast.ValueSpec) for i, str := range val.Values { lit, ok := str.(*ast.BasicLit) if !ok || !v.isSupported(lit.Kind) { continue } v.addConst(val.Names[i].Name, lit.Value, val.Names[i].Pos()) } } // foo := "moo" case *ast.AssignStmt: for _, rhs := range t.Rhs { lit, ok := rhs.(*ast.BasicLit) if !ok || !v.isSupported(lit.Kind) { continue } v.addString(lit.Value, rhs.(*ast.BasicLit).Pos()) } // if foo == "moo" case *ast.BinaryExpr: if t.Op != token.EQL && t.Op != token.NEQ { return v } var lit *ast.BasicLit var ok bool lit, ok = t.X.(*ast.BasicLit) if ok && v.isSupported(lit.Kind) { v.addString(lit.Value, lit.Pos()) } lit, ok = t.Y.(*ast.BasicLit) if ok && v.isSupported(lit.Kind) { v.addString(lit.Value, lit.Pos()) } // case "foo": case *ast.CaseClause: for _, item := range t.List { lit, ok := item.(*ast.BasicLit) if ok && v.isSupported(lit.Kind) { v.addString(lit.Value, lit.Pos()) } } // return "boo" case *ast.ReturnStmt: for _, item := range t.Results { lit, ok := item.(*ast.BasicLit) if ok && v.isSupported(lit.Kind) { v.addString(lit.Value, lit.Pos()) } } } return v }