| | |
| | |
| | |
| |
|
| | package main |
| |
|
| | |
| | |
| |
|
| | import ( |
| | "flag" |
| | "fmt" |
| | "internal/coverage" |
| | "internal/coverage/decodecounter" |
| | "internal/coverage/decodemeta" |
| | "internal/coverage/pods" |
| | "os" |
| | "strings" |
| | ) |
| |
|
| | |
| | |
| | func makeSubtractIntersectOp(mode string) covOperation { |
| | outdirflag = flag.String("o", "", "Output directory to write") |
| | s := &sstate{ |
| | mode: mode, |
| | mm: newMetaMerge(), |
| | inidx: -1, |
| | } |
| | return s |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | type sstate struct { |
| | mm *metaMerge |
| | inidx int |
| | mode string |
| | |
| | |
| | |
| | imm map[pkfunc]struct{} |
| | } |
| |
|
| | func (s *sstate) Usage(msg string) { |
| | if len(msg) > 0 { |
| | fmt.Fprintf(os.Stderr, "error: %s\n", msg) |
| | } |
| | fmt.Fprintf(os.Stderr, "usage: go tool covdata %s -i=dir1,dir2 -o=<dir>\n\n", s.mode) |
| | flag.PrintDefaults() |
| | fmt.Fprintf(os.Stderr, "\nExamples:\n\n") |
| | op := "from" |
| | if s.mode == intersectMode { |
| | op = "with" |
| | } |
| | fmt.Fprintf(os.Stderr, " go tool covdata %s -i=dir1,dir2 -o=outdir\n\n", s.mode) |
| | fmt.Fprintf(os.Stderr, " \t%ss dir2 %s dir1, writing result\n", s.mode, op) |
| | fmt.Fprintf(os.Stderr, " \tinto output dir outdir.\n") |
| | os.Exit(2) |
| | } |
| |
|
| | func (s *sstate) Setup() { |
| | if *indirsflag == "" { |
| | usage("select input directories with '-i' option") |
| | } |
| | indirs := strings.Split(*indirsflag, ",") |
| | if s.mode == subtractMode && len(indirs) != 2 { |
| | usage("supply exactly two input dirs for subtract operation") |
| | } |
| | if *outdirflag == "" { |
| | usage("select output directory with '-o' option") |
| | } |
| | } |
| |
|
| | func (s *sstate) BeginPod(p pods.Pod) { |
| | s.mm.beginPod() |
| | } |
| |
|
| | func (s *sstate) EndPod(p pods.Pod) { |
| | const pcombine = false |
| | s.mm.endPod(pcombine) |
| | } |
| |
|
| | func (s *sstate) EndCounters() { |
| | if s.imm != nil { |
| | s.pruneCounters() |
| | } |
| | } |
| |
|
| | |
| | |
| | |
| | func (s *sstate) pruneCounters() { |
| | pkeys := make([]pkfunc, 0, len(s.mm.pod.pmm)) |
| | for k := range s.mm.pod.pmm { |
| | pkeys = append(pkeys, k) |
| | } |
| | |
| | |
| | |
| | for _, k := range pkeys { |
| | if _, found := s.imm[k]; !found { |
| | delete(s.mm.pod.pmm, k) |
| | } |
| | } |
| | s.imm = nil |
| | } |
| |
|
| | func (s *sstate) BeginCounterDataFile(cdf string, cdr *decodecounter.CounterDataReader, dirIdx int) { |
| | dbgtrace(2, "visiting counter data file %s diridx %d", cdf, dirIdx) |
| | if s.inidx != dirIdx { |
| | if s.inidx > dirIdx { |
| | |
| | |
| | |
| | panic("decreasing dir index, internal error") |
| | } |
| | if dirIdx == 0 { |
| | |
| | |
| | |
| | s.imm = nil |
| | } else { |
| | |
| | if s.mode == intersectMode { |
| | if s.imm != nil { |
| | s.pruneCounters() |
| | } |
| | s.imm = make(map[pkfunc]struct{}) |
| | } |
| | } |
| | s.inidx = dirIdx |
| | } |
| | } |
| |
|
| | func (s *sstate) EndCounterDataFile(cdf string, cdr *decodecounter.CounterDataReader, dirIdx int) { |
| | } |
| |
|
| | func (s *sstate) VisitFuncCounterData(data decodecounter.FuncPayload) { |
| | key := pkfunc{pk: data.PkgIdx, fcn: data.FuncIdx} |
| |
|
| | if *verbflag >= 5 { |
| | fmt.Printf("ctr visit fid=%d pk=%d inidx=%d data.Counters=%+v\n", data.FuncIdx, data.PkgIdx, s.inidx, data.Counters) |
| | } |
| |
|
| | |
| | |
| | |
| | if s.inidx == 0 { |
| | s.mm.visitFuncCounterData(data) |
| | return |
| | } |
| |
|
| | |
| | |
| | if val, ok := s.mm.pod.pmm[key]; ok { |
| | if s.mode == subtractMode { |
| | for i := 0; i < len(data.Counters); i++ { |
| | if data.Counters[i] != 0 { |
| | val.Counters[i] = 0 |
| | } |
| | } |
| | } else if s.mode == intersectMode { |
| | s.imm[key] = struct{}{} |
| | for i := 0; i < len(data.Counters); i++ { |
| | if data.Counters[i] == 0 { |
| | val.Counters[i] = 0 |
| | } |
| | } |
| | } |
| | } |
| | } |
| |
|
| | func (s *sstate) VisitMetaDataFile(mdf string, mfr *decodemeta.CoverageMetaFileReader) { |
| | if s.mode == intersectMode { |
| | s.imm = make(map[pkfunc]struct{}) |
| | } |
| | s.mm.visitMetaDataFile(mdf, mfr) |
| | } |
| |
|
| | func (s *sstate) BeginPackage(pd *decodemeta.CoverageMetaDataDecoder, pkgIdx uint32) { |
| | s.mm.visitPackage(pd, pkgIdx, false) |
| | } |
| |
|
| | func (s *sstate) EndPackage(pd *decodemeta.CoverageMetaDataDecoder, pkgIdx uint32) { |
| | } |
| |
|
| | func (s *sstate) VisitFunc(pkgIdx uint32, fnIdx uint32, fd *coverage.FuncDesc) { |
| | s.mm.visitFunc(pkgIdx, fnIdx, fd, s.mode, false) |
| | } |
| |
|
| | func (s *sstate) Finish() { |
| | } |
| |
|