github.com/GeniusesGroup/libgo@v0.0.0-20220929090155-5ff932cb408e/go/parser/package.go (about) 1 /* For license and copyright information please see the LEGAL file in the code repository */ 2 3 package parser 4 5 import ( 6 "go/ast" 7 "go/parser" 8 "go/token" 9 "path" 10 "strings" 11 ) 12 13 // Package : 14 type Package struct { 15 Name string 16 DependencyID [16]byte // 17 FSPath string // Folder location in FileSystems 18 Files map[string]*File // Name 19 Imports map[string]*Import // UsageName 20 Functions map[string]*Function // Name 21 Types map[string]*Type // Name 22 Dependencies map[string]*Package // Name 23 } 24 25 // Init initialize the object. 26 func (p *Package) Init() { 27 p.Files = make(map[string]*File) 28 p.Imports = make(map[string]*Import) 29 p.Functions = make(map[string]*Function) 30 p.Types = make(map[string]*Type) 31 p.Dependencies = make(map[string]*Package) 32 } 33 34 // AddFile use to add file to Package 35 func (p *Package) AddFile(f *File) { 36 p.Files[f.Name] = f 37 } 38 39 // Parse use to add new file & parsed FileData and add to repo object! 40 func (p *Package) Parse(FileName string, FileData []byte) (err error) { 41 // Parsed FileData 42 var ( 43 file = File{Name: FileName, Data: FileData} 44 fileSet = token.NewFileSet() 45 ) 46 p.Files[FileName] = &file 47 48 // Just parsed needed file! 49 if strings.HasSuffix(FileName, ".go") || 50 !strings.HasSuffix(FileName, "_test.go") { 51 52 file.Parsed, err = parser.ParseFile(fileSet, "", FileData, parser.ParseComments) 53 if err != nil { 54 return 55 } 56 57 // Set package name 58 p.Name = file.Parsed.Name.Name 59 60 err = p.parseFile(&file) 61 if err != nil { 62 return 63 } 64 } 65 66 return nil 67 } 68 69 func (p *Package) parseFile(file *File) (err error) { 70 for _, imp := range file.Parsed.Imports { 71 var impor = Import{ 72 FSPath: imp.Path.Value[1 : len(imp.Path.Value)-1], 73 ImportSpec: imp, 74 } 75 if imp.Name != nil { 76 impor.UsageName = imp.Name.Name 77 impor.PackageName = path.Base(imp.Path.Value[1 : len(imp.Path.Value)-1]) 78 } else { 79 impor.UsageName = path.Base(imp.Path.Value[1 : len(imp.Path.Value)-1]) 80 impor.PackageName = path.Base(imp.Path.Value[1 : len(imp.Path.Value)-1]) 81 } 82 83 p.Imports[impor.UsageName] = &impor 84 } 85 86 for _, decl := range file.Parsed.Decls { 87 switch d := decl.(type) { 88 case *ast.GenDecl: 89 for _, gDecl := range d.Specs { 90 switch gd := gDecl.(type) { 91 case *ast.ImportSpec: 92 // Check this before in file.Parsed.Imports!!!! WHY go WHY!!!? duplicate data!!!??? 93 case *ast.ValueSpec: 94 // Don't need this so far! 95 case *ast.TypeSpec: 96 t := p.parseType(gd.Type) 97 t.Name = gd.Name.Name 98 t.Exported = gd.Name.IsExported() 99 t.File = file 100 101 p.Types[t.Name] = &t 102 } 103 } 104 105 case *ast.FuncDecl: 106 // Just exported function use in chaparkhane generation! 107 if !d.Name.IsExported() { 108 continue 109 } 110 111 function := Function{ 112 Name: d.Name.Name, 113 File: file, 114 Decl: d, 115 } 116 117 if d.Type != nil && d.Type.Params != nil { 118 if len(d.Type.Params.List) != 2 { 119 continue 120 } 121 fp := p.parseType(d.Type.Params.List[0].Type) 122 fp.Name = d.Type.Params.List[0].Names[0].Name 123 fp.Exported = d.Type.Params.List[0].Names[0].IsExported() 124 fp.File = file 125 function.Parameter = &fp 126 } 127 128 if d.Type != nil && d.Type.Results != nil { 129 if len(d.Type.Params.List) > 2 { 130 continue 131 } 132 133 for _, rField := range d.Type.Results.List { 134 for _, name := range rField.Names { 135 fr := p.parseType(rField.Type) 136 fr.Name = name.Name 137 fr.Exported = name.IsExported() 138 fr.File = file 139 if fr.Type == "error" { 140 function.Err = &fr 141 } else { 142 function.Result = &fr 143 } 144 } 145 } 146 } 147 148 p.Functions[function.Name] = &function 149 } 150 } 151 152 return nil 153 } 154 155 func (p *Package) parseType(expr ast.Expr) (ft Type) { 156 switch v := expr.(type) { 157 case *ast.StarExpr: 158 ft = p.parseType(v.X) 159 ft.Pointer = true 160 case *ast.SelectorExpr: 161 if imp, ok := p.Imports[v.X.(*ast.Ident).Name]; ok { 162 ft.Package = imp 163 } 164 ft.Type = v.Sel.Name 165 case *ast.ArrayType: 166 //ft.Type = "[" + repo.parseType(v.Len).Type + "]" + repo.parseType(v.Elt).Type 167 case *ast.MapType: 168 //"map[" + parseType(v.Key) + "]" + parseType(v.Value) 169 case *ast.InterfaceType: 170 //"interface{}" 171 // interface type forbidden 172 case *ast.Ident: 173 if v.Obj != nil { 174 switch obj := v.Obj.Decl.(type) { 175 case *ast.TypeSpec: 176 innerFT := p.parseType(obj.Type) 177 for _, each := range innerFT.InnerType { 178 ft.InnerType = append(ft.InnerType, each) 179 } 180 } 181 } 182 ft.Type = v.Name 183 case *ast.StructType: 184 for _, field := range v.Fields.List { 185 if field.Names == nil { 186 // embedded struct forbidden 187 } 188 for _, innerField := range field.Names { 189 innerFT := p.parseType(field.Type) 190 innerFT.Name = innerField.Name 191 innerFT.ID = len(ft.InnerType) 192 ft.InnerType = append(ft.InnerType, &innerFT) 193 } 194 } 195 case *ast.BasicLit: 196 // embedded basic type forbidden 197 // type test struct { 198 // string 199 // } 200 } 201 202 return ft 203 }