github.com/alexey-mercari/reviewdog@v0.10.1-0.20200514053941-928943b10766/filter.go (about)

     1  package reviewdog
     2  
     3  import (
     4  	"path/filepath"
     5  
     6  	"github.com/reviewdog/reviewdog/diff"
     7  	"github.com/reviewdog/reviewdog/difffilter"
     8  )
     9  
    10  // FilteredCheck represents CheckResult with filtering info.
    11  type FilteredCheck struct {
    12  	*CheckResult
    13  	ShouldReport bool
    14  	LnumDiff     int  // 0 if the result is outside diff.
    15  	InDiffFile   bool // false if the result is outside diff files.
    16  	OldPath      string
    17  	OldLine      int
    18  }
    19  
    20  // FilterCheck filters check results by diff. It doesn't drop check which
    21  // is not in diff but set FilteredCheck.ShouldReport field false.
    22  func FilterCheck(results []*CheckResult, diff []*diff.FileDiff, strip int,
    23  	cwd string, mode difffilter.Mode) []*FilteredCheck {
    24  	checks := make([]*FilteredCheck, 0, len(results))
    25  	df := difffilter.New(diff, strip, cwd, mode)
    26  	for _, result := range results {
    27  		check := &FilteredCheck{CheckResult: result}
    28  		shouldReport, difffile, diffline := df.ShouldReport(result.Path, result.Lnum)
    29  		check.ShouldReport = shouldReport
    30  		if diffline != nil {
    31  			check.LnumDiff = diffline.LnumDiff
    32  		}
    33  		result.Path = CleanPath(result.Path, cwd)
    34  		if difffile != nil {
    35  			check.InDiffFile = true
    36  			check.OldPath, check.OldLine = getOldPosition(difffile, strip, result.Path, result.Lnum)
    37  		}
    38  		checks = append(checks, check)
    39  	}
    40  	return checks
    41  }
    42  
    43  // CleanPath clean up given path. If workdir is not empty, it returns relative
    44  // path to the given workdir.
    45  func CleanPath(path, workdir string) string {
    46  	p := path
    47  	if filepath.IsAbs(path) && workdir != "" {
    48  		relPath, err := filepath.Rel(workdir, path)
    49  		if err == nil {
    50  			p = relPath
    51  		}
    52  	}
    53  	p = filepath.Clean(p)
    54  	if p == "." {
    55  		return ""
    56  	}
    57  	return filepath.ToSlash(p)
    58  }
    59  
    60  func getOldPosition(filediff *diff.FileDiff, strip int, newPath string, newLine int) (oldPath string, oldLine int) {
    61  	if filediff == nil {
    62  		return "", 0
    63  	}
    64  	if difffilter.NormalizeDiffPath(filediff.PathNew, strip) != newPath {
    65  		return "", 0
    66  	}
    67  	oldPath = difffilter.NormalizeDiffPath(filediff.PathOld, strip)
    68  	delta := 0
    69  	for _, hunk := range filediff.Hunks {
    70  		if newLine < hunk.StartLineNew {
    71  			break
    72  		}
    73  		delta += hunk.LineLengthOld - hunk.LineLengthNew
    74  		for _, line := range hunk.Lines {
    75  			if line.LnumNew == newLine {
    76  				return oldPath, line.LnumOld
    77  			}
    78  		}
    79  	}
    80  	return oldPath, newLine + delta
    81  }