github.com/goplus/igop@v0.17.0/cmd/internal/export/exportpkg.go (about) 1 /* 2 * Copyright (c) 2022 The GoPlus Authors (goplus.org). All rights reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package export 18 19 import ( 20 "errors" 21 "fmt" 22 "go/format" 23 "io/ioutil" 24 "os" 25 "path/filepath" 26 "sort" 27 "strings" 28 ) 29 30 func writeFile(dir string, file string, data []byte) error { 31 err := os.MkdirAll(dir, 0777) 32 if err != nil { 33 return fmt.Errorf("make dir %v error: %v", dir, err) 34 } 35 filename := filepath.Join(dir, file) 36 err = ioutil.WriteFile(filename, data, 0777) 37 if err != nil { 38 return fmt.Errorf("write file %v error: %v", filename, err) 39 } 40 return nil 41 } 42 43 func joinList(list []string) string { 44 if len(list) == 0 { 45 return "" 46 } 47 sort.Strings(list) 48 return "\n\t" + strings.Join(list, ",\n\t") + ",\n" 49 } 50 51 const EmptyPackage = "empty package" 52 53 var ( 54 errEmptyPackage = errors.New(EmptyPackage) 55 ) 56 57 func exportPkg(pkg *Package, sname string, id string, tagList []string) ([]byte, error) { 58 imports := []string{fmt.Sprintf("%v %q\n", sname, pkg.Path)} 59 imports = append(imports, `"reflect"`) 60 if len(pkg.UntypedConsts) > 0 || len(pkg.TypedConsts) > 0 { 61 imports = append(imports, `"go/constant"`) 62 var hasToken bool 63 for _, c := range pkg.UntypedConsts { 64 if strings.Index(c, "token.") >= 0 { 65 hasToken = true 66 break 67 } 68 } 69 if hasToken { 70 imports = append(imports, `"go/token"`) 71 } 72 } 73 tmpl := template_pkg 74 if pkg.IsEmpty() { 75 tmpl = template_empty_pkg 76 imports = []string{fmt.Sprintf("_ %q", pkg.Path)} 77 } 78 if len(pkg.Source) > 0 { 79 tmpl = template_link_pkg 80 if len(pkg.Links) > 0 { 81 imports = append(imports, `_ "unsafe"`) 82 } 83 } 84 r := strings.NewReplacer("$PKGNAME", pkg.Name, 85 "$IMPORTS", strings.Join(imports, "\n"), 86 "$PKGPATH", pkg.Path, 87 "$DEPS", joinList(pkg.Deps), 88 "$NAMEDTYPES", joinList(pkg.NamedTypes), 89 "$INTERFACES", joinList(pkg.Interfaces), 90 "$ALIASTYPES", joinList(pkg.AliasTypes), 91 "$VARS", joinList(pkg.Vars), 92 "$FUNCS", joinList(pkg.Funcs), 93 "$TYPEDCONSTS", joinList(pkg.TypedConsts), 94 "$UNTYPEDCONSTS", joinList(pkg.UntypedConsts), 95 "$TAGS", strings.Join(tagList, "\n"), 96 "$SOURCE", pkg.Source, 97 "$LINKS", strings.Join(pkg.Links, "\n"), 98 "$ID", id) 99 src := r.Replace(tmpl) 100 data, err := format.Source([]byte(src)) 101 if err != nil { 102 return nil, fmt.Errorf("format pkg %v error: %v", src, err) 103 } 104 return data, nil 105 } 106 107 var template_pkg = `// export by github.com/goplus/igop/cmd/qexp 108 109 $TAGS 110 111 package $PKGNAME 112 113 import ( 114 $IMPORTS 115 116 "github.com/goplus/igop" 117 ) 118 119 func init() { 120 igop.RegisterPackage(&igop.Package { 121 Name: "$PKGNAME", 122 Path: "$PKGPATH", 123 Deps: map[string]string{$DEPS}, 124 Interfaces: map[string]reflect.Type{$INTERFACES}, 125 NamedTypes: map[string]reflect.Type{$NAMEDTYPES}, 126 AliasTypes: map[string]reflect.Type{$ALIASTYPES}, 127 Vars: map[string]reflect.Value{$VARS}, 128 Funcs: map[string]reflect.Value{$FUNCS}, 129 TypedConsts: map[string]igop.TypedConst{$TYPEDCONSTS}, 130 UntypedConsts: map[string]igop.UntypedConst{$UNTYPEDCONSTS}, 131 }) 132 } 133 ` 134 135 var template_empty_pkg = `// export by github.com/goplus/igop/cmd/qexp 136 137 $TAGS 138 139 package $PKGNAME 140 141 import ( 142 $IMPORTS 143 144 "github.com/goplus/igop" 145 ) 146 147 func init() { 148 igop.RegisterPackage(&igop.Package { 149 Name: "$PKGNAME", 150 Path: "$PKGPATH", 151 Deps: map[string]string{$DEPS}, 152 }) 153 } 154 ` 155 156 var template_link_pkg = `// export by github.com/goplus/igop/cmd/qexp 157 158 $TAGS 159 160 package $PKGNAME 161 162 import ( 163 $IMPORTS 164 165 "github.com/goplus/igop" 166 ) 167 168 func init() { 169 igop.RegisterPackage(&igop.Package { 170 Name: "$PKGNAME", 171 Path: "$PKGPATH", 172 Deps: map[string]string{$DEPS}, 173 Interfaces: map[string]reflect.Type{$INTERFACES}, 174 NamedTypes: map[string]reflect.Type{$NAMEDTYPES}, 175 AliasTypes: map[string]reflect.Type{$ALIASTYPES}, 176 Vars: map[string]reflect.Value{$VARS}, 177 Funcs: map[string]reflect.Value{$FUNCS}, 178 TypedConsts: map[string]igop.TypedConst{$TYPEDCONSTS}, 179 UntypedConsts: map[string]igop.UntypedConst{$UNTYPEDCONSTS}, 180 Source: source, 181 }) 182 } 183 $LINKS 184 var source = $SOURCE 185 `