func (gofile *File) readStruct(r *kmgGoReader.Reader) StructType { // 仅跳过 r.ReadAllSpace() b := r.ReadByte() if b != '{' { panic(fmt.Errorf("%s unexcept %s", r.GetFileLineInfo(), string(rune(b)))) } lastReadBuf := []bytesAndType{} var lastTag []byte out := StructType{} for { r.ReadAllSpaceWithoutLineBreak() b := r.ReadByte() if b == '}' { return out } else if b == '"' || b == '\'' || b == '`' { r.UnreadByte() lastTag = MustReadGoString(r) } else if b == ',' { continue } else if b == '\n' { if len(lastReadBuf) == 0 { continue } else if len(lastReadBuf) == 1 { typ := lastReadBuf[0].typ name := getTypeStructAnonymousName(typ) out.Field = append(out.Field, StructField{ Name: name, Elem: typ, IsAnonymousField: true, Tag: string(lastTag), }) lastReadBuf = []bytesAndType{} } else if len(lastReadBuf) >= 2 { typ := lastReadBuf[len(lastReadBuf)-1].typ for i := range lastReadBuf[:len(lastReadBuf)-1] { out.Field = append(out.Field, StructField{ Name: string(lastReadBuf[i].originByte), Elem: typ, IsAnonymousField: false, Tag: string(lastTag), }) } lastReadBuf = []bytesAndType{} } } else { r.UnreadByte() startPos := r.Pos() typ := gofile.readType(r) lastReadBuf = append(lastReadBuf, bytesAndType{ originByte: r.BufToCurrent(startPos), typ: typ, }) } } }
// 此处暂时仅跳过该部分 func (gofile *File) readGoType(r *kmgGoReader.Reader) { r.MustReadMatch([]byte("type")) r.ReadAllSpace() b := r.ReadByte() if b == '(' { for { r.ReadAllSpace() b = r.ReadByte() if b == ')' { return } r.UnreadByte() name := readIdentifier(r) r.ReadAllSpace() typ := gofile.readType(r) gofile.NamedTypeList = append(gofile.NamedTypeList, &NamedType{ PackagePath: gofile.PackagePath, Name: string(name), underType: typ, }) } return } else { r.UnreadByte() name := readIdentifier(r) r.ReadAllSpace() typ := gofile.readType(r) gofile.NamedTypeList = append(gofile.NamedTypeList, &NamedType{ PackagePath: gofile.PackagePath, Name: string(name), underType: typ, }) return } }
// 正确跳过该部分. func (gofile *File) readGoConst(r *kmgGoReader.Reader) { r.MustReadMatch([]byte("const")) r.ReadAllSpace() b := r.ReadByte() if b == '(' { readMatchSmallParantheses(r) return } for { if b == '"' || b == '`' { r.UnreadByte() MustReadGoString(r) } if b == '\'' { r.UnreadByte() mustReadGoChar(r) } if b == '\n' { return } b = r.ReadByte() } }
// 读取一个import语法里面的数据,此处从import关键词开始 func (gofile *File) readImport(r *kmgGoReader.Reader) { r.MustReadMatch([]byte("import")) r.ReadAllSpace() if r.IsEof() { panic(r.GetFileLineInfo() + " unexcept EOF ") } b := r.ReadByte() if b == '(' { for { r.ReadAllSpace() b := r.ReadByte() if b == ')' { return } else { r.UnreadByte() gofile.readImportSpec(r) } } } else { r.UnreadByte() gofile.readImportSpec(r) } }
// 正确跳过该部分. func (gofile *File) readGoVar(r *kmgGoReader.Reader) { r.MustReadMatch([]byte("var")) r.ReadAllSpace() b := r.ReadByte() if b == '(' { readMatchSmallParantheses(r) return } r.UnreadByte() readIdentifier(r) r.ReadAllSpace() b = r.ReadByte() if b == '=' { r.ReadAllSpace() } for { if b == '"' || b == '`' { r.UnreadByte() MustReadGoString(r) } if b == '\'' { r.UnreadByte() mustReadGoChar(r) } if b == '\n' { return } if b == '{' { //里面可以字面写东西. readMatchBigParantheses(r) //TODO 正确跳过该部分 /* 简单解决下列情况 var UnreadRuneErrorTests = []struct { name string f func(*Reader) }{ {"Read", func(r *Reader) { r.Read([]byte{0}) }}, {"ReadByte", func(r *Reader) { r.ReadByte() }}, {"UnreadRune", func(r *Reader) { r.UnreadRune() }}, {"Seek", func(r *Reader) { r.Seek(0, 1) }}, {"WriteTo", func(r *Reader) { r.WriteTo(&Buffer{}) }}, } */ } if b == '(' { //里面可以调用函数 readMatchSmallParantheses(r) } if r.IsEof() { return } b = r.ReadByte() } }
// 此处仅跳过函数 func (gofile *File) readGoFunc(r *kmgGoReader.Reader) *FuncOrMethodDeclaration { funcDecl := &FuncOrMethodDeclaration{} r.MustReadMatch([]byte("func")) // 读函数头,至少要有括号 r.ReadAllSpace() b := r.ReadByte() if b == '(' { r.UnreadByte() receiver := gofile.readParameters(r) if len(receiver) != 1 { panic(fmt.Errorf("%s receiver must have one parameter", r.GetFileLineInfo())) } funcDecl.ReceiverType = receiver[0].Type r.ReadAllSpace() // 暂不处理方法 } else { r.UnreadByte() } id := readIdentifier(r) funcDecl.Name = string(id) if funcDecl.Name == "" { panic(fmt.Errorf("%s need function name", r.GetFileLineInfo())) } r.ReadAllSpace() b = r.ReadByte() if b != '(' { panic(fmt.Errorf("%s unexcept %s", r.GetFileLineInfo(), string(rune(b)))) } r.UnreadByte() funcDecl.InParameter = gofile.readParameters(r) r.ReadAllSpaceWithoutLineBreak() b = r.ReadByte() if b == '\n' { //没有body return funcDecl } else if b != '{' { r.UnreadByte() funcDecl.OutParameter = gofile.readParameters(r) r.ReadAllSpaceWithoutLineBreak() b = r.ReadByte() } if b == '\n' { //没有body return funcDecl } if b != '{' { panic(fmt.Errorf("%s unexcept %s", r.GetFileLineInfo(), string(rune(b)))) } //跳过函数体 readMatchBigParantheses(r) return funcDecl }
// 此处暂时只保留路径,其他数据抛弃. func (gofile *File) readImportSpec(r *kmgGoReader.Reader) { r.ReadAllSpace() b := r.ReadByte() //fmt.Println(b,string(rune(b))) if b == '"' || b == '`' { r.UnreadByte() gofile.AddImport(string(MustReadGoString(r)), "") } else if b == '.' { r.ReadAllSpace() gofile.AddImport(string(MustReadGoString(r)), ".") } else { r.UnreadByte() alias := readIdentifier(r) r.ReadAllSpace() gofile.AddImport(string(MustReadGoString(r)), string(alias)) } }
func (gofile *File) readParameters(r *kmgGoReader.Reader) (output []FuncParameter) { b := r.ReadByte() if b != '(' { // 处理 int 这种类型 r.UnreadByte() return []FuncParameter{ { Type: gofile.readType(r), }, } } parameterPartList := []*astParameterPart{} lastPart := &astParameterPart{} for { r.ReadAllSpace() b := r.ReadByte() if b == ')' || b == ',' { if lastPart.partList[0].originByte != nil { parameterPartList = append(parameterPartList, lastPart) lastPart = &astParameterPart{} } if b == ')' { break } if b == ',' { continue } } r.UnreadByte() if r.IsMatchAfter([]byte("...")) { r.MustReadMatch([]byte("...")) lastPart.isVariadic = true } startPos := r.Pos() typ := gofile.readType(r) buf := r.BufToCurrent(startPos) //fmt.Println(string(buf)) hasSet := false for i := range lastPart.partList { if lastPart.partList[i].originByte == nil { lastPart.partList[i].originByte = buf lastPart.partList[i].typ = typ hasSet = true break } } if !hasSet { panic(r.GetFileLineInfo() + " unexcept func parameterList.") } } output = make([]FuncParameter, len(parameterPartList)) onlyHavePart1Num := 0 for i := range parameterPartList { if parameterPartList[i].partList[1].originByte == nil { onlyHavePart1Num++ } } //重新分析出函数参数来. 处理(int,int) 这种类型. if onlyHavePart1Num == len(parameterPartList) { for i := range parameterPartList { output[i].Type = parameterPartList[i].partList[0].typ output[i].IsVariadic = parameterPartList[i].isVariadic } return output } // 处理 (x,y int) (x int,y int) 这种类型. for i, parameterPart := range parameterPartList { output[i].Name = string(parameterPart.partList[0].originByte) if parameterPart.partList[1].typ != nil { output[i].Type = parameterPart.partList[1].typ } output[i].IsVariadic = parameterPart.isVariadic } // 补全 (x,y int) 里面 x的类型. for i := range parameterPartList { if output[i].Type == nil { for j := i + 1; j < len(parameterPartList); j++ { if output[j].Type != nil { output[i].Type = output[j].Type } } } } return output }
/* 第一个字符可能为 letter -> identifier(单独的类型名,带package的类型的package部分) "struct" struct类型开头 "func" func类型开头 "interface" interface类型开头 "*" 指针开头 "[" (数组,slice) 开头 "map[" map开头 "chan " chan开头 "chan<- " chan<- 开头 "<-chan" chan<- 开头 */ func (gofile *File) readType(r *kmgGoReader.Reader) Type { id := readIdentifier(r) if len(id) == 0 { if r.IsMatchAfter([]byte("<-chan")) { r.MustReadMatch([]byte("<-chan")) r.ReadAllSpace() return ChanType{ Dir: RecvDir, Elem: gofile.readType(r), } } b := r.ReadByte() if b == '*' { return PointerType{ Elem: gofile.readType(r), } } else if b == '[' { content := readMatchMiddleParantheses(r) if len(content) == 1 { return SliceType{ Elem: gofile.readType(r), } } else { // 仅跳过 return ArrayType{ Elem: gofile.readType(r), } } } else if b == '(' { typ := gofile.readType(r) r.MustReadMatch([]byte(")")) return typ } else { panic(fmt.Errorf("%s unexcept %s", r.GetFileLineInfo(), string(rune(b)))) } } if bytes.Equal(id, []byte("struct")) { return gofile.readStruct(r) } else if bytes.Equal(id, []byte("interface")) { // 仅跳过 r.ReadAllSpace() b := r.ReadByte() if b != '{' { panic(fmt.Errorf("%s unexcept %s", r.GetFileLineInfo(), string(rune(b)))) } readMatchBigParantheses(r) return InterfaceType{} } else if bytes.Equal(id, []byte("map")) { b := r.ReadByte() m := MapType{} if b != '[' { panic(fmt.Errorf("%s unexcept %s", r.GetFileLineInfo(), string(rune(b)))) } m.Key = gofile.readType(r) r.MustReadMatch([]byte("]")) m.Value = gofile.readType(r) return m } else if bytes.Equal(id, []byte("func")) { // 仅跳过 r.ReadAllSpace() b := r.ReadByte() if b != '(' { panic(fmt.Errorf("%s unexcept %s", r.GetFileLineInfo(), string(rune(b)))) } readMatchSmallParantheses(r) //跳过输入参数 r.ReadAllSpaceWithoutLineBreak() run := r.ReadRune() //跳过输出参数 if run == '(' { readMatchSmallParantheses(r) } else if run == '\n' { //换行符可以标识这个函数定义结束了. return FuncType{} } else if unicode.IsLetter(run) || run == '[' || run == '*' || run == '<' { r.UnreadRune() //输出参数只有一个类型 gofile.readType(r) } else { r.UnreadRune() //读到了其他东西,退回. } return FuncType{} } else if bytes.Equal(id, []byte("chan")) { if r.IsMatchAfter([]byte("<-")) { r.MustReadMatch([]byte("<-")) r.ReadAllSpace() return ChanType{ Dir: SendDir, Elem: gofile.readType(r), } } else { r.ReadAllSpace() return ChanType{ Dir: BothDir, Elem: gofile.readType(r), } } } else { b := r.ReadByte() if b == '.' { pkgPath := string(id) pkgPath, err := gofile.LookupFullPackagePath(pkgPath) if err != nil { fmt.Println(r.GetFileLineInfo(), err.Error()) //TODO 以目前的复杂度暂时无解.需要把所有相关的package都看一遍才能正确. } id2 := readIdentifier(r) return &NamedType{ PackagePath: pkgPath, Name: string(id2), Pkg: gofile.Pkg, } } else { r.UnreadByte() name := string(id) if builtinTypeMap[BuiltinType(name)] != Invalid { return BuiltinType(name) } else { return &NamedType{ PackagePath: gofile.PackagePath, Name: string(id), Pkg: gofile.Pkg, } } } } /* }else if r.IsMatchAfter([]byte("struct")) { //TODO 解决struct后面必须有一个空格的问题. r.ReadAllSpace() b := r.ReadByte() if b!='{' { panic(fmt.Errorf("%s unexcept %s", r.GetFileLineInfo(), string(rune(b)))) } readMatchBigParantheses(r) return StructType{} }else if r.IsMatchAfter([]byte("interface")) { r.ReadAllSpace() b := r.ReadByte() if b!='{' { panic(fmt.Errorf("%s unexcept %s", r.GetFileLineInfo(), string(rune(b)))) } readMatchBigParantheses(r) return InterfaceType{} }else if r.IsMatchAfter([]byte("map[")){ }else if r.IsMatchAfter([]byte("func")){ //TODO finish it. } */ }