Skip to content

Commit bddb372

Browse files
committed
gopls: deprecate three experimental features
Deprecate the following features, which never made it out of experimental: - experimentalWorkspaceModule (golang/go#52897) - experimentalWatchedFileDelay (golang/go#55268) - experimentalUseInvalidMetadata (golang/go#54180) See the associated issues for rationale behind the deprecations. With this change, any users configuring these settings will get a ShowMessageRequest warning them of the deprecation. Fixes golang/go#52897 Fixes golang/go#55268 Fixes golang/go#54180 Change-Id: I49f178e68793df4e4f9edb63e9b03cad127c5f51 Reviewed-on: https://go-review.googlesource.com/c/tools/+/434640 TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Alan Donovan <[email protected]> Run-TryBot: Robert Findley <[email protected]> gopls-CI: kokoro <[email protected]>
1 parent 4dd4ddb commit bddb372

File tree

5 files changed

+103
-32
lines changed

5 files changed

+103
-32
lines changed

gopls/doc/settings.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,9 @@ Default: `true`.
123123
experimentalWorkspaceModule opts a user into the experimental support
124124
for multi-module workspaces.
125125

126+
Deprecated: this feature is deprecated and will be removed in a future
127+
version of gopls (https://go.dev/issue/55331).
128+
126129
Default: `false`.
127130

128131
#### **experimentalPackageCacheKey** *bool*
@@ -164,8 +167,10 @@ Default: `false`.
164167

165168
experimentalUseInvalidMetadata enables gopls to fall back on outdated
166169
package metadata to provide editor features if the go command fails to
167-
load packages for some reason (like an invalid go.mod file). This will
168-
eventually be the default behavior, and this setting will be removed.
170+
load packages for some reason (like an invalid go.mod file).
171+
172+
Deprecated: this setting is deprecated and will be removed in a future
173+
version of gopls (https://go.dev/issue/55333).
169174

170175
Default: `false`.
171176

@@ -353,6 +358,9 @@ file system notifications.
353358

354359
This option must be set to a valid duration string, for example `"100ms"`.
355360

361+
Deprecated: this setting is deprecated and will be removed in a future
362+
version of gopls (https://go.dev/issue/55332)
363+
356364
Default: `"0s"`.
357365

358366
#### Documentation

gopls/doc/workspace.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,11 @@ go work use tools tools/gopls
4444

4545
...followed by opening the `$WORK` directory in our editor.
4646

47-
#### Experimental workspace module (Go 1.17 and earlier)
47+
#### DEPRECATED: Experimental workspace module (Go 1.17 and earlier)
48+
49+
**This feature is deprecated and will be removed in future versions of gopls.
50+
Please see [issue #52897](https://go.dev/issue/52897) for additional
51+
information.**
4852

4953
With earlier versions of Go, `gopls` can simulate multi-module workspaces by
5054
creating a synthetic module requiring the modules in the workspace root.

gopls/internal/lsp/source/api_json.go

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

gopls/internal/lsp/source/options.go

Lines changed: 60 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,9 @@ type BuildOptions struct {
266266

267267
// ExperimentalWorkspaceModule opts a user into the experimental support
268268
// for multi-module workspaces.
269+
//
270+
// Deprecated: this feature is deprecated and will be removed in a future
271+
// version of gopls (https://go.dev/issue/55331).
269272
ExperimentalWorkspaceModule bool `status:"experimental"`
270273

271274
// ExperimentalPackageCacheKey controls whether to use a coarser cache key
@@ -288,8 +291,10 @@ type BuildOptions struct {
288291

289292
// ExperimentalUseInvalidMetadata enables gopls to fall back on outdated
290293
// package metadata to provide editor features if the go command fails to
291-
// load packages for some reason (like an invalid go.mod file). This will
292-
// eventually be the default behavior, and this setting will be removed.
294+
// load packages for some reason (like an invalid go.mod file).
295+
//
296+
// Deprecated: this setting is deprecated and will be removed in a future
297+
// version of gopls (https://go.dev/issue/55333).
293298
ExperimentalUseInvalidMetadata bool `status:"experimental"`
294299
}
295300

@@ -425,6 +430,9 @@ type DiagnosticOptions struct {
425430
// file system notifications.
426431
//
427432
// This option must be set to a valid duration string, for example `"100ms"`.
433+
//
434+
// Deprecated: this setting is deprecated and will be removed in a future
435+
// version of gopls (https://go.dev/issue/55332)
428436
ExperimentalWatchedFileDelay time.Duration `status:"experimental"`
429437
}
430438

@@ -865,15 +873,15 @@ func (o *Options) set(name string, value interface{}, seen map[string]struct{})
865873

866874
result := OptionResult{Name: name, Value: value}
867875
if _, ok := seen[name]; ok {
868-
result.errorf("duplicate configuration for %s", name)
876+
result.parseErrorf("duplicate configuration for %s", name)
869877
}
870878
seen[name] = struct{}{}
871879

872880
switch name {
873881
case "env":
874882
menv, ok := value.(map[string]interface{})
875883
if !ok {
876-
result.errorf("invalid type %T, expect map", value)
884+
result.parseErrorf("invalid type %T, expect map", value)
877885
break
878886
}
879887
if o.Env == nil {
@@ -886,7 +894,7 @@ func (o *Options) set(name string, value interface{}, seen map[string]struct{})
886894
case "buildFlags":
887895
iflags, ok := value.([]interface{})
888896
if !ok {
889-
result.errorf("invalid type %T, expect list", value)
897+
result.parseErrorf("invalid type %T, expect list", value)
890898
break
891899
}
892900
flags := make([]string, 0, len(iflags))
@@ -897,14 +905,14 @@ func (o *Options) set(name string, value interface{}, seen map[string]struct{})
897905
case "directoryFilters":
898906
ifilters, ok := value.([]interface{})
899907
if !ok {
900-
result.errorf("invalid type %T, expect list", value)
908+
result.parseErrorf("invalid type %T, expect list", value)
901909
break
902910
}
903911
var filters []string
904912
for _, ifilter := range ifilters {
905913
filter, err := validateDirectoryFilter(fmt.Sprintf("%v", ifilter))
906914
if err != nil {
907-
result.errorf(err.Error())
915+
result.parseErrorf("%v", err)
908916
return result
909917
}
910918
filters = append(filters, strings.TrimRight(filepath.FromSlash(filter), "/"))
@@ -1048,7 +1056,12 @@ func (o *Options) set(name string, value interface{}, seen map[string]struct{})
10481056
case "experimentalPostfixCompletions":
10491057
result.setBool(&o.ExperimentalPostfixCompletions)
10501058

1051-
case "experimentalWorkspaceModule": // TODO(rfindley): suggest go.work on go1.18+
1059+
case "experimentalWorkspaceModule":
1060+
const msg = "The experimentalWorkspaceModule feature has been replaced by go workspaces, " +
1061+
"and will be removed in a future version of gopls (https://go.dev/issue/55331). " +
1062+
"Please see https://github.com/golang/tools/blob/master/gopls/doc/workspace.md " +
1063+
"for information on setting up multi-module workspaces using go.work files."
1064+
result.softErrorf(msg)
10521065
result.setBool(&o.ExperimentalWorkspaceModule)
10531066

10541067
case "experimentalTemplateSupport": // TODO(pjw): remove after June 2022
@@ -1067,14 +1080,18 @@ func (o *Options) set(name string, value interface{}, seen map[string]struct{})
10671080
o.TemplateExtensions = nil
10681081
break
10691082
}
1070-
result.errorf(fmt.Sprintf("unexpected type %T not []string", value))
1071-
case "experimentalDiagnosticsDelay", "diagnosticsDelay":
1072-
if name == "experimentalDiagnosticsDelay" {
1073-
result.deprecated("diagnosticsDelay")
1074-
}
1083+
result.parseErrorf("unexpected type %T not []string", value)
1084+
1085+
case "experimentalDiagnosticsDelay":
1086+
result.deprecated("diagnosticsDelay")
1087+
1088+
case "diagnosticsDelay":
10751089
result.setDuration(&o.DiagnosticsDelay)
10761090

10771091
case "experimentalWatchedFileDelay":
1092+
const msg = "The experimentalWatchedFileDelay setting is deprecated, and will " +
1093+
"be removed in a future version of gopls (https://go.dev/issue/55332)."
1094+
result.softErrorf(msg)
10781095
result.setDuration(&o.ExperimentalWatchedFileDelay)
10791096

10801097
case "experimentalPackageCacheKey":
@@ -1087,6 +1104,9 @@ func (o *Options) set(name string, value interface{}, seen map[string]struct{})
10871104
result.setBool(&o.AllowImplicitNetworkAccess)
10881105

10891106
case "experimentalUseInvalidMetadata":
1107+
const msg = "The experimentalUseInvalidMetadata setting is deprecated, and will be removed" +
1108+
"in a future version of gopls (https://go.dev/issue/55333)."
1109+
result.softErrorf(msg)
10901110
result.setBool(&o.ExperimentalUseInvalidMetadata)
10911111

10921112
case "allExperiments":
@@ -1140,7 +1160,11 @@ func (o *Options) set(name string, value interface{}, seen map[string]struct{})
11401160
return result
11411161
}
11421162

1143-
func (r *OptionResult) errorf(msg string, values ...interface{}) {
1163+
// parseErrorf reports an error parsing the current configuration value.
1164+
func (r *OptionResult) parseErrorf(msg string, values ...interface{}) {
1165+
if false {
1166+
_ = fmt.Sprintf(msg, values...) // this causes vet to check this like printf
1167+
}
11441168
prefix := fmt.Sprintf("parsing setting %q: ", r.Name)
11451169
r.Error = fmt.Errorf(prefix+msg, values...)
11461170
}
@@ -1154,6 +1178,16 @@ func (e *SoftError) Error() string {
11541178
return e.msg
11551179
}
11561180

1181+
// softErrorf reports an error that does not affect the functionality of gopls
1182+
// (a warning in the UI).
1183+
// The formatted message will be shown to the user unmodified.
1184+
func (r *OptionResult) softErrorf(format string, values ...interface{}) {
1185+
msg := fmt.Sprintf(format, values...)
1186+
r.Error = &SoftError{msg}
1187+
}
1188+
1189+
// deprecated reports the current setting as deprecated. If 'replacement' is
1190+
// non-nil, it is suggested to the user.
11571191
func (r *OptionResult) deprecated(replacement string) {
11581192
msg := fmt.Sprintf("gopls setting %q is deprecated", r.Name)
11591193
if replacement != "" {
@@ -1162,14 +1196,15 @@ func (r *OptionResult) deprecated(replacement string) {
11621196
r.Error = &SoftError{msg}
11631197
}
11641198

1199+
// unexpected reports that the current setting is not known to gopls.
11651200
func (r *OptionResult) unexpected() {
11661201
r.Error = fmt.Errorf("unexpected gopls setting %q", r.Name)
11671202
}
11681203

11691204
func (r *OptionResult) asBool() (bool, bool) {
11701205
b, ok := r.Value.(bool)
11711206
if !ok {
1172-
r.errorf("invalid type %T, expect bool", r.Value)
1207+
r.parseErrorf("invalid type %T, expect bool", r.Value)
11731208
return false, false
11741209
}
11751210
return b, true
@@ -1185,7 +1220,7 @@ func (r *OptionResult) setDuration(d *time.Duration) {
11851220
if v, ok := r.asString(); ok {
11861221
parsed, err := time.ParseDuration(v)
11871222
if err != nil {
1188-
r.errorf("failed to parse duration %q: %v", v, err)
1223+
r.parseErrorf("failed to parse duration %q: %v", v, err)
11891224
return
11901225
}
11911226
*d = parsed
@@ -1217,18 +1252,18 @@ func (r *OptionResult) setAnnotationMap(bm *map[Annotation]bool) {
12171252
switch k {
12181253
case "noEscape":
12191254
m[Escape] = false
1220-
r.errorf(`"noEscape" is deprecated, set "Escape: false" instead`)
1255+
r.parseErrorf(`"noEscape" is deprecated, set "Escape: false" instead`)
12211256
case "noNilcheck":
12221257
m[Nil] = false
1223-
r.errorf(`"noNilcheck" is deprecated, set "Nil: false" instead`)
1258+
r.parseErrorf(`"noNilcheck" is deprecated, set "Nil: false" instead`)
12241259
case "noInline":
12251260
m[Inline] = false
1226-
r.errorf(`"noInline" is deprecated, set "Inline: false" instead`)
1261+
r.parseErrorf(`"noInline" is deprecated, set "Inline: false" instead`)
12271262
case "noBounds":
12281263
m[Bounds] = false
1229-
r.errorf(`"noBounds" is deprecated, set "Bounds: false" instead`)
1264+
r.parseErrorf(`"noBounds" is deprecated, set "Bounds: false" instead`)
12301265
default:
1231-
r.errorf(err.Error())
1266+
r.parseErrorf("%v", err)
12321267
}
12331268
continue
12341269
}
@@ -1240,15 +1275,15 @@ func (r *OptionResult) setAnnotationMap(bm *map[Annotation]bool) {
12401275
func (r *OptionResult) asBoolMap() map[string]bool {
12411276
all, ok := r.Value.(map[string]interface{})
12421277
if !ok {
1243-
r.errorf("invalid type %T for map[string]bool option", r.Value)
1278+
r.parseErrorf("invalid type %T for map[string]bool option", r.Value)
12441279
return nil
12451280
}
12461281
m := make(map[string]bool)
12471282
for a, enabled := range all {
12481283
if enabled, ok := enabled.(bool); ok {
12491284
m[a] = enabled
12501285
} else {
1251-
r.errorf("invalid type %T for map key %q", enabled, a)
1286+
r.parseErrorf("invalid type %T for map key %q", enabled, a)
12521287
return m
12531288
}
12541289
}
@@ -1258,7 +1293,7 @@ func (r *OptionResult) asBoolMap() map[string]bool {
12581293
func (r *OptionResult) asString() (string, bool) {
12591294
b, ok := r.Value.(string)
12601295
if !ok {
1261-
r.errorf("invalid type %T, expect string", r.Value)
1296+
r.parseErrorf("invalid type %T, expect string", r.Value)
12621297
return "", false
12631298
}
12641299
return b, true
@@ -1271,7 +1306,7 @@ func (r *OptionResult) asOneOf(options ...string) (string, bool) {
12711306
}
12721307
s, err := asOneOf(s, options...)
12731308
if err != nil {
1274-
r.errorf(err.Error())
1309+
r.parseErrorf("%v", err)
12751310
}
12761311
return s, err == nil
12771312
}

gopls/internal/regtest/misc/configuration_test.go

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,30 @@ var FooErr = errors.New("foo")
7171
WithOptions(
7272
Settings{"staticcheck": true},
7373
).Run(t, files, func(t *testing.T, env *Env) {
74-
env.Await(ShownMessage("staticcheck is not supported"))
74+
env.Await(
75+
OnceMet(
76+
InitialWorkspaceLoad,
77+
ShownMessage("staticcheck is not supported"),
78+
),
79+
)
80+
})
81+
}
82+
83+
func TestDeprecatedSettings(t *testing.T) {
84+
WithOptions(
85+
Settings{
86+
"experimentalUseInvalidMetadata": true,
87+
"experimentalWatchedFileDelay": "1s",
88+
"experimentalWorkspaceModule": true,
89+
},
90+
).Run(t, "", func(t *testing.T, env *Env) {
91+
env.Await(
92+
OnceMet(
93+
InitialWorkspaceLoad,
94+
ShownMessage("experimentalWorkspaceModule"),
95+
ShownMessage("experimentalUseInvalidMetadata"),
96+
ShownMessage("experimentalWatchedFileDelay"),
97+
),
98+
)
7599
})
76100
}

0 commit comments

Comments
 (0)