fork of https://github.com/sourcegraph/zoekt
0

Configure Feed

Select the types of activity you want to include in your feed.

build: ignore out of bound lines from ctags (#694)

universal-ctags sometimes returns lines that are out of bounds. In
practice it seems to only do an off by one. We haven't noticed the
linenum error until a recent change of mine which didn't append an extra
entry to NLS if the file was terminated by "\n". In practice this would
end up being filtered out later on. So we update to just continue rather
than error here.

An example is
https://github.com/sourcegraph/sourcegraph/blob/v5.2.2/client/web-sveltekit/.storybook/main.ts

$ universal-ctags '--fields=*' --output-format=json main.ts | grep 22
{"_type": "tag", "name": "config", "path": "main.ts", "pattern": "/^export default config$/", "language": "TypeScript", "line": 22, "kind": "constant", "roles": "def"}

$ wc -l main.ts
21 main.ts

$ tail -n1 main.ts
export default config

Test Plan: added a unit test

+55 -25
+2 -1
build/ctags.go
··· 134 134 } 135 135 lineIdx := t.Line - 1 136 136 if lineIdx >= len(nls) { 137 - return nil, nil, fmt.Errorf("linenum for entry out of range %v", t) 137 + // Observed this with a .TS file. 138 + continue 138 139 } 139 140 140 141 lineOff := uint32(0)
+44 -9
build/ctags_test.go
··· 116 116 Name: "bar", 117 117 Line: 2, 118 118 }, 119 - } 119 + 120 + // We have seen ctags do this on a JS file 121 + { 122 + Name: "wat", 123 + Line: -1, 124 + }, 120 125 121 - secs, _, err := (&tagsToSections{}).Convert(c, tags) 122 - if err != nil { 123 - t.Fatal("tagsToSections", err) 126 + // We have seen ctags return out of bounds lines 127 + { 128 + Name: "goliath", 129 + Line: 3, 130 + }, 124 131 } 125 132 126 - if len(secs) != 1 || secs[0].Start != 17 || secs[0].End != 20 { 127 - t.Fatalf("got %#v, want 1 section (17,20)", secs) 133 + // We run this test twice. Once with a final \n and without. 134 + do := func(t *testing.T, doc []byte) { 135 + secs, _, err := (&tagsToSections{}).Convert(doc, tags) 136 + if err != nil { 137 + t.Fatal("tagsToSections", err) 138 + } 139 + 140 + if len(secs) != 1 || secs[0].Start != 17 || secs[0].End != 20 { 141 + t.Fatalf("got %#v, want 1 section (17,20)", secs) 142 + } 128 143 } 144 + 145 + t.Run("no final newline", func(t *testing.T) { 146 + do(t, c) 147 + }) 148 + t.Run("trailing newline", func(t *testing.T) { 149 + do(t, append(c, '\n')) 150 + }) 129 151 } 130 152 131 153 func TestOverlaps(t *testing.T) { ··· 232 254 } 233 255 234 256 func BenchmarkTagsToSections(b *testing.B) { 235 - if checkCTags() == "" { 236 - b.Skip("ctags not available") 237 - } 257 + requireCTags(b) 238 258 239 259 file, err := os.ReadFile("./testdata/large_file.cc") 240 260 parser, err := ctags.NewParser(ctags.UniversalCTags, "universal-ctags") ··· 268 288 } 269 289 } 270 290 } 291 + 292 + func requireCTags(tb testing.TB) { 293 + tb.Helper() 294 + 295 + if checkCTags() != "" { 296 + return 297 + } 298 + 299 + // On CI we require ctags to be available. Otherwise we skip 300 + if os.Getenv("CI") != "" { 301 + tb.Fatal("universal-ctags is missing") 302 + } else { 303 + tb.Skip("universal-ctags is missing") 304 + } 305 + }
+9 -15
build/scoring_test.go
··· 27 27 ) 28 28 29 29 type scoreCase struct { 30 - fileName string 31 - content []byte 30 + fileName string 31 + content []byte 32 32 query query.Q 33 33 language string 34 34 wantScore float64 ··· 58 58 wantScore: 510, 59 59 }, 60 60 } 61 - 61 + 62 62 for _, c := range cases { 63 63 checkScoring(t, c, ctags.UniversalCTags) 64 64 } ··· 165 165 } 166 166 167 167 for _, c := range cases { 168 - checkScoring(t, c, ctags.UniversalCTags) 168 + checkScoring(t, c, ctags.UniversalCTags) 169 169 } 170 170 } 171 171 ··· 174 174 if err != nil { 175 175 t.Fatal(err) 176 176 } 177 - 177 + 178 178 cases := []scoreCase{ 179 179 { 180 180 fileName: "example.kt", ··· 239 239 if err != nil { 240 240 t.Fatal(err) 241 241 } 242 - 242 + 243 243 cases := []scoreCase{ 244 244 { 245 245 fileName: "example.cc", ··· 489 489 490 490 switch parserType { 491 491 case ctags.UniversalCTags: 492 - if checkCTags() == "" { 493 - t.Skip("ctags not available") 494 - } 492 + requireCTags(t) 495 493 case ctags.ScipCTags: 496 494 if checkScipCTags() == "" { 497 495 t.Skip("scip-ctags not available") ··· 560 558 } 561 559 562 560 func TestDocumentRanks(t *testing.T) { 563 - if os.Getenv("CI") == "" && checkCTags() == "" { 564 - t.Skip("ctags not available") 565 - } 561 + requireCTags(t) 566 562 dir := t.TempDir() 567 563 568 564 opts := Options{ ··· 649 645 } 650 646 651 647 func TestRepoRanks(t *testing.T) { 652 - if os.Getenv("CI") == "" && checkCTags() == "" { 653 - t.Skip("ctags not available") 654 - } 648 + requireCTags(t) 655 649 dir := t.TempDir() 656 650 657 651 opts := Options{