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  `