pkgsrc-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[pkgsrc/trunk]: pkgsrc/pkgtools/pkglint pkgtools/pkglint: update to 5.5.15



details:   https://anonhg.NetBSD.org/pkgsrc/rev/27e1e4256c67
branches:  trunk
changeset: 310975:27e1e4256c67
user:      rillig <rillig%pkgsrc.org@localhost>
date:      Sat Jul 28 18:31:23 2018 +0000

description:
pkgtools/pkglint: update to 5.5.15

Changes since 5.5.14:

* Check that the comments in .endif and .endfor lines match the
  corresponding conditions.

* Check for redundant variables (e.g. MASTER_SITES for R packages).

* Check for accidentally overwritten variables.

* Miscellaneous code cleanup and refactoring.

diffstat:

 pkgtools/pkglint/Makefile                   |    4 +-
 pkgtools/pkglint/files/check_test.go        |    8 +-
 pkgtools/pkglint/files/mkline.go            |  190 +++++++++++++++++++++------
 pkgtools/pkglint/files/mkline_test.go       |   16 +-
 pkgtools/pkglint/files/mklinechecker.go     |   47 ++++--
 pkgtools/pkglint/files/mklines.go           |   81 ++++++++++-
 pkgtools/pkglint/files/mklines_test.go      |   71 ++++++++++-
 pkgtools/pkglint/files/mkparser.go          |    2 +
 pkgtools/pkglint/files/mkparser_test.go     |    2 +
 pkgtools/pkglint/files/package.go           |   36 +---
 pkgtools/pkglint/files/package_test.go      |   45 ++++++-
 pkgtools/pkglint/files/patches.go           |   17 +-
 pkgtools/pkglint/files/patches_test.go      |   64 +++++++-
 pkgtools/pkglint/files/pkgsrc.go            |    2 +-
 pkgtools/pkglint/files/shell_test.go        |   30 +++-
 pkgtools/pkglint/files/util.go              |   80 +++++++++++
 pkgtools/pkglint/files/vartypecheck.go      |   16 +-
 pkgtools/pkglint/files/vartypecheck_test.go |   11 +-
 18 files changed, 583 insertions(+), 139 deletions(-)

diffs (truncated from 1330 to 300 lines):

diff -r 71b99d4b818b -r 27e1e4256c67 pkgtools/pkglint/Makefile
--- a/pkgtools/pkglint/Makefile Sat Jul 28 18:29:38 2018 +0000
+++ b/pkgtools/pkglint/Makefile Sat Jul 28 18:31:23 2018 +0000
@@ -1,6 +1,6 @@
-# $NetBSD: Makefile,v 1.542 2018/07/19 06:38:15 rillig Exp $
+# $NetBSD: Makefile,v 1.543 2018/07/28 18:31:23 rillig Exp $
 
-PKGNAME=       pkglint-5.5.14
+PKGNAME=       pkglint-5.5.15
 DISTFILES=     # none
 CATEGORIES=    pkgtools
 
diff -r 71b99d4b818b -r 27e1e4256c67 pkgtools/pkglint/files/check_test.go
--- a/pkgtools/pkglint/files/check_test.go      Sat Jul 28 18:29:38 2018 +0000
+++ b/pkgtools/pkglint/files/check_test.go      Sat Jul 28 18:31:23 2018 +0000
@@ -3,6 +3,7 @@
 import (
        "bytes"
        "fmt"
+       "io"
        "io/ioutil"
        "os"
        "path"
@@ -296,11 +297,12 @@
        t.c().Check(emptyToNil(actualLines), deepEquals, emptyToNil(expectedLines))
 }
 
-// EnableTracing redirects all logging output to stdout instead of
-// the buffer. This is useful when stepping through the code, especially
+// EnableTracing redirects all logging output (which is normally captured
+// in an in-memory buffer) additionally to stdout.
+// This is useful when stepping through the code, especially
 // in combination with SetupCommandLine("--debug").
 func (t *Tester) EnableTracing() {
-       G.logOut = NewSeparatorWriter(os.Stdout)
+       G.logOut = NewSeparatorWriter(io.MultiWriter(os.Stdout, &t.stdout))
        trace.Out = os.Stdout
        trace.Tracing = true
 }
diff -r 71b99d4b818b -r 27e1e4256c67 pkgtools/pkglint/files/mkline.go
--- a/pkgtools/pkglint/files/mkline.go  Sat Jul 28 18:29:38 2018 +0000
+++ b/pkgtools/pkglint/files/mkline.go  Sat Jul 28 18:31:23 2018 +0000
@@ -38,6 +38,7 @@
        indent    string
        directive string
        args      string
+       comment   string
 }
 type mkLineInclude struct {
        mustExist     bool
@@ -112,8 +113,8 @@
                return &MkLineImpl{line, mkLineEmpty{}}
        }
 
