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  `