github.com/goplus/igop@v0.25.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 var imports []string 59 if pkg.usedPkg { 60 imports = append(imports, fmt.Sprintf("q %q", pkg.Path)) 61 imports = append(imports, "") 62 } else { 63 imports = append(imports, fmt.Sprintf("_ %q", pkg.Path)) 64 } 65 if !pkg.IsEmpty() { 66 imports = append(imports, `"reflect"`) 67 } 68 if len(pkg.UntypedConsts) > 0 || len(pkg.TypedConsts) > 0 { 69 imports = append(imports, `"go/constant"`) 70 var hasToken bool 71 for _, c := range pkg.UntypedConsts { 72 if strings.Index(c, "token.") >= 0 { 73 hasToken = true 74 break 75 } 76 } 77 if hasToken { 78 imports = append(imports, `"go/token"`) 79 } 80 } 81 tmpl := template_pkg 82 if pkg.IsEmpty() { 83 tmpl = template_empty_pkg 84 } 85 if len(pkg.Source) > 0 { 86 tmpl = template_link_pkg 87 if pkg.IsEmpty() { 88 tmpl = template_emtpy_link_pkg 89 } 90 if len(pkg.Links) > 0 { 91 imports = append(imports, `_ "unsafe"`) 92 } 93 } 94 r := strings.NewReplacer("$PKGNAME", pkg.Name, 95 "$IMPORTS", strings.Join(imports, "\n"), 96 "$PKGPATH", pkg.Path, 97 "$DEPS", joinList(pkg.Deps), 98 "$NAMEDTYPES", joinList(pkg.NamedTypes), 99 "$INTERFACES", joinList(pkg.Interfaces), 100 "$ALIASTYPES", joinList(pkg.AliasTypes), 101 "$VARS", joinList(pkg.Vars), 102 "$FUNCS", joinList(pkg.Funcs), 103 "$TYPEDCONSTS", joinList(pkg.TypedConsts), 104 "$UNTYPEDCONSTS", joinList(pkg.UntypedConsts), 105 "$TAGS", strings.Join(tagList, "\n"), 106 "$SOURCE", pkg.Source, 107 "$LINKS", strings.Join(pkg.Links, "\n"), 108 "$ID", id) 109 src := r.Replace(tmpl) 110 data, err := format.Source([]byte(src)) 111 if err != nil { 112 return nil, fmt.Errorf("format pkg %v error: %v", src, err) 113 } 114 return data, nil 115 } 116 117 var template_pkg = `// export by github.com/goplus/igop/cmd/qexp 118 119 $TAGS 120 121 package $PKGNAME 122 123 import ( 124 $IMPORTS 125 126 "github.com/goplus/igop" 127 ) 128 129 func init() { 130 igop.RegisterPackage(&igop.Package { 131 Name: "$PKGNAME", 132 Path: "$PKGPATH", 133 Deps: map[string]string{$DEPS}, 134 Interfaces: map[string]reflect.Type{$INTERFACES}, 135 NamedTypes: map[string]reflect.Type{$NAMEDTYPES}, 136 AliasTypes: map[string]reflect.Type{$ALIASTYPES}, 137 Vars: map[string]reflect.Value{$VARS}, 138 Funcs: map[string]reflect.Value{$FUNCS}, 139 TypedConsts: map[string]igop.TypedConst{$TYPEDCONSTS}, 140 UntypedConsts: map[string]igop.UntypedConst{$UNTYPEDCONSTS}, 141 }) 142 } 143 ` 144 145 var template_empty_pkg = `// export by github.com/goplus/igop/cmd/qexp 146 147 $TAGS 148 149 package $PKGNAME 150 151 import ( 152 $IMPORTS 153 154 "github.com/goplus/igop" 155 ) 156 157 func init() { 158 igop.RegisterPackage(&igop.Package { 159 Name: "$PKGNAME", 160 Path: "$PKGPATH", 161 Deps: map[string]string{$DEPS}, 162 }) 163 } 164 ` 165 166 var template_link_pkg = `// export by github.com/goplus/igop/cmd/qexp 167 168 $TAGS 169 170 package $PKGNAME 171 172 import ( 173 $IMPORTS 174 175 "github.com/goplus/igop" 176 ) 177 178 func init() { 179 igop.RegisterPackage(&igop.Package { 180 Name: "$PKGNAME", 181 Path: "$PKGPATH", 182 Deps: map[string]string{$DEPS}, 183 Interfaces: map[string]reflect.Type{$INTERFACES}, 184 NamedTypes: map[string]reflect.Type{$NAMEDTYPES}, 185 AliasTypes: map[string]reflect.Type{$ALIASTYPES}, 186 Vars: map[string]reflect.Value{$VARS}, 187 Funcs: map[string]reflect.Value{$FUNCS}, 188 TypedConsts: map[string]igop.TypedConst{$TYPEDCONSTS}, 189 UntypedConsts: map[string]igop.UntypedConst{$UNTYPEDCONSTS}, 190 Source: source, 191 }) 192 } 193 $LINKS 194 var source = $SOURCE 195 ` 196 197 var template_emtpy_link_pkg = `// export by github.com/goplus/igop/cmd/qexp 198 199 $TAGS 200 201 package $PKGNAME 202 203 import ( 204 $IMPORTS 205 206 "github.com/goplus/igop" 207 ) 208 209 func init() { 210 igop.RegisterPackage(&igop.Package { 211 Name: "$PKGNAME", 212 Path: "$PKGPATH", 213 Deps: map[string]string{$DEPS}, 214 Source: source, 215 }) 216 } 217 $LINKS 218 var source = $SOURCE 219 `