-       if m, indent, directive, args := matchMkCond(text); m {
-               return &MkLineImpl{line, mkLineConditional{indent, directive, args}}
+       if m, indent, directive, args, comment := matchMkCond(text); m {
+               return &MkLineImpl{line, mkLineConditional{indent, directive, args, comment}}
        }
 
        if m, indent, directive, includefile := MatchMkInclude(text); m {
@@ -217,7 +218,8 @@
 // Op applies to variable assignments and returns the assignment operator.
 func (mkline *MkLineImpl) Op() MkOperator { return mkline.data.(mkLineAssign).op }
 
-// For a variable assignment, the text up to and including the assignment operator, e.g. VARNAME+=\t
+// ValueAlign applies to variable assignments and returns all the text
+// before the variable value, e.g. "VARNAME+=\t".
 func (mkline *MkLineImpl) ValueAlign() string { return mkline.data.(mkLineAssign).valueAlign }
 func (mkline *MkLineImpl) Value() string      { return mkline.data.(mkLineAssign).value }
 
@@ -235,14 +237,25 @@
                return mkline.data.(mkLineInclude).indent
        }
 }
-func (mkline *MkLineImpl) Directive() string   { return mkline.data.(mkLineConditional).directive }
-func (mkline *MkLineImpl) Args() string        { return mkline.data.(mkLineConditional).args }
+
+// Directive returns one of "if", "ifdef", "ifndef", "else", "elif", "endif", "for", "endfor", "undef".
+//
+// See matchMkCond.
+func (mkline *MkLineImpl) Directive() string { return mkline.data.(mkLineConditional).directive }
+func (mkline *MkLineImpl) Args() string      { return mkline.data.(mkLineConditional).args }
+
+// CondComment is the trailing end-of-line comment, typically at a deeply nested .endif or .endfor.
+func (mkline *MkLineImpl) CondComment() string { return mkline.data.(mkLineConditional).comment }
+
 func (mkline *MkLineImpl) MustExist() bool     { return mkline.data.(mkLineInclude).mustExist }
 func (mkline *MkLineImpl) IncludeFile() string { return mkline.data.(mkLineInclude).includeFile }
-func (mkline *MkLineImpl) Targets() string     { return mkline.data.(mkLineDependency).targets }
-func (mkline *MkLineImpl) Sources() string     { return mkline.data.(mkLineDependency).sources }
+
+func (mkline *MkLineImpl) Targets() string { return mkline.data.(mkLineDependency).targets }
+func (mkline *MkLineImpl) Sources() string { return mkline.data.(mkLineDependency).sources }
 
-// Initialized step by step, when parsing other lines
+// ConditionVars is a space-separated list of those variable names
+// on which the inclusion depends. It is initialized later,
+// step by step, when parsing other lines
 func (mkline *MkLineImpl) ConditionVars() string { return mkline.data.(mkLineInclude).conditionVars }
 func (mkline *MkLineImpl) SetConditionVars(varnames string) {
        include := mkline.data.(mkLineInclude)
@@ -340,7 +353,7 @@
                "main pkgsrc repository.")
 }
 
