github.com/jhump/golang-x-tools@v0.0.0-20220218190644-4958d6d39439/go/internal/gcimporter/iexport_go118_test.go (about)

     1  // Copyright 2021 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  //go:build go1.18
     6  // +build go1.18
     7  
     8  package gcimporter_test
     9  
    10  import (
    11  	"bytes"
    12  	"go/ast"
    13  	"go/importer"
    14  	"go/parser"
    15  	"go/token"
    16  	"go/types"
    17  	"os"
    18  	"path/filepath"
    19  	"runtime"
    20  	"strings"
    21  	"testing"
    22  
    23  	"github.com/jhump/golang-x-tools/go/internal/gcimporter"
    24  )
    25  
    26  // TODO(rfindley): migrate this to testdata, as has been done in the standard library.
    27  func TestGenericExport(t *testing.T) {
    28  	const src = `
    29  package generic
    30  
    31  type Any any
    32  
    33  type T[A, B any] struct { Left A; Right B }
    34  
    35  func (T[P, Q]) m() {}
    36  
    37  var X T[int, string] = T[int, string]{1, "hi"}
    38  
    39  func ToInt[P interface{ ~int }](p P) int { return int(p) }
    40  
    41  var IntID = ToInt[int]
    42  
    43  type G[C comparable] int
    44  
    45  func ImplicitFunc[T ~int]() {}
    46  
    47  type ImplicitType[T ~int] int
    48  
    49  // Exercise constant import/export
    50  const C1 = 42
    51  const C2 int = 42
    52  const C3 float64 = 42
    53  
    54  type Constraint[T any] interface {
    55         m(T)
    56  }
    57  
    58  // TODO(rfindley): revert to multiple blanks once the restriction on multiple
    59  // blanks is removed from the type checker.
    60  // type Blanks[_ any, _ Constraint[int]] int
    61  // func (Blanks[_, _]) m() {}
    62  type Blanks[_ any] int
    63  func (Blanks[_]) m() {}
    64  `
    65  	testExportSrc(t, []byte(src))
    66  }
    67  
    68  func testExportSrc(t *testing.T, src []byte) {
    69  	// This package only handles gc export data.
    70  	if runtime.Compiler != "gc" {
    71  		t.Skipf("gc-built packages not available (compiler = %s)", runtime.Compiler)
    72  	}
    73  
    74  	// Test at both stages of the 1.18 export data format change.
    75  	tests := []struct {
    76  		name    string
    77  		version int
    78  	}{
    79  		{"legacy generics", gcimporter.IExportVersionGenerics},
    80  		{"go1.18", gcimporter.IExportVersionGo1_18},
    81  	}
    82  
    83  	for _, test := range tests {
    84  		t.Run(test.name, func(t *testing.T) {
    85  			fset := token.NewFileSet()
    86  			f, err := parser.ParseFile(fset, "g.go", src, 0)
    87  			if err != nil {
    88  				t.Fatal(err)
    89  			}
    90  			conf := types.Config{
    91  				Importer: importer.Default(),
    92  			}
    93  			pkg, err := conf.Check("", fset, []*ast.File{f}, nil)
    94  			if err != nil {
    95  				t.Fatal(err)
    96  			}
    97  
    98  			// export
    99  			data, err := iexport(fset, test.version, pkg)
   100  			if err != nil {
   101  				t.Fatal(err)
   102  			}
   103  
   104  			testPkgData(t, fset, test.version, pkg, data)
   105  		})
   106  	}
   107  }
   108  
   109  func TestImportTypeparamTests(t *testing.T) {
   110  	// Check go files in test/typeparam.
   111  	rootDir := filepath.Join(runtime.GOROOT(), "test", "typeparam")
   112  	list, err := os.ReadDir(rootDir)
   113  	if err != nil {
   114  		t.Fatal(err)
   115  	}
   116  
   117  	if isUnifiedBuilder() {
   118  		t.Skip("unified export data format is currently unsupported")
   119  	}
   120  
   121  	skip := map[string]string{
   122  		"issue48424.go": "go/types support missing", // TODO: need to implement this if #48424 is accepted
   123  	}
   124  
   125  	for _, entry := range list {
   126  		if entry.IsDir() || !strings.HasSuffix(entry.Name(), ".go") {
   127  			// For now, only consider standalone go files.
   128  			continue
   129  		}
   130  
   131  		t.Run(entry.Name(), func(t *testing.T) {
   132  			if reason, ok := skip[entry.Name()]; ok {
   133  				t.Skip(reason)
   134  			}
   135  
   136  			filename := filepath.Join(rootDir, entry.Name())
   137  			src, err := os.ReadFile(filename)
   138  			if err != nil {
   139  				t.Fatal(err)
   140  			}
   141  
   142  			if !bytes.HasPrefix(src, []byte("// run")) && !bytes.HasPrefix(src, []byte("// compile")) {
   143  				// We're bypassing the logic of run.go here, so be conservative about
   144  				// the files we consider in an attempt to make this test more robust to
   145  				// changes in test/typeparams.
   146  				t.Skipf("not detected as a run test")
   147  			}
   148  
   149  			testExportSrc(t, src)
   150  		})
   151  	}
   152  }