func packageFromInfo(prog *loader.Program, pkgInfo *loader.PackageInfo) *Package { files := map[string]*ast.File{} for _, f := range pkgInfo.Files { files[prog.Fset.File(f.Pos()).Name()] = f } // Ignore (perhaps) "unresolved identifier" errors astPkg, _ := ast.NewPackage(prog.Fset, files, nil, nil) var mode doc.Mode docPkg := doc.New(astPkg, pkgInfo.String(), mode) return NewPackage(prog.Fset, docPkg, pkgInfo.Pkg) }
func findSourceFile(pkg *loader.PackageInfo, typeName string) (*ast.File, *ast.GenDecl, *ast.TypeSpec, error) { for _, file := range pkg.Files { for _, decl := range file.Decls { if gd, ok := decl.(*ast.GenDecl); ok { for _, gs := range gd.Specs { if ts, ok := gs.(*ast.TypeSpec); ok { strfmtNme, isStrfmt := strfmtName(gd.Doc) if (isStrfmt && strfmtNme == typeName) || ts.Name != nil && ts.Name.Name == typeName { return file, gd, ts, nil } } } } } } return nil, nil, nil, fmt.Errorf("unable to find %s in %s", typeName, pkg.String()) }
func (scp *schemaParser) parseIdentProperty(pkg *loader.PackageInfo, expr *ast.Ident, prop swaggerTypable) error { // find the file this selector points to file, gd, ts, err := findSourceFile(pkg, expr.Name) if err != nil { err := swaggerSchemaForType(expr.Name, prop) if err != nil { return fmt.Errorf("package %s, error is: %v", pkg.String(), err) } return nil } if at, ok := ts.Type.(*ast.ArrayType); ok { // the swagger spec defines strfmt base64 as []byte. // in that case we don't actually want to turn it into an array // but we want to turn it into a string if _, ok := at.Elt.(*ast.Ident); ok { if strfmtName, ok := strfmtName(gd.Doc); ok { prop.Typed("string", strfmtName) return nil } } // this is a selector, so most likely not base64 if strfmtName, ok := strfmtName(gd.Doc); ok { prop.Items().Typed("string", strfmtName) return nil } } // look at doc comments for swagger:strfmt [name] // when found this is the format name, create a schema with that name if strfmtName, ok := strfmtName(gd.Doc); ok { prop.Typed("string", strfmtName) return nil } switch tpe := ts.Type.(type) { case *ast.ArrayType: switch atpe := tpe.Elt.(type) { case *ast.Ident: return scp.parseIdentProperty(pkg, atpe, prop.Items()) case *ast.SelectorExpr: return scp.typeForSelector(file, atpe, prop.Items()) case *ast.StarExpr: return parseProperty(scp, file, atpe.X, prop.Items()) default: return fmt.Errorf("unknown selector type: %#v", atpe) } case *ast.StructType: sd := newSchemaDecl(file, gd, ts) sd.inferNames() ref, err := spec.NewRef("#/definitions/" + sd.Name) if err != nil { return err } prop.SetRef(ref) scp.postDecls = append(scp.postDecls, *sd) return nil case *ast.Ident: return scp.parseIdentProperty(pkg, tpe, prop) case *ast.SelectorExpr: return scp.typeForSelector(file, tpe, prop) case *ast.InterfaceType: sd := newSchemaDecl(file, gd, ts) sd.inferNames() ref, err := spec.NewRef("#/definitions/" + sd.Name) if err != nil { return err } prop.SetRef(ref) scp.postDecls = append(scp.postDecls, *sd) return nil default: err := swaggerSchemaForType(expr.Name, prop) if err != nil { return fmt.Errorf("package %s, error is: %v", pkg.String(), err) } return nil } }