-func matchMkCond(text string) (m bool, indent, directive, args string) {
+func matchMkCond(text string) (m bool, indent, directive, args, comment string) {
        i, n := 0, len(text)
        if i < n && text[i] == '.' {
                i++
@@ -375,6 +388,13 @@
        for i < n && (text[i] != '#' || text[i-1] == '\\') {
                i++
        }
+       commentStart := i
+       if commentStart < n {
+               commentStart++
+               for commentStart < n && (text[commentStart] == ' ' || text[commentStart] == '\t') {
+                       commentStart++
+               }
+       }
        for i > argsStart && (text[i-1] == ' ' || text[i-1] == '\t') {
                i--
        }
@@ -383,6 +403,7 @@
        m = true
        indent = text[indentStart:indentEnd]
        args = strings.Replace(text[argsStart:argsEnd], "\\#", "#", -1)
+       comment = text[commentStart:]
        return
 }
 
@@ -728,57 +749,66 @@
 // An excepting are multiple-inclusion guards, they don't increase the
 // indentation.
 type Indentation struct {
-       depth         []int      // Number of space characters; always a multiple of 2
-       conditionVars [][]string // Variables on which the current path depends
+       levels []indentationLevel
+}
+
+func NewIndentation() *Indentation {
+       ind := &Indentation{}
+       ind.Push(0, "") // Dummy
+       return ind
+}
+
+type indentationLevel struct {
+       depth         int      // Number of space characters; always a multiple of 2
+       condition     string   // The corresponding condition from the .if or .elif
+       conditionVars []string // Variables on which the current path depends
 
        // Files whose existence has been checked in a related path.
        // The check counts for both the "if" and the "else" branch,
        // but that sloppiness will be discovered by functional tests.
-       checkedFiles [][]string
+       checkedFiles []string
 }
 
 func (ind *Indentation) Len() int {
-       return len(ind.depth)
+       return len(ind.levels)
 }
 
+func (ind *Indentation) top() *indentationLevel {
+       return &ind.levels[ind.Len()-1]
+}
+
+// Depth returns the number of space characters by which the directive
+// should be indented.
 func (ind *Indentation) Depth(directive string) int {
        switch directive {
-       case "elif", "else", "endfor", "endif":
-               return ind.depth[imax(0, len(ind.depth)-2)]
+       case "if", "elif", "else", "endfor", "endif":
+               return ind.levels[imax(0, ind.Len()-2)].depth
        }
-       return ind.depth[len(ind.depth)-1]
+       return ind.top().depth
 }
 
 func (ind *Indentation) Pop() {
-       newlen := ind.Len() - 1
-       ind.depth = ind.depth[:newlen]
-       ind.conditionVars = ind.conditionVars[:newlen]
-       ind.checkedFiles = ind.checkedFiles[:newlen]
+       ind.levels = ind.levels[:ind.Len()-1]
 }
 
-func (ind *Indentation) Push(indent int) {
-       ind.depth = append(ind.depth, indent)
-       ind.conditionVars = append(ind.conditionVars, nil)
-       ind.checkedFiles = append(ind.checkedFiles, nil)
+func (ind *Indentation) Push(indent int, condition string) {
+       ind.levels = append(ind.levels, indentationLevel{indent, condition, nil, nil})
 }
 
 func (ind *Indentation) AddVar(varname string) {
-       level := ind.Len() - 1
-       if hasSuffix(varname, "_MK") {
-               return
-       }
-       for _, existingVarname := range ind.conditionVars[level] {
+       vars := &ind.top().conditionVars
+       for _, existingVarname := range *vars {
                if varname == existingVarname {
                        return
                }
        }
 
-       ind.conditionVars[level] = append(ind.conditionVars[level], varname)
+       *vars = append(*vars, varname)
 }
 
 func (ind *Indentation) DependsOn(varname string) bool {
-       for _, levelVarnames := range ind.conditionVars {
-               for _, levelVarname := range levelVarnames {
+       for _, level := range ind.levels {
+               for _, levelVarname := range level.conditionVars {
                        if varname == levelVarname {
                                return true
                        }
@@ -788,34 +818,46 @@
 }
 
 func (ind *Indentation) IsConditional() bool {
-       for _, vars := range ind.conditionVars {
-               if len(vars) > 0 {
-                       return true
+       for _, level := range ind.levels {
+               for _, varname := range level.conditionVars {
+                       if !hasSuffix(varname, "_MK") {
+                               return true
+                       }
                }
        }
        return false
 }
 
+// Varnames returns the list of all variables that are mentioned in any
+// condition or loop surrounding the current line.
+// Variables named *_MK are excluded since they are usually not interesting.
 func (ind *Indentation) Varnames() string {
        sep := ""
        varnames := ""
-       for _, levelVarnames := range ind.conditionVars {
-               for _, levelVarname := range levelVarnames {
-                       varnames += sep + levelVarname
-                       sep = ", "
+       for _, level := range ind.levels {
+               for _, levelVarname := range level.conditionVars {
+                       if !hasSuffix(levelVarname, "_MK") {
+                               varnames += sep + levelVarname
+                               sep = ", "
+                       }
                }
        }
        return varnames
 }
 
+// Condition returns the condition for the innermost .if, .elif or .for.
+func (ind *Indentation) Condition() string {
+       return ind.top().condition
+}
+
 func (ind *Indentation) AddCheckedFile(filename string) {
-       level := ind.Len() - 1
-       ind.checkedFiles[level] = append(ind.checkedFiles[level], filename)
+       top := ind.top()
+       top.checkedFiles = append(top.checkedFiles, filename)
 }
 
 func (ind *Indentation) IsCheckedFile(filename string) bool {
-       for _, levelFilenames := range ind.checkedFiles {
-               for _, levelFilename := range levelFilenames {
+       for _, level := range ind.levels {
+               for _, levelFilename := range level.checkedFiles {
                        if filename == levelFilename {
                                return true
                        }
@@ -824,6 +866,68 @@
        return false
 }
 
+func (ind *Indentation) TrackBefore(mkline MkLine) {
+       if !mkline.IsCond() {
+               return
+       }
+       if trace.Tracing {
+               trace.Stepf("Indentation before line %s: %+v", mkline.Linenos(), ind.levels)
+       }
+
+       directive := mkline.Directive()
+       args := mkline.Args()
+
+       switch directive {
+       case "for", "if", "ifdef", "ifndef":
+               ind.Push(ind.top().depth, args)
+       }



Home | Main Index | Thread Index | Old Index