Skip to content

Commit

Permalink
Create a new parser for every shard
Browse files Browse the repository at this point in the history
  • Loading branch information
jtibshirani committed Nov 21, 2023
1 parent 6863a52 commit 85d2caf
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 39 deletions.
7 changes: 2 additions & 5 deletions build/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -564,14 +564,11 @@ func NewBuilder(opts Options) (*Builder, error) {
}

parserFactory, err := ctags.NewParserFactory(
ctags.ParserBinMap{
ctags.UniversalCTags: b.opts.CTagsPath,
ctags.ScipCTags: b.opts.ScipCTagsPath,
},
b.opts.CTagsPath,
b.opts.ScipCTagsPath,
opts.LanguageMap,
b.opts.CTagsMustSucceed,
)

if err != nil {
return nil, err
}
Expand Down
14 changes: 11 additions & 3 deletions build/ctags.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ func parseSymbols(todo []*zoekt.Document, languageMap ctags.LanguageMap, parserF

var tagsToSections tagsToSections

parsers := make(map[ctags.CTagsParserType]ctags.Parser)

for _, doc := range todo {
if len(doc.Content) == 0 || doc.Symbols != nil {
continue
Expand All @@ -65,10 +67,16 @@ func parseSymbols(todo []*zoekt.Document, languageMap ctags.LanguageMap, parserF
parserKind = ctags.UniversalCTags
}

parser := parserFactory[parserKind]
parser := parsers[parserKind]
if parser == nil {
// this happens if CTagsMustSucceed is false and we didn't find the binary
continue
// Spin up a new parser for this parser kind
parser = parserFactory.NewParser(parserKind)
if parser == nil {
// this happens if CTagsMustSucceed is false and we didn't find the binary
continue
}
parsers[parserKind] = parser
defer parser.Close()
}

monitor.BeginParsing(doc)
Expand Down
11 changes: 9 additions & 2 deletions build/ctags_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -257,15 +257,22 @@ func BenchmarkTagsToSections(b *testing.B) {
requireCTags(b)

file, err := os.ReadFile("./testdata/large_file.cc")
parser := ctags.NewParser("universal-ctags")
if err != nil {
b.Fatal(err)
}

var tagsToSections tagsToSections
factory, err := ctags.NewParserFactory("universal-ctags", "", ctags.LanguageMap{}, true)
if err != nil {
b.Fatal(err)
}

parser := factory.NewParser(ctags.UniversalCTags)
entries, err := parser.Parse("./testdata/large_file.cc", file)
if err != nil {
b.Fatal(err)
}

var tagsToSections tagsToSections
secs, _, err := tagsToSections.Convert(file, entries)
if err != nil {
b.Fatal(err)
Expand Down
15 changes: 0 additions & 15 deletions ctags/json.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ package ctags

import (
"fmt"
"log"
"os"
"sync"
"time"

Expand Down Expand Up @@ -115,16 +113,3 @@ func (lp *lockedParser) close() {
lp.send = nil
lp.recv = nil
}

// NewParser creates a parser that is implemented by the given
// universal-ctags binary. The parser is safe for concurrent use.
func NewParser(bin string) Parser {
opts := goctags.Options{
Bin: bin,
}
if debug {
opts.Info = log.New(os.Stderr, "CTAGS INF: ", log.LstdFlags)
opts.Debug = log.New(os.Stderr, "CTAGS DBG: ", log.LstdFlags)
}
return &lockedParser{opts: opts,}
}
7 changes: 6 additions & 1 deletion ctags/json_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,12 @@ func TestJSON(t *testing.T) {
t.Skip(err)
}

p := NewParser("universal-ctags")
factory, err := NewParserFactory("universal-ctags", "", LanguageMap{}, true)
if err != nil {
t.Fatal(err)
}

p := factory.NewParser(UniversalCTags)
defer p.Close()

java := `
Expand Down
46 changes: 33 additions & 13 deletions ctags/parser_map.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,12 @@ package ctags
import (
"bytes"
"fmt"
"log"
"os"
"os/exec"
"strings"

goctags "github.com/sourcegraph/go-ctags"
)

type CTagsParserType uint8
Expand Down Expand Up @@ -60,34 +64,34 @@ func StringToParser(str string) CTagsParserType {
}
}

type ParserFactory map[CTagsParserType]Parser
type ParserBinMap map[CTagsParserType]string

func NewParserFactory(bins ParserBinMap, languageMap LanguageMap, cTagsMustSucceed bool) (ParserFactory, error) {
parsers := make(ParserFactory)
type ParserFactory map[CTagsParserType]string

requiredTypes := []CTagsParserType{UniversalCTags}
func NewParserFactory(
ctagsPath string,
scipCTagsPath string,
languageMap LanguageMap,
cTagsMustSucceed bool,
) (ParserFactory, error) {
validBins := make(map[CTagsParserType]string)
requiredBins := map[CTagsParserType]string{UniversalCTags: ctagsPath}
for _, parserType := range languageMap {
if parserType == ScipCTags {
requiredTypes = append(requiredTypes, ScipCTags)
requiredBins[ScipCTags] = scipCTagsPath
break
}
}

for _, parserType := range requiredTypes {
bin := bins[parserType]
for parserType, bin := range requiredBins {
if bin == "" && cTagsMustSucceed {
return nil, fmt.Errorf("ctags binary not found for %s parser type", ParserToString(parserType))
}

if err := checkBinary(parserType, bin); err != nil && cTagsMustSucceed {
return nil, fmt.Errorf("ctags.NewParserFactory: %v", err)
}

parsers[parserType] = NewParser(bin)
validBins[parserType] = bin
}

return parsers, nil
return validBins, nil
}

// checkBinary does checks on bin to ensure we can correctly use the binary
Expand All @@ -111,3 +115,19 @@ func checkBinary(typ CTagsParserType, bin string) error {

return nil
}

// NewParser creates a parser that is implemented by the given
// ctags binary. The parser is safe for concurrent use.
func (p ParserFactory) NewParser(typ CTagsParserType) Parser {
bin := p[typ]
if bin == "" {
return nil
}

opts := goctags.Options{Bin: bin}
if debug {
opts.Info = log.New(os.Stderr, "CTAGS INF: ", log.LstdFlags)
opts.Debug = log.New(os.Stderr, "CTAGS DBG: ", log.LstdFlags)
}
return &lockedParser{opts: opts}
}

0 comments on commit 85d2caf

Please sign in to comment.