第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問(wèn)題,去搜搜看,總會(huì)有你想問(wèn)的

將項(xiàng)目添加到 Go AST 后評(píng)論亂序

將項(xiàng)目添加到 Go AST 后評(píng)論亂序

Go
慕妹3242003 2021-10-25 16:53:36
以下測(cè)試嘗試使用 AST 向結(jié)構(gòu)添加字段。字段添加正確,但注釋添加順序不正確。我認(rèn)為可能需要手動(dòng)指定位置,但到目前為止我已經(jīng)找到了答案。這是一個(gè)失敗的測(cè)試:http : //play.golang.org/p/RID4N30FZK這是代碼:package generatorimport (    "bytes"    "fmt"    "go/ast"    "go/parser"    "go/printer"    "go/token"    "testing")func TestAst(t *testing.T) {    source := `package a// B commenttype B struct {    // C comment    C string}`    fset := token.NewFileSet()    file, err := parser.ParseFile(fset, "", []byte(source), parser.ParseComments)    if err != nil {        t.Error(err)    }    v := &visitor{        file: file,    }    ast.Walk(v, file)    var output []byte    buf := bytes.NewBuffer(output)    if err := printer.Fprint(buf, fset, file); err != nil {        t.Error(err)    }    expected := `package a// B commenttype B struct {    // C comment    C string    // D comment    D int    // E comment    E float64}`    if buf.String() != expected {        t.Error(fmt.Sprintf("Test failed. Expected:\n%s\nGot:\n%s", expected, buf.String()))    }    /*    actual output = `package a// B commenttype B struct {    // C comment    // D comment    // E comment    C   string    D   int    E   float64}`    */}type visitor struct {    file *ast.File}func (v *visitor) Visit(node ast.Node) (w ast.Visitor) {    if node == nil {        return v    }    switch n := node.(type) {    case *ast.GenDecl:        if n.Tok != token.TYPE {            break        }        ts := n.Specs[0].(*ast.TypeSpec)        if ts.Name.Name == "B" {            fields := ts.Type.(*ast.StructType).Fields            addStructField(fields, v.file, "int", "D", "D comment")            addStructField(fields, v.file, "float64", "E", "E comment")        }    }    return v}
查看完整描述

2 回答

?
明月笑刀無(wú)情

TA貢獻(xiàn)1828條經(jīng)驗(yàn) 獲得超4個(gè)贊

我相信我已經(jīng)讓它發(fā)揮作用了。正如我在上面的評(píng)論中所述,所需的要點(diǎn)是:

  1. 具體設(shè)置緩沖區(qū)位置包括SlashNamePos

  2. 用于token.File.AddLine在特定偏移處添加新行(使用第 1 項(xiàng)中的位置計(jì)算)

  3. 過(guò)度分配源緩沖區(qū)token.File.Position(由源緩沖區(qū)使用,printer.Printer并且token.File.Addline不會(huì)使源緩沖區(qū)的范圍檢查失敗

代碼:

package main


import (

    "bytes"

    "fmt"

    "go/ast"

    "go/parser"

    "go/printer"

    "go/token"

    "testing"

)


func main() {

    tests := []testing.InternalTest{{"TestAst", TestAst}}

    matchAll := func(t string, pat string) (bool, error) { return true, nil }

    testing.Main(matchAll, tests, nil, nil)

}


func TestAst(t *testing.T) {


    source := `package a


// B comment

type B struct {

    // C comment

    C string

}`


    buffer := make([]byte, 1024, 1024)

    for idx,_ := range buffer {

        buffer[idx] = 0x20

    }

    copy(buffer[:], source)

    fset := token.NewFileSet()

    file, err := parser.ParseFile(fset, "", buffer, parser.ParseComments)

    if err != nil {

        t.Error(err)

    }


    v := &visitor{

        file: file,

        fset: fset,

    }

    ast.Walk(v, file)


    var output []byte

    buf := bytes.NewBuffer(output)

    if err := printer.Fprint(buf, fset, file); err != nil {

        t.Error(err)

    }


    expected := `package a


// B comment

type B struct {

    // C comment

    C   string

    // D comment

    D   int

    // E comment

    E   float64

}

`

    if buf.String() != expected {

        t.Error(fmt.Sprintf("Test failed. Expected:\n%s\nGot:\n%s", expected, buf.String()))

    }


}


type visitor struct {

    file *ast.File

    fset *token.FileSet

}


func (v *visitor) Visit(node ast.Node) (w ast.Visitor) {


    if node == nil {

        return v

    }


    switch n := node.(type) {

    case *ast.GenDecl:

        if n.Tok != token.TYPE {

            break

        }

        ts := n.Specs[0].(*ast.TypeSpec)

        if ts.Name.Name == "B" {

            fields := ts.Type.(*ast.StructType).Fields

            addStructField(v.fset, fields, v.file, "int", "D", "D comment")

            addStructField(v.fset, fields, v.file, "float64", "E", "E comment")

        }

    }


    return v

}


func addStructField(fset *token.FileSet, fields *ast.FieldList, file *ast.File, typ string, name string, comment string) {

    prevField := fields.List[fields.NumFields()-1] 


    c := &ast.Comment{Text: fmt.Sprint("// ", comment), Slash: prevField.End() + 1}

    cg := &ast.CommentGroup{List: []*ast.Comment{c}}

    o := ast.NewObj(ast.Var, name)

    f := &ast.Field{

        Doc:   cg,

        Names: []*ast.Ident{&ast.Ident{Name: name, Obj: o, NamePos: cg.End() + 1}},

    }

    o.Decl = f

    f.Type = &ast.Ident{Name: typ, NamePos: f.Names[0].End() + 1}


    fset.File(c.End()).AddLine(int(c.End()))

    fset.File(f.End()).AddLine(int(f.End()))


    fields.List = append(fields.List, f)

    file.Comments = append(file.Comments, cg)

}

示例:http : //play.golang.org/p/_q1xh3giHm


對(duì)于Item (3),將所有過(guò)度分配的字節(jié)設(shè)置為空格 ( 0x20)也很重要,以便打印機(jī)在處理它們時(shí)不會(huì)抱怨空字節(jié)。


查看完整回答
反對(duì) 回復(fù) 2021-10-25
  • 2 回答
  • 0 關(guān)注
  • 182 瀏覽
慕課專(zhuān)欄
更多

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購(gòu)課補(bǔ)貼
聯(lián)系客服咨詢(xún)優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)