Skip to content

Commit

Permalink
all: merge master (9358add) into gopls-release-branch.0.9
Browse files Browse the repository at this point in the history
Also add the replace directive to ./gopls/go.mod.

For golang/go#53412

Merge List:

+ 2022-06-30 9358add internal/lsp/cache: remove unused function
+ 2022-06-30 c77473f gopls: upgrade staticcheck to v0.3.2
+ 2022-06-30 e8e5b37 internal/lsp/cache: don't construct a new metadata graph if no changes
+ 2022-06-30 8314b7a go/analysis: add suggested fix for unkeyed composite literals
+ 2022-06-30 8865782 internal/lsp: add text edits for unkeyed literals
+ 2022-06-30 1a196f0 internal/lsp/cache: don't build symbol info for non-Go files
+ 2022-06-29 b84d509 gopls/doc: regenerate documentation
+ 2022-06-29 c10541a go/analysis/passes/fieldalignment: document "false sharing"
+ 2022-06-28 7743d1d internal/lsp: respect range for inlay hints
+ 2022-06-28 0248714 internal/lsp: add additional instrumentation around package loading
+ 2022-06-28 e5b3324 internal/lsp: add InlayHint regtests
+ 2022-06-28 2a90056 go/gcexportdata: fix Find for Go modules

Change-Id: Id16dc1247a73be034ddfc70630254db082da7b6f
  • Loading branch information
findleyr committed Jun 30, 2022
2 parents 51f46e2 + 9358add commit 6178576
Show file tree
Hide file tree
Showing 24 changed files with 443 additions and 42 deletions.
41 changes: 35 additions & 6 deletions go/analysis/passes/composite/composite.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
package composite

import (
"fmt"
"go/ast"
"go/types"
"strings"
Expand Down Expand Up @@ -83,7 +84,8 @@ func run(pass *analysis.Pass) (interface{}, error) {
}
for _, typ := range structuralTypes {
under := deref(typ.Underlying())
if _, ok := under.(*types.Struct); !ok {
strct, ok := under.(*types.Struct)
if !ok {
// skip non-struct composite literals
continue
}
Expand All @@ -92,20 +94,47 @@ func run(pass *analysis.Pass) (interface{}, error) {
continue
}

// check if the CompositeLit contains an unkeyed field
// check if the struct contains an unkeyed field
allKeyValue := true
for _, e := range cl.Elts {
var suggestedFixAvailable = len(cl.Elts) == strct.NumFields()
var missingKeys []analysis.TextEdit
for i, e := range cl.Elts {
if _, ok := e.(*ast.KeyValueExpr); !ok {
allKeyValue = false
break
if i >= strct.NumFields() {
break
}
field := strct.Field(i)
if !field.Exported() {
// Adding unexported field names for structs not defined
// locally will not work.
suggestedFixAvailable = false
break
}
missingKeys = append(missingKeys, analysis.TextEdit{
Pos: e.Pos(),
End: e.Pos(),
NewText: []byte(fmt.Sprintf("%s: ", field.Name())),
})
}
}
if allKeyValue {
// all the composite literal fields are keyed
// all the struct fields are keyed
continue
}

pass.ReportRangef(cl, "%s composite literal uses unkeyed fields", typeName)
diag := analysis.Diagnostic{
Pos: cl.Pos(),
End: cl.End(),
Message: fmt.Sprintf("%s struct literal uses unkeyed fields", typeName),
}
if suggestedFixAvailable {
diag.SuggestedFixes = []analysis.SuggestedFix{{
Message: "Add field names to struct literal",
TextEdits: missingKeys,
}}
}
pass.Report(diag)
return
}
})
Expand Down
2 changes: 1 addition & 1 deletion go/analysis/passes/composite/composite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@ func Test(t *testing.T) {
if typeparams.Enabled {
pkgs = append(pkgs, "typeparams")
}
analysistest.Run(t, testdata, composite.Analyzer, pkgs...)
analysistest.RunWithSuggestedFixes(t, testdata, composite.Analyzer, pkgs...)
}
17 changes: 17 additions & 0 deletions go/analysis/passes/composite/testdata/src/a/a.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"go/scanner"
"go/token"
"image"
"sync"
"unicode"
)

