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

     1  // Copyright 2020 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 misc
     6  
     7  import (
     8  	"testing"
     9  
    10  	. "golang.org/x/tools/gopls/internal/test/integration"
    11  
    12  	"golang.org/x/tools/internal/testenv"
    13  )
    14  
    15  // Test that enabling and disabling produces the expected results of showing
    16  // and hiding staticcheck analysis results.
    17  func TestChangeConfiguration(t *testing.T) {
    18  	// Staticcheck only supports Go versions >= 1.19.
    19  	// Note: keep this in sync with TestStaticcheckWarning. Below this version we
    20  	// should get an error when setting staticcheck configuration.
    21  	testenv.NeedsGo1Point(t, 20)
    22  
    23  	const files = `
    24  -- go.mod --
    25  module mod.com
    26  
    27  go 1.12
    28  -- a/a.go --
    29  package a
    30  
    31  import "errors"
    32  
    33  // FooErr should be called ErrFoo (ST1012)
    34  var FooErr = errors.New("foo")
    35  `
    36  	Run(t, files, func(t *testing.T, env *Env) {
    37  		env.OpenFile("a/a.go")
    38  		env.AfterChange(
    39  			NoDiagnostics(ForFile("a/a.go")),
    40  		)
    41  		cfg := env.Editor.Config()
    42  		cfg.Settings = map[string]any{
    43  			"staticcheck": true,
    44  		}
    45  		env.ChangeConfiguration(cfg)
    46  		env.AfterChange(
    47  			Diagnostics(env.AtRegexp("a/a.go", "var (FooErr)")),
    48  		)
    49  	})
    50  }
    51  
    52  func TestIdenticalConfiguration(t *testing.T) {
    53  	// This test checks that changing configuration does not cause views to be
    54  	// recreated if there is no configuration change.
    55  	const files = `
    56  -- a.go --
    57  package p
    58  
    59  func _() {
    60  	var x *int
    61  	y := *x
    62  	_ = y
    63  }
    64  `
    65  	Run(t, files, func(t *testing.T, env *Env) {
    66  		// Sanity check: before disabling the nilness analyzer, we should have a
    67  		// diagnostic for the nil dereference.
    68  		env.OpenFile("a.go")
    69  		env.AfterChange(
    70  			Diagnostics(
    71  				ForFile("a.go"),
    72  				WithMessage("nil dereference"),
    73  			),
    74  		)
    75  
    76  		// Collect the view ID before changing configuration.
    77  		viewID := func() string {
    78  			t.Helper()
    79  			views := env.Views()
    80  			if len(views) != 1 {
    81  				t.Fatalf("got %d views, want 1", len(views))
    82  			}
    83  			return views[0].ID
    84  		}
    85  		before := viewID()
    86  
    87  		// Now disable the nilness analyzer.
    88  		cfg := env.Editor.Config()
    89  		cfg.Settings = map[string]any{
    90  			"analyses": map[string]any{
    91  				"nilness": false,
    92  			},
    93  		}
    94  
    95  		// This should cause the diagnostic to disappear...
    96  		env.ChangeConfiguration(cfg)
    97  		env.AfterChange(
    98  			NoDiagnostics(),
    99  		)
   100  		// ...and we should be on the second view.
   101  		after := viewID()
   102  		if after == before {
   103  			t.Errorf("after configuration change, got view %q (same as before), want new view", after)
   104  		}
   105  
   106  		// Now change configuration again, this time with the same configuration as
   107  		// before. We should still have no diagnostics...
   108  		env.ChangeConfiguration(cfg)
   109  		env.AfterChange(
   110  			NoDiagnostics(),
   111  		)
   112  		// ...and we should still be on the second view.
   113  		if got := viewID(); got != after {
   114  			t.Errorf("after second configuration change, got view %q, want %q", got, after)
   115  		}
   116  	})
   117  }
   118  
   119  // Test that clients can configure per-workspace configuration, which is
   120  // queried via the scopeURI of a workspace/configuration request.
   121  // (this was broken in golang/go#65519).
   122  func TestWorkspaceConfiguration(t *testing.T) {
   123  	const files = `
   124  -- go.mod --
   125  module example.com/config
   126  
   127  go 1.18
   128  
   129  -- a/a.go --
   130  package a
   131  
   132  import "example.com/config/b"
   133  
   134  func _() {
   135  	_ = b.B{2}
   136  }
   137  
   138  -- b/b.go --
   139  package b
   140  
   141  type B struct {
   142  	F int
   143  }
   144  `
   145  
   146  	WithOptions(
   147  		WorkspaceFolders("a"),
   148  		FolderSettings{
   149  			"a": {
   150  				"analyses": map[string]bool{
   151  					"composites": false,
   152  				},
   153  			},
   154  		},
   155  	).Run(t, files, func(t *testing.T, env *Env) {
   156  		env.OpenFile("a/a.go")
   157  		env.AfterChange(NoDiagnostics())
   158  	})
   159  }
   160  
   161  // TestMajorOptionsChange is like TestChangeConfiguration, but modifies an
   162  // an open buffer before making a major (but inconsequential) change that
   163  // causes gopls to recreate the view.
   164  //
   165  // Gopls should not get confused about buffer content when recreating the view.
   166  func TestMajorOptionsChange(t *testing.T) {
   167  	testenv.NeedsGo1Point(t, 20) // needs staticcheck
   168  
   169  	const files = `
   170  -- go.mod --
   171  module mod.com
   172  
   173  go 1.12
   174  -- a/a.go --
   175  package a
   176  
   177  import "errors"
   178  
   179  var ErrFoo = errors.New("foo")
   180  `
   181  	Run(t, files, func(t *testing.T, env *Env) {
   182  		env.OpenFile("a/a.go")
   183  		// Introduce a staticcheck diagnostic. It should be detected when we enable
   184  		// staticcheck later.
   185  		env.RegexpReplace("a/a.go", "ErrFoo", "FooErr")
   186  		env.AfterChange(
   187  			NoDiagnostics(ForFile("a/a.go")),
   188  		)
   189  		cfg := env.Editor.Config()
   190  		// Any change to environment recreates the view, but this should not cause
   191  		// gopls to get confused about the content of a/a.go: we should get the
   192  		// staticcheck diagnostic below.
   193  		cfg.Env = map[string]string{
   194  			"AN_ARBITRARY_VAR": "FOO",
   195  		}
   196  		cfg.Settings = map[string]interface{}{
   197  			"staticcheck": true,
   198  		}
   199  		env.ChangeConfiguration(cfg)
   200  		env.AfterChange(
   201  			Diagnostics(env.AtRegexp("a/a.go", "var (FooErr)")),
   202  		)
   203  	})
   204  }
   205  
   206  func TestStaticcheckWarning(t *testing.T) {
   207  	// Note: keep this in sync with TestChangeConfiguration.
   208  	testenv.SkipAfterGo1Point(t, 19)
   209  
   210  	const files = `
   211  -- go.mod --
   212  module mod.com
   213  
   214  go 1.12
   215  -- a/a.go --
   216  package a
   217  
   218  import "errors"
   219  
   220  // FooErr should be called ErrFoo (ST1012)
   221  var FooErr = errors.New("foo")
   222  `
   223  
   224  	WithOptions(
   225  		Settings{"staticcheck": true},
   226  	).Run(t, files, func(t *testing.T, env *Env) {
   227  		env.OnceMet(
   228  			InitialWorkspaceLoad,
   229  			ShownMessage("staticcheck is not supported"),
   230  		)
   231  	})
   232  }
   233  
   234  func TestGofumptWarning(t *testing.T) {
   235  	testenv.SkipAfterGo1Point(t, 17)
   236  
   237  	WithOptions(
   238  		Settings{"gofumpt": true},
   239  	).Run(t, "", func(t *testing.T, env *Env) {
   240  		env.OnceMet(
   241  			InitialWorkspaceLoad,
   242  			ShownMessage("gofumpt is not supported"),
   243  		)
   244  	})
   245  }
   246  
   247  func TestDeprecatedSettings(t *testing.T) {
   248  	WithOptions(
   249  		Settings{
   250  			"experimentalUseInvalidMetadata": true,
   251  			"experimentalWatchedFileDelay":   "1s",
   252  			"experimentalWorkspaceModule":    true,
   253  			"tempModfile":                    true,
   254  			"allowModfileModifications":      true,
   255  		},
   256  	).Run(t, "", func(t *testing.T, env *Env) {
   257  		env.OnceMet(
   258  			InitialWorkspaceLoad,
   259  			ShownMessage("experimentalWorkspaceModule"),
   260  			ShownMessage("experimentalUseInvalidMetadata"),
   261  			ShownMessage("experimentalWatchedFileDelay"),
   262  			ShownMessage("tempModfile"),
   263  			ShownMessage("allowModfileModifications"),
   264  		)
   265  	})
   266  }