golang.org/x/tools/gopls@v0.15.3/internal/test/integration/workspace/metadata_test.go (about)

     1  // Copyright 2022 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  package workspace
     6  
     7  import (
     8  	"strings"
     9  	"testing"
    10  
    11  	. "golang.org/x/tools/gopls/internal/test/integration"
    12  )
    13  
    14  // TODO(rfindley): move workspace tests related to metadata bugs into this
    15  // file.
    16  
    17  func TestFixImportDecl(t *testing.T) {
    18  	const src = `
    19  -- go.mod --
    20  module mod.test
    21  
    22  go 1.12
    23  -- p.go --
    24  package p
    25  
    26  import (
    27  	_ "fmt"
    28  
    29  const C = 42
    30  `
    31  
    32  	Run(t, src, func(t *testing.T, env *Env) {
    33  		env.OpenFile("p.go")
    34  		env.RegexpReplace("p.go", "\"fmt\"", "\"fmt\"\n)")
    35  		env.AfterChange(
    36  			NoDiagnostics(ForFile("p.go")),
    37  		)
    38  	})
    39  }
    40  
    41  // Test that moving ignoring a file via build constraints causes diagnostics to
    42  // be resolved.
    43  func TestIgnoreFile(t *testing.T) {
    44  	const src = `
    45  -- go.mod --
    46  module mod.test
    47  
    48  go 1.12
    49  -- foo.go --
    50  package main
    51  
    52  func main() {}
    53  -- bar.go --
    54  package main
    55  
    56  func main() {}
    57  	`
    58  
    59  	Run(t, src, func(t *testing.T, env *Env) {
    60  		env.OpenFile("foo.go")
    61  		env.OpenFile("bar.go")
    62  		env.OnceMet(
    63  			env.DoneWithOpen(),
    64  			Diagnostics(env.AtRegexp("foo.go", "func (main)")),
    65  			Diagnostics(env.AtRegexp("bar.go", "func (main)")),
    66  		)
    67  
    68  		// Ignore bar.go. This should resolve diagnostics.
    69  		env.RegexpReplace("bar.go", "package main", "//go:build ignore\n\npackage main")
    70  
    71  		// To make this test pass with experimentalUseInvalidMetadata, we could make
    72  		// an arbitrary edit that invalidates the snapshot, at which point the
    73  		// orphaned diagnostics will be invalidated.
    74  		//
    75  		// But of course, this should not be necessary: we should invalidate stale
    76  		// information when fresh metadata arrives.
    77  		// env.RegexpReplace("foo.go", "package main", "package main // test")
    78  		env.AfterChange(
    79  			NoDiagnostics(ForFile("foo.go")),
    80  			NoDiagnostics(ForFile("bar.go")),
    81  		)
    82  
    83  		// If instead of 'ignore' (which gopls treats as a standalone package) we
    84  		// used a different build tag, we should get a warning about having no
    85  		// packages for bar.go
    86  		env.RegexpReplace("bar.go", "ignore", "excluded")
    87  		env.AfterChange(
    88  			Diagnostics(env.AtRegexp("bar.go", "package (main)"), WithMessage("excluded due to its build tags")),
    89  		)
    90  	})
    91  }
    92  
    93  func TestReinitializeRepeatedly(t *testing.T) {
    94  	const multiModule = `
    95  -- go.work --
    96  go 1.18
    97  
    98  use (
    99  	moda/a
   100  	modb
   101  )
   102  -- moda/a/go.mod --
   103  module a.com
   104  
   105  require b.com v1.2.3
   106  -- moda/a/go.sum --
   107  b.com v1.2.3 h1:tXrlXP0rnjRpKNmkbLYoWBdq0ikb3C3bKK9//moAWBI=
   108  b.com v1.2.3/go.mod h1:D+J7pfFBZK5vdIdZEFquR586vKKIkqG7Qjw9AxG5BQ8=
   109  -- moda/a/a.go --
   110  package a
   111  
   112  import (
   113  	"b.com/b"
   114  )
   115  
   116  func main() {
   117  	var x int
   118  	_ = b.Hello()
   119  	// AAA
   120  }
   121  -- modb/go.mod --
   122  module b.com
   123  
   124  -- modb/b/b.go --
   125  package b
   126  
   127  func Hello() int {
   128  	var x int
   129  }
   130  `
   131  	WithOptions(
   132  		ProxyFiles(workspaceModuleProxy),
   133  		Settings{
   134  			// For this test, we want workspace diagnostics to start immediately
   135  			// during change processing.
   136  			"diagnosticsDelay": "0",
   137  		},
   138  	).Run(t, multiModule, func(t *testing.T, env *Env) {
   139  		env.OpenFile("moda/a/a.go")
   140  		env.AfterChange()
   141  
   142  		// This test verifies that we fully process workspace reinitialization
   143  		// (which allows GOPROXY), even when the reinitialized snapshot is
   144  		// invalidated by subsequent changes.
   145  		//
   146  		// First, update go.work to remove modb. This will cause reinitialization
   147  		// to fetch b.com from the proxy.
   148  		env.WriteWorkspaceFile("go.work", "go 1.18\nuse moda/a")
   149  		// Next, wait for gopls to start processing the change. Because we've set
   150  		// diagnosticsDelay to zero, this will start diagnosing the workspace (and
   151  		// try to reinitialize on the snapshot context).
   152  		env.Await(env.StartedChangeWatchedFiles())
   153  		// Finally, immediately make a file change to cancel the previous
   154  		// operation. This is racy, but will usually cause initialization to be
   155  		// canceled.
   156  		env.RegexpReplace("moda/a/a.go", "AAA", "BBB")
   157  		env.AfterChange()
   158  		// Now, to satisfy a definition request, gopls will try to reload moda. But
   159  		// without access to the proxy (because this is no longer a
   160  		// reinitialization), this loading will fail.
   161  		loc := env.GoToDefinition(env.RegexpSearch("moda/a/a.go", "Hello"))
   162  		got := env.Sandbox.Workdir.URIToPath(loc.URI)
   163  		if want := "b.com@v1.2.3/b/b.go"; !strings.HasSuffix(got, want) {
   164  			t.Errorf("expected %s, got %v", want, got)
   165  		}
   166  	})
   167  }
   168  
   169  // Test for golang/go#59458. With lazy module loading, we may not need
   170  // transitively required modules.
   171  func TestNestedModuleLoading_Issue59458(t *testing.T) {
   172  	// In this test, module b.com/nested requires b.com/other, which in turn
   173  	// requires b.com, but b.com/nested does not reach b.com through the package
   174  	// graph. Therefore, b.com/nested does not need b.com on 1.17 and later,
   175  	// thanks to graph pruning.
   176  	//
   177  	// We verify that we can load b.com/nested successfully. Previously, we
   178  	// couldn't, because loading the pattern b.com/nested/... matched the module
   179  	// b.com, which exists in the module graph but does not have a go.sum entry.
   180  
   181  	const proxy = `
   182  -- b.com@v1.2.3/go.mod --
   183  module b.com
   184  
   185  go 1.18
   186  -- b.com@v1.2.3/b/b.go --
   187  package b
   188  
   189  func Hello() {}
   190  
   191  -- b.com/other@v1.4.6/go.mod --
   192  module b.com/other
   193  
   194  go 1.18
   195  
   196  require b.com v1.2.3
   197  -- b.com/other@v1.4.6/go.sun --
   198  b.com v1.2.3 h1:AGjCxWRJLUuJiZ21IUTByr9buoa6+B6Qh5LFhVLKpn4=
   199  -- b.com/other@v1.4.6/bar/bar.go --
   200  package bar
   201  
   202  import "b.com/b"
   203  
   204  func _() {
   205  	b.Hello()
   206  }
   207  -- b.com/other@v1.4.6/foo/foo.go --
   208  package foo
   209  
   210  const Foo = 0
   211  `
   212  
   213  	const files = `
   214  -- go.mod --
   215  module b.com/nested
   216  
   217  go 1.18
   218  
   219  require b.com/other v1.4.6
   220  -- go.sum --
   221  b.com/other v1.4.6 h1:pHXSzGsk6DamYXp9uRdDB9A/ZQqAN9it+JudU0sBf94=
   222  b.com/other v1.4.6/go.mod h1:T0TYuGdAHw4p/l0+1P/yhhYHfZRia7PaadNVDu58OWM=
   223  -- nested.go --
   224  package nested
   225  
   226  import "b.com/other/foo"
   227  
   228  const C = foo.Foo
   229  `
   230  	WithOptions(
   231  		ProxyFiles(proxy),
   232  	).Run(t, files, func(t *testing.T, env *Env) {
   233  		env.OnceMet(
   234  			InitialWorkspaceLoad,
   235  			NoDiagnostics(),
   236  		)
   237  	})
   238  }