Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion internal/x/tools/analysisflags/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,7 @@ This is just a copy of the code without any changes.

## History

- sync with https://github.com/golang/tools/blob/v0.28.0
- https://github.com/golangci/golangci-lint/pull/6076
- sync with https://github.com/golang/tools/blob/v0.37.0/go/analysis/internal/analysisflags
- https://github.com/golangci/golangci-lint/pull/5576
- sync with https://github.com/golang/tools/blob/v0.28.0/go/analysis/internal/analysisflags
27 changes: 11 additions & 16 deletions internal/x/tools/analysisinternal/analysis.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,30 @@ package analysisinternal

import (
"fmt"
"os"
"slices"

"golang.org/x/tools/go/analysis"
)

// MakeReadFile returns a simple implementation of the Pass.ReadFile function.
func MakeReadFile(pass *analysis.Pass) func(filename string) ([]byte, error) {
// A ReadFileFunc is a function that returns the
// contents of a file, such as [os.ReadFile].
type ReadFileFunc = func(filename string) ([]byte, error)

// CheckedReadFile returns a wrapper around a Pass.ReadFile
// function that performs the appropriate checks.
func CheckedReadFile(pass *analysis.Pass, readFile ReadFileFunc) ReadFileFunc {
return func(filename string) ([]byte, error) {
if err := CheckReadable(pass, filename); err != nil {
return nil, err
}
return os.ReadFile(filename)
return readFile(filename)
}
}

// CheckReadable enforces the access policy defined by the ReadFile field of [analysis.Pass].
func CheckReadable(pass *analysis.Pass, filename string) error {
if slicesContains(pass.OtherFiles, filename) ||
slicesContains(pass.IgnoredFiles, filename) {
if slices.Contains(pass.OtherFiles, filename) ||
slices.Contains(pass.IgnoredFiles, filename) {
return nil
}
for _, f := range pass.Files {
Expand All @@ -36,13 +41,3 @@ func CheckReadable(pass *analysis.Pass, filename string) error {
}
return fmt.Errorf("Pass.ReadFile: %s is not among OtherFiles, IgnoredFiles, or names of Files", filename)
}

// TODO(adonovan): use go1.21 slices.Contains.
func slicesContains[S ~[]E, E comparable](slice S, x E) bool {
for _, elem := range slice {
if elem == x {
return true
}
}
return false
}
5 changes: 4 additions & 1 deletion internal/x/tools/analysisinternal/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,7 @@ This is just a copy of the code without any changes.

## History

- sync with https://github.com/golang/tools/blob/v0.28.0
- https://github.com/golangci/golangci-lint/pull/6076
- sync with https://github.com/golang/tools/blob/v0.37.0/internal/analysisinternal/
- https://github.com/golangci/golangci-lint/pull/5576
- sync with https://github.com/golang/tools/blob/v0.28.0/internal/analysisinternal/
3 changes: 2 additions & 1 deletion internal/x/tools/diff/diff.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package diff

import (
"fmt"
"slices"
"sort"
"strings"
)
Expand Down Expand Up @@ -64,7 +65,7 @@ func ApplyBytes(src []byte, edits []Edit) ([]byte, error) {
// It may return a different slice.
func validate(src string, edits []Edit) ([]Edit, int, error) {
if !sort.IsSorted(editsSort(edits)) {
edits = append([]Edit(nil), edits...)
edits = slices.Clone(edits)
SortEdits(edits)
}

Expand Down
2 changes: 1 addition & 1 deletion internal/x/tools/diff/lcs/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func (l lcs) fix() lcs {
// from the set of diagonals in l, find a maximal non-conflicting set
// this problem may be NP-complete, but we use a greedy heuristic,
// which is quadratic, but with a better data structure, could be D log D.
// indepedent is not enough: {0,3,1} and {3,0,2} can't both occur in an lcs
// independent is not enough: {0,3,1} and {3,0,2} can't both occur in an lcs
// which has to have monotone x and y
if len(l) == 0 {
return nil
Expand Down
15 changes: 7 additions & 8 deletions internal/x/tools/diff/lcs/common_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ package lcs

import (
"log"
"math/rand"
"math/rand/v2"
"slices"
"strings"
"testing"
)
Expand Down Expand Up @@ -72,10 +73,8 @@ func check(t *testing.T, str string, lcs lcs, want []string) {
got.WriteString(str[dd.X : dd.X+dd.Len])
}
ans := got.String()
for _, w := range want {
if ans == w {
return
}
if slices.Contains(want, ans) {
return
}
t.Fatalf("str=%q lcs=%v want=%q got=%q", str, lcs, want, ans)
}
Expand Down Expand Up @@ -106,11 +105,11 @@ func lcslen(l lcs) int {
}

// return a random string of length n made of characters from s
func randstr(s string, n int) string {
func randstr(rng *rand.Rand, s string, n int) string {
src := []rune(s)
x := make([]rune, n)
for i := 0; i < n; i++ {
x[i] = src[rand.Intn(len(src))]
for i := range n {
x[i] = src[rng.Int64N(int64(len(src)))]
}
return string(x)
}
Expand Down
2 changes: 1 addition & 1 deletion internal/x/tools/diff/lcs/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ computed labels. That is the worst case. Had the code noticed (x,y)=(u,v)=(3,3)
from the edgegraph. The implementation looks for a number of special cases to try to avoid computing an extra forward path.

If the two-sided algorithm has stop early (because D has become too large) it will have found a forward LCS and a
backwards LCS. Ideally these go with disjoint prefixes and suffixes of A and B, but disjointness may fail and the two
backwards LCS. Ideally these go with disjoint prefixes and suffixes of A and B, but disjointedness may fail and the two
computed LCS may conflict. (An easy example is where A is a suffix of B, and shares a short prefix. The backwards LCS
is all of A, and the forward LCS is a prefix of A.) The algorithm combines the two
to form a best-effort LCS. In the worst case the forward partial LCS may have to
Expand Down
12 changes: 5 additions & 7 deletions internal/x/tools/diff/lcs/old.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ func forward(e *editGraph) lcs {
return ans
}
// from D to D+1
for D := 0; D < e.limit; D++ {
for D := range e.limit {
e.setForward(D+1, -(D + 1), e.getForward(D, -D))
if ok, ans := e.fdone(D+1, -(D + 1)); ok {
return ans
Expand Down Expand Up @@ -199,13 +199,14 @@ func (e *editGraph) bdone(D, k int) (bool, lcs) {
}

// run the backward algorithm, until success or up to the limit on D.
// (used only by tests)
func backward(e *editGraph) lcs {
e.setBackward(0, 0, e.ux)
if ok, ans := e.bdone(0, 0); ok {
return ans
}
// from D to D+1
for D := 0; D < e.limit; D++ {
for D := range e.limit {
e.setBackward(D+1, -(D + 1), e.getBackward(D, -D)-1)
if ok, ans := e.bdone(D+1, -(D + 1)); ok {
return ans
Expand Down Expand Up @@ -299,7 +300,7 @@ func twosided(e *editGraph) lcs {
e.setBackward(0, 0, e.ux)

// from D to D+1
for D := 0; D < e.limit; D++ {
for D := range e.limit {
// just finished a backwards pass, so check
if got, ok := e.twoDone(D, D); ok {
return e.twolcs(D, D, got)
Expand Down Expand Up @@ -376,10 +377,7 @@ func (e *editGraph) twoDone(df, db int) (int, bool) {
if (df+db+e.delta)%2 != 0 {
return 0, false // diagonals cannot overlap
}
kmin := -db + e.delta
if -df > kmin {
kmin = -df
}
kmin := max(-df, -db+e.delta)
kmax := db + e.delta
if df < kmax {
kmax = df
Expand Down
32 changes: 20 additions & 12 deletions internal/x/tools/diff/lcs/old_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ package lcs
import (
"fmt"
"log"
"math/rand"
"math/rand/v2"
"os"
"strings"
"testing"
Expand Down Expand Up @@ -106,15 +106,16 @@ func TestRegressionOld003(t *testing.T) {
}

func TestRandOld(t *testing.T) {
rand.Seed(1)
for i := 0; i < 1000; i++ {
rng := rng(t)

for i := range 1000 {
// TODO(adonovan): use ASCII and bytesSeqs here? The use of
// non-ASCII isn't relevant to the property exercised by the test.
a := []rune(randstr("abω", 16))
b := []rune(randstr("abωc", 16))
a := []rune(randstr(rng, "abω", 16))
b := []rune(randstr(rng, "abωc", 16))
seq := runesSeqs{a, b}

const lim = 24 // large enough to get true lcs
const lim = 0 // make sure we get the lcs (24 was too small)
_, forw := compute(seq, forward, lim)
_, back := compute(seq, backward, lim)
_, two := compute(seq, twosided, lim)
Expand Down Expand Up @@ -158,7 +159,7 @@ func TestDiffAPI(t *testing.T) {
}

func BenchmarkTwoOld(b *testing.B) {
tests := genBench("abc", 96)
tests := genBench(rng(b), "abc", 96)
for i := 0; i < b.N; i++ {
for _, tt := range tests {
_, two := compute(stringSeqs{tt.before, tt.after}, twosided, 100)
Expand All @@ -170,7 +171,7 @@ func BenchmarkTwoOld(b *testing.B) {
}

func BenchmarkForwOld(b *testing.B) {
tests := genBench("abc", 96)
tests := genBench(rng(b), "abc", 96)
for i := 0; i < b.N; i++ {
for _, tt := range tests {
_, two := compute(stringSeqs{tt.before, tt.after}, forward, 100)
Expand All @@ -181,14 +182,21 @@ func BenchmarkForwOld(b *testing.B) {
}
}

func genBench(set string, n int) []struct{ before, after string } {
// rng returns a randomly initialized PRNG whose seeds are logged so
// that occasional test failures can be deterministically replayed.
func rng(tb testing.TB) *rand.Rand {
seed1, seed2 := rand.Uint64(), rand.Uint64()
tb.Logf("PRNG seeds: %d, %d", seed1, seed2)
return rand.New(rand.NewPCG(seed1, seed2))
}

func genBench(rng *rand.Rand, set string, n int) []struct{ before, after string } {
// before and after for benchmarks. 24 strings of length n with
// before and after differing at least once, and about 5%
rand.Seed(3)
var ans []struct{ before, after string }
for i := 0; i < 24; i++ {
for range 24 {
// maybe b should have an approximately known number of diffs
a := randstr(set, n)
a := randstr(rng, set, n)
cnt := 0
bb := make([]rune, 0, n)
for _, r := range a {
Expand Down
2 changes: 1 addition & 1 deletion internal/x/tools/diff/ndiff.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ func diffRunes(before, after []rune) []Edit {
func runes(bytes []byte) []rune {
n := utf8.RuneCount(bytes)
runes := make([]rune, n)
for i := 0; i < n; i++ {
for i := range n {
r, sz := utf8.DecodeRune(bytes)
bytes = bytes[sz:]
runes[i] = r
Expand Down
5 changes: 4 additions & 1 deletion internal/x/tools/diff/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,7 @@ This is just a copy of the code without any changes.

## History

- sync with https://github.com/golang/tools/blob/v0.28.0
- https://github.com/golangci/golangci-lint/pull/6076
- sync with https://github.com/golang/tools/blob/v0.37.0/internal/diff/
- https://github.com/golangci/golangci-lint/pull/5576
- sync with https://github.com/golang/tools/blob/v0.28.0/internal/diff/
6 changes: 3 additions & 3 deletions internal/x/tools/diff/unified.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,12 +129,12 @@ func toUnified(fromName, toName string, content string, edits []Edit, contextLin

switch {
case h != nil && start == last:
//direct extension
// direct extension
case h != nil && start <= last+gap:
//within range of previous lines, add the joiners
// within range of previous lines, add the joiners
addEqualLines(h, lines, last, start)
default:
//need to start a new hunk
// need to start a new hunk
if h != nil {
// add the edge to the previous hunk
addEqualLines(h, lines, last, last+contextLines)
Expand Down
3 changes: 2 additions & 1 deletion pkg/goanalysis/runner_checker.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"errors"
"fmt"
"go/types"
"os"
"reflect"
"time"

Expand Down Expand Up @@ -160,7 +161,7 @@ func (act *action) analyze() {
AllObjectFacts: act.AllObjectFacts,
AllPackageFacts: act.AllPackageFacts,
}
pass.ReadFile = analysisinternal.MakeReadFile(pass)
pass.ReadFile = analysisinternal.CheckedReadFile(pass, os.ReadFile)
act.pass = pass

act.runner.passToPkgGuard.Lock()
Expand Down
Loading