Expand Down Expand Up @@ -79,6 +80,18 @@ var badStructLiteral = flag.Flag{ // want "unkeyed fields"
nil, // Value
"DefValue",
}
var tooManyFieldsStructLiteral = flag.Flag{ // want "unkeyed fields"
"Name",
"Usage",
nil, // Value
"DefValue",
"Extra Field",
}
var tooFewFieldsStructLiteral = flag.Flag{ // want "unkeyed fields"
"Name",
"Usage",
nil, // Value
}

var delta [3]rune

Expand All @@ -100,6 +113,10 @@ var badScannerErrorList = scanner.ErrorList{
&scanner.Error{token.Position{}, "foobar"}, // want "unkeyed fields"
}

// sync.Mutex has unexported fields. We expect a diagnostic but no
// suggested fix.
var mu = sync.Mutex{0, 0} // want "unkeyed fields"

// Check whitelisted structs: if vet is run with --compositewhitelist=false,
// this line triggers an error.
var whitelistedPoint = image.Point{1, 2}
Expand Down
144 changes: 144 additions & 0 deletions go/analysis/passes/composite/testdata/src/a/a.go.golden
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This file contains the test for untagged struct literals.

package a

import (
"flag"
"go/scanner"
"go/token"
"image"
"sync"
"unicode"
)

var Okay1 = []string{
"Name",
"Usage",
"DefValue",
}

var Okay2 = map[string]bool{
"Name": true,
"Usage": true,
"DefValue": true,
}

var Okay3 = struct {
X string
Y string
Z string
}{
"Name",
"Usage",
"DefValue",
}

var Okay4 = []struct {
A int
B int
}{
{1, 2},
{3, 4},
}

type MyStruct struct {
X string
Y string
Z string
}

var Okay5 = &MyStruct{
"Name",
"Usage",
"DefValue",
}

var Okay6 = []MyStruct{
{"foo", "bar", "baz"},
{"aa", "bb", "cc"},
}

var Okay7 = []*MyStruct{
{"foo", "bar", "baz"},
{"aa", "bb", "cc"},
}

// Testing is awkward because we need to reference things from a separate package
// to trigger the warnings.

var goodStructLiteral = flag.Flag{
Name: "Name",
Usage: "Usage",
}
var badStructLiteral = flag.Flag{ // want "unkeyed fields"
Name: "Name",
Usage: "Usage",
Value: nil, // Value
DefValue: "DefValue",
}
var tooManyFieldsStructLiteral = flag.Flag{ // want "unkeyed fields"
"Name",
"Usage",
nil, // Value
"DefValue",
"Extra Field",
}
var tooFewFieldsStructLiteral = flag.Flag{ // want "unkeyed fields"
"Name",
"Usage",
nil, // Value
}

var delta [3]rune

// SpecialCase is a named slice of CaseRange to test issue 9171.
var goodNamedSliceLiteral = unicode.SpecialCase{
{Lo: 1, Hi: 2, Delta: delta},
unicode.CaseRange{Lo: 1, Hi: 2, Delta: delta},
}
var badNamedSliceLiteral = unicode.SpecialCase{
{Lo: 1, Hi: 2, Delta: delta}, // want "unkeyed fields"
unicode.CaseRange{Lo: 1, Hi: 2, Delta: delta}, // want "unkeyed fields"
}

// ErrorList is a named slice, so no warnings should be emitted.
var goodScannerErrorList = scanner.ErrorList{
&scanner.Error{Msg: "foobar"},
}
var badScannerErrorList = scanner.ErrorList{
&scanner.Error{Pos: token.Position{}, Msg: "foobar"}, // want "unkeyed fields"
}

// sync.Mutex has unexported fields. We expect a diagnostic but no
// suggested fix.
var mu = sync.Mutex{0, 0} // want "unkeyed fields"

// Check whitelisted structs: if vet is run with --compositewhitelist=false,
// this line triggers an error.
var whitelistedPoint = image.Point{1, 2}

