diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8f93baf9a..75038b07d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,11 +23,15 @@ jobs: name: fuzz test runs-on: ubuntu-latest steps: - - uses: jidicula/go-fuzz-action@4f24eed45b25214f31a9fe035ca68ea2c88c6a13 # v1.2.0 + # Pinned a commit to make go version configurable. + # This should be safe to upgrade once this commit is in a released version: + # https://github.com/jidicula/go-fuzz-action/commit/23cc553941669144159507e2cccdbb4afc5b3076 + - uses: jidicula/go-fuzz-action@0206b61afc603b665297621fa5e691b1447a5e57 with: packages: 'github.com/sourcegraph/zoekt' # This is the package where the Protobuf round trip tests are defined fuzz-time: 30s fuzz-minimize-time: 1m + go-version: '1.21' shellcheck: name: shellcheck diff --git a/contentprovider.go b/contentprovider.go index 802f925d7..b1fe0ab81 100644 --- a/contentprovider.go +++ b/contentprovider.go @@ -454,6 +454,18 @@ func (nls newlines) getLines(data []byte, low, high int) []byte { lowStart, _ := nls.lineBounds(low) _, highEnd := nls.lineBounds(high - 1) + // Drop any trailing newline. Editors do not treat a trailing newline as + // the start of a new line, so we should not either. lineBounds clamps to + // len(data) when an out-of-bounds line is requested. + // + // As an example, if we request lines 1-5 from a file with contents + // `one\ntwo\nthree\n`, we should return `one\ntwo\nthree` because those are + // the three "lines" in the file, separated by newlines. + if highEnd == uint32(len(data)) && bytes.HasSuffix(data, []byte{'\n'}) { + highEnd = highEnd - 1 + lowStart = min(lowStart, highEnd) + } + return data[lowStart:highEnd] } @@ -681,7 +693,6 @@ func sectionSlice(data []byte, sec DocumentSection) []byte { return data[sec.Start:sec.End] } - // scoreSymbolKind boosts a match based on the combination of language, symbol // and kind. The language string comes from go-enry, the symbol and kind from // ctags. diff --git a/contentprovider_test.go b/contentprovider_test.go index 59294495a..deb31b090 100644 --- a/contentprovider_test.go +++ b/contentprovider_test.go @@ -32,7 +32,8 @@ func TestGetLines(t *testing.T) { for _, content := range contents { t.Run("", func(t *testing.T) { newLines := getNewlines(content) - lines := bytes.Split(content, []byte{'\n'}) // TODO does split group consecutive sep? + // Trim the last newline before splitting because a trailing newline does not constitute a new line + lines := bytes.Split(bytes.TrimSuffix(content, []byte{'\n'}), []byte{'\n'}) wantGetLines := func(low, high int) []byte { low-- high-- diff --git a/web/e2e_test.go b/web/e2e_test.go index be00b61d6..01ca5999c 100644 --- a/web/e2e_test.go +++ b/web/e2e_test.go @@ -560,7 +560,10 @@ func TestContextLines(t *testing.T) { // Returns 3 instead of 4 new line characters since we swallow // the last new line in Before, Fragments and After. Before: "\n\n\n", - After: "\n\n\n", + // Returns 2 instead of 3 new line characters since a + // trailing newline at the end of the file does not + // constitue a new line. + After: "\n\n", }, }, },