github.com/dvyukov/gometalinter@v2.0.12-0.20181028185006-9777a28a8438+incompatible/aggregate.go (about)

     1  package main
     2  
     3  import (
     4  	"sort"
     5  	"strings"
     6  )
     7  
     8  type issueKey struct {
     9  	path      string
    10  	line, col int
    11  	message   string
    12  }
    13  
    14  type multiIssue struct {
    15  	*Issue
    16  	linterNames []string
    17  }
    18  
    19  // AggregateIssueChan reads issues from a channel, aggregates issues which have
    20  // the same file, line, vol, and message, and returns aggregated issues on
    21  // a new channel.
    22  func AggregateIssueChan(issues chan *Issue) chan *Issue {
    23  	out := make(chan *Issue, 1000000)
    24  	issueMap := make(map[issueKey]*multiIssue)
    25  	go func() {
    26  		for issue := range issues {
    27  			key := issueKey{
    28  				path:    issue.Path.String(),
    29  				line:    issue.Line,
    30  				col:     issue.Col,
    31  				message: issue.Message,
    32  			}
    33  			if existing, ok := issueMap[key]; ok {
    34  				existing.linterNames = append(existing.linterNames, issue.Linter)
    35  			} else {
    36  				issueMap[key] = &multiIssue{
    37  					Issue:       issue,
    38  					linterNames: []string{issue.Linter},
    39  				}
    40  			}
    41  		}
    42  		for _, multi := range issueMap {
    43  			issue := multi.Issue
    44  			sort.Strings(multi.linterNames)
    45  			issue.Linter = strings.Join(multi.linterNames, ", ")
    46  			out <- issue
    47  		}
    48  		close(out)
    49  	}()
    50  	return out
    51  }