// Do not check type from unknown package.
// See issue 15408.
var unknownPkgVar = unicode.NoSuchType{"foo", "bar"}

// A named pointer slice of CaseRange to test issue 23539. In
// particular, we're interested in how some slice elements omit their
// type.
var goodNamedPointerSliceLiteral = []*unicode.CaseRange{
{Lo: 1, Hi: 2},
&unicode.CaseRange{Lo: 1, Hi: 2},
}
var badNamedPointerSliceLiteral = []*unicode.CaseRange{
{Lo: 1, Hi: 2, Delta: delta}, // want "unkeyed fields"
&unicode.CaseRange{Lo: 1, Hi: 2, Delta: delta}, // want "unkeyed fields"
}

// unicode.Range16 is whitelisted, so there'll be no vet error
var range16 = unicode.Range16{0xfdd0, 0xfdef, 1}

// unicode.Range32 is whitelisted, so there'll be no vet error
var range32 = unicode.Range32{0x1fffe, 0x1ffff, 1}
16 changes: 16 additions & 0 deletions go/analysis/passes/composite/testdata/src/a/a_fuzz_test.go.golden
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

//go:build go1.18
// +build go1.18

package a

import "testing"

var fuzzTargets = []testing.InternalFuzzTarget{
{"Fuzz", Fuzz},
}

func Fuzz(f *testing.F) {}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ package typeparams

import "typeparams/lib"

type localStruct struct { F int }
type localStruct struct{ F int }

func F[
T1 ~struct{ f int },
Expand All @@ -20,8 +20,8 @@ func F[
_ = T1{2}
_ = T2a{2}
_ = T2b{2} // want "unkeyed fields"
_ = T3{1,2}
_ = T4{1,2}
_ = T5{1:2}
_ = T6{1:2}
_ = T3{1, 2}
_ = T4{1, 2}
_ = T5{1: 2}
_ = T6{1: 2}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package typeparams

import "typeparams/lib"

type localStruct struct{ F int }

func F[
T1 ~struct{ f int },
T2a localStruct,
T2b lib.Struct,
T3 ~[]int,
T4 lib.Slice,
T5 ~map[int]int,
T6 lib.Map,
]() {
_ = T1{2}
_ = T2a{2}
_ = T2b{F: 2} // want "unkeyed fields"
_ = T3{1, 2}
_ = T4{1, 2}
_ = T5{1: 2}
_ = T6{1: 2}
}
7 changes: 6 additions & 1 deletion go/analysis/passes/fieldalignment/fieldalignment.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import (
const Doc = `find structs that would use less memory if their fields were sorted
This analyzer find structs that can be rearranged to use less memory, and provides
a suggested edit with the optimal order.
a suggested edit with the most compact order.
Note that there are two different diagnostics reported. One checks struct size,
and the other reports "pointer bytes" used. Pointer bytes is how many bytes of the
Expand All @@ -41,6 +41,11 @@ has 24 pointer bytes because it has to scan further through the *uint32.
struct { string; uint32 }
has 8 because it can stop immediately after the string pointer.
Be aware that the most compact order is not always the most efficient.
In rare cases it may cause two variables each updated by its own goroutine
to occupy the same CPU cache line, inducing a form of memory contention
known as "false sharing" that slows down both goroutines.
`

var Analyzer = &analysis.Analyzer{
Expand Down
2 changes: 0 additions & 2 deletions go/gcexportdata/example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ func ExampleRead() {
log.Fatalf("can't find export data for fmt")
}
fmt.Printf("Package path: %s\n", path)
fmt.Printf("Export data: %s\n", filepath.Base(filename))

// Open and read the file.
f, err := os.Open(filename)
Expand Down Expand Up @@ -80,7 +79,6 @@ func ExampleRead() {
// Output:
//
// Package path: fmt
// Export data: fmt.a
// Package members: Println found
// Println type: func(a ...any) (n int, err error)
// Println location: $GOROOT/src/fmt/print.go:123:1
Expand Down
Loading

0 comments on commit 6178576

Please sign in to comment.