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 22.3.1



details:   https://anonhg.NetBSD.org/pkgsrc/rev/1c9fc4906abe
branches:  trunk
changeset: 388411:1c9fc4906abe
user:      rillig <rillig%pkgsrc.org@localhost>
date:      Sat Nov 19 10:51:07 2022 +0000

description:
pkgtools/pkglint: Update to 22.3.1

Changes since 22.3.0:

In doc/CHANGES files, check for typos in month and day of the dates.

In conditions for YesNo variables, suggest to replace the modifier
':M[yY][eE][sS]' with a simpler comparison.

https://mail-index.netbsd.org/tech-pkg/2022/11/16/msg026992.html

diffstat:

 pkgtools/pkglint/Makefile                       |    9 +-
 pkgtools/pkglint/files/mkcondchecker_test.go    |    6 +-
 pkgtools/pkglint/files/mkcondsimplifier.go      |  115 +++-
 pkgtools/pkglint/files/mkcondsimplifier_test.go |  757 +++++++++++++----------
 pkgtools/pkglint/files/mktypes.go               |   25 +-
 pkgtools/pkglint/files/mktypes_test.go          |    4 +-
 pkgtools/pkglint/files/pkgsrc.go                |   71 +-
 pkgtools/pkglint/files/pkgsrc_test.go           |   40 +
 8 files changed, 644 insertions(+), 383 deletions(-)

diffs (truncated from 1352 to 300 lines):

diff -r 61cbe667533e -r 1c9fc4906abe pkgtools/pkglint/Makefile
--- a/pkgtools/pkglint/Makefile Sat Nov 19 10:43:21 2022 +0000
+++ b/pkgtools/pkglint/Makefile Sat Nov 19 10:51:07 2022 +0000
@@ -1,7 +1,6 @@
-# $NetBSD: Makefile,v 1.733 2022/11/02 19:39:53 bsiegert Exp $
+# $NetBSD: Makefile,v 1.734 2022/11/19 10:51:07 rillig Exp $
 
-PKGNAME=       pkglint-22.3.0
-PKGREVISION=   2
+PKGNAME=       pkglint-22.3.1
 CATEGORIES=    pkgtools
 
 MAINTAINER=    rillig%NetBSD.org@localhost
@@ -16,7 +15,7 @@
 
 SUBST_CLASSES+=                pkglint
 SUBST_STAGE.pkglint=   post-configure
-SUBST_FILES.pkglint+=  ${WRKSRC}/pkglint.go
+SUBST_FILES.pkglint+=  pkglint.go
 SUBST_SED.pkglint+=    -e s\|@VERSION@\|${PKGVERSION}\|g
 SUBST_SED.pkglint+=    -e s\|@BMAKE@\|${MAKE:T:Q}\|g
 
@@ -46,7 +45,7 @@
 PLIST_VARS+=           catinstall0 catinstall maninstall
 .if ${MANINSTALL:Mcatinstall}
 INSTALLATION_DIRS+=    man/cat1
-.  if ${CATMAN_SECTION_SUFFIX:M[Yy][Ee][Ss]}
+.  if ${CATMAN_SECTION_SUFFIX:U:tl} == yes
 PLIST.catinstall=      yes
 .  else
 PLIST.catinstall0=     yes
diff -r 61cbe667533e -r 1c9fc4906abe pkgtools/pkglint/files/mkcondchecker_test.go
--- a/pkgtools/pkglint/files/mkcondchecker_test.go      Sat Nov 19 10:43:21 2022 +0000
+++ b/pkgtools/pkglint/files/mkcondchecker_test.go      Sat Nov 19 10:51:07 2022 +0000
@@ -51,7 +51,11 @@
                "WARN: filename.mk:4: PKGSRC_RUN_TEST should be matched "+
                        "against \"[yY][eE][sS]\" or \"[nN][oO]\", not \"[Y][eE][sS]\".")
 
-       test(".if !empty(IS_BUILTIN.Xfixes:M[yY][eE][sS])")
+       test(".if !empty(IS_BUILTIN.Xfixes:M[yY][eE][sS])",
+               "NOTE: filename.mk:4: "+
+                       "\"!empty(IS_BUILTIN.Xfixes:M[yY][eE][sS])\" "+
+                       "can be simplified to "+
+                       "\"${IS_BUILTIN.Xfixes:U:tl} == yes\".")
 
        test(".if !empty(${IS_BUILTIN.Xfixes:M[yY][eE][sS]})",
                "WARN: filename.mk:4: The empty() function takes a variable name as parameter, "+
diff -r 61cbe667533e -r 1c9fc4906abe pkgtools/pkglint/files/mkcondsimplifier.go
--- a/pkgtools/pkglint/files/mkcondsimplifier.go        Sat Nov 19 10:43:21 2022 +0000
+++ b/pkgtools/pkglint/files/mkcondsimplifier.go        Sat Nov 19 10:51:07 2022 +0000
@@ -1,6 +1,9 @@
 package pkglint
 
-import "netbsd.org/pkglint/textproc"
+import (
+       "netbsd.org/pkglint/textproc"
+       "strings"
+)
 
 // MkCondSimplifier replaces unnecessarily complex conditions with simpler yet
 // equivalent conditions.
@@ -16,6 +19,9 @@
 //
 // * neg is true for the form !empty(VAR...), and false for empty(VAR...).
 func (s *MkCondSimplifier) SimplifyVarUse(varuse *MkVarUse, fromEmpty bool, neg bool) {
+       if s.simplifyYesNo(varuse, fromEmpty, neg) {
+               return
+       }
        s.simplifyMatch(varuse, fromEmpty, neg)
        s.simplifyWord(varuse, fromEmpty, neg)
 }
@@ -33,6 +39,9 @@
        }
        modsExceptLast := NewMkVarUse("", modifiers[:n-1]...).Mod()
        vartype := G.Pkgsrc.VariableType(s.MkLines, varname)
+       if vartype == nil || vartype.IsList() {
+               return
+       }
 
        // replace constructs the state before and after the autofix.
        // The before state is constructed to ensure that only very simple
@@ -82,12 +91,10 @@
        if !ok || !positive && n != 1 {
                return
        }
-
-       switch {
-       case !exact,
-               vartype == nil,
-               vartype.IsList(),
-               textproc.NewLexer(pattern).NextBytesSet(mkCondModifierPatternLiteral) != pattern:
+       if !exact {
+               return
+       }
+       if textproc.NewLexer(pattern).NextBytesSet(mkCondModifierPatternLiteral) != pattern {
                return
        }
 
@@ -112,6 +119,100 @@
        fix.Apply()
 }
 
+// simplifyYesNo replaces conditions of the form '${VAR:M[yY][eE][sS]}' with
+// the equivalent ${VAR:tl} == yes.
+func (s *MkCondSimplifier) simplifyYesNo(varuse *MkVarUse, fromEmpty bool, neg bool) (done bool) {
+
+       // TODO: Merge the common code from simplifyWord and simplifyYesNo.
+       //  Even better would be to manipulate the conditions in an AST
+       //  instead of working directly with strings, but as of November 2022,
+       //  that is not implemented yet.
+       //  .
+       //  Another useful feature would be to chain multiple autofixes
+       //  together, but to do that, pkglint needs to be able to convert an
+       //  AST back into the source code form.
+
+       toLower := func(p string) string {
+               var sb strings.Builder
+               upper := textproc.Upper
+               lower := textproc.Lower
+               for ; len(p) >= 4 && p[0] == '[' && p[3] == ']'; p = p[4:] {
+                       if upper.Contains(p[1]) && p[2] == p[1]-'A'+'a' {
+                               sb.WriteByte(p[2])
+                       } else if lower.Contains(p[1]) && p[2] == p[1]-'a'+'A' {
+                               sb.WriteByte(p[1])
+                       } else {
+                               return ""
+                       }
+               }
+               if p != "" {
+                       return ""
+               }
+               return sb.String()
+       }
+
+       varname := varuse.varname
+       modifiers := varuse.modifiers
+
+       n := len(modifiers)
+       if n == 0 {
+               return
+       }
+       modsExceptLast := NewMkVarUse("", modifiers[:n-1]...).Mod()
+       vartype := G.Pkgsrc.VariableType(s.MkLines, varname)
+       if vartype == nil || vartype.IsList() {
+               return
+       }
+
+       // replace constructs the state before and after the autofix.
+       replace := func(positive bool, pattern, lower string) (bool, string, string) {
+               defined := s.isDefined(varname, vartype)
+               if !defined && !positive {
+                       // Too many negations; maybe handle this case later.
+                       return false, "", ""
+               }
+               uMod := condStr(!defined && !varuse.HasModifier("U"), ":U", "")
+
+               op := condStr(neg == positive, "==", "!=")
+
+               from := sprintf("%s%s%s%s%s%s%s",
+                       condStr(neg != fromEmpty, "", "!"),
+                       condStr(fromEmpty, "empty(", "${"),
+                       varname,
+                       modsExceptLast,
+                       condStr(positive, ":M", ":N"),
+                       pattern,
+                       condStr(fromEmpty, ")", "}"))
+
+               to := sprintf(
+                       "${%s%s%s:tl} %s %s",
+                       varname, uMod, modsExceptLast, op, lower)
+
+               return true, from, to
+       }
+
+       modifier := modifiers[n-1]
+       ok, positive, pattern, exact := modifier.MatchMatch()
+       if !ok || !positive && n != 1 || exact {
+               return
+       }
+       lower := toLower(pattern)
+       if lower == "" {
+               return
+       }
+
+       ok, from, to := replace(positive, pattern, lower)
+       if !ok {
+               return
+       }
+
+       fix := s.MkLine.Autofix()
+       fix.Notef("\"%s\" can be simplified to \"%s\".", from, to)
+       fix.Replace(from, to)
+       fix.Apply()
+       return true
+}
+
 // simplifyMatch replaces:
 //  !empty(VAR:M*.c) with ${VAR:M*.c}
 //  empty(VAR:M*.c) with !${VAR:M*.c}
diff -r 61cbe667533e -r 1c9fc4906abe pkgtools/pkglint/files/mkcondsimplifier_test.go
--- a/pkgtools/pkglint/files/mkcondsimplifier_test.go   Sat Nov 19 10:43:21 2022 +0000
+++ b/pkgtools/pkglint/files/mkcondsimplifier_test.go   Sat Nov 19 10:51:07 2022 +0000
@@ -2,11 +2,21 @@
 
 import (
        "gopkg.in/check.v1"
+       "netbsd.org/pkglint/regex"
 )
 
 type MkCondSimplifierTester struct {
        c *check.C
        *Tester
+       allowedVariableNames regex.Pattern
+}
+
+func NewMkCondSimplifierTester(c *check.C, s *Suite) *MkCondSimplifierTester {
+       return &MkCondSimplifierTester{
+               c,
+               s.Init(c),
+               `IN_SCOPE|PREFS|LATER|UNDEFINED`,
+       }
 }
 
 func (t *MkCondSimplifierTester) setUp() {
@@ -37,6 +47,10 @@
        // Even when they are in scope, some variables such as PKGREVISION
        // or MAKE_JOBS may be undefined.
 
+       // TODO: Test list variables; they differ in that a ':M' modifier
+       //  cannot be replaced with '==', as the variable may contain
+       //  multiple words.
+
        t.SetUpVarType("IN_SCOPE_DEFINED", btAnything, AlwaysInScope|DefinedIfInScope,
                "*.mk: use, use-loadtime")
        t.SetUpVarType("IN_SCOPE", btAnything, AlwaysInScope,
@@ -69,8 +83,10 @@
 // before: the directive before the condition is simplified
 // after: the directive after the condition is simplified
 func (t *MkCondSimplifierTester) doTest(prefs bool, before, after string, diagnostics ...string) {
-       if !matches(before, `IN_SCOPE|PREFS|LATER|UNDEFINED`) {
-               t.c.Errorf("Condition %q must include one of the above variable names.", before)
+       if !matches(before, t.allowedVariableNames) {
+               // Prevent typos in the variable names used in the test.
+               t.c.Errorf("Condition %q must include one of the variable names %q.",
+                       before, t.allowedVariableNames)
        }
        mklines := t.SetUpFileMkLines("filename.mk",
                MkCvsID,
@@ -104,33 +120,7 @@
 }
 
 func (s *Suite) Test_MkCondSimplifier_SimplifyVarUse(c *check.C) {
-       t := MkCondSimplifierTester{c, s.Init(c)}
-
-       t.setUp()
-
-       t.testBeforeAndAfterPrefs(
-               ".if ${IN_SCOPE_DEFINED:Mpattern}",
-               ".if ${IN_SCOPE_DEFINED} == pattern",
-
-               "NOTE: filename.mk:6: IN_SCOPE_DEFINED can be "+
-                       "compared using the simpler \"${IN_SCOPE_DEFINED} == pattern\" "+
-                       "instead of matching against \":Mpattern\".",
-               "AUTOFIX: filename.mk:6: Replacing \"${IN_SCOPE_DEFINED:Mpattern}\" "+
-                       "with \"${IN_SCOPE_DEFINED} == pattern\".")
-
-       t.testBeforeAndAfterPrefs(
-               ".if !empty(IN_SCOPE_DEFINED:M[Nn][Oo])",
-               ".if ${IN_SCOPE_DEFINED:M[Nn][Oo]}",
-
-               "NOTE: filename.mk:6: \"!empty(IN_SCOPE_DEFINED:M[Nn][Oo])\" "+
-                       "can be simplified to \"${IN_SCOPE_DEFINED:M[Nn][Oo]}\".",
-               "AUTOFIX: filename.mk:6: "+
-                       "Replacing \"!empty(IN_SCOPE_DEFINED:M[Nn][Oo])\" "+
-                       "with \"${IN_SCOPE_DEFINED:M[Nn][Oo]}\".")
-}
-
-func (s *Suite) Test_MkCondSimplifier_simplifyWord(c *check.C) {
-       t := MkCondSimplifierTester{c, s.Init(c)}
+       t := NewMkCondSimplifierTester(c, s)
 
        t.setUp()
 
@@ -144,6 +134,43 @@
                "AUTOFIX: filename.mk:6: Replacing \"${IN_SCOPE_DEFINED:Mpattern}\" "+
                        "with \"${IN_SCOPE_DEFINED} == pattern\".")
 
+       // From simplifyYesNo.
+       t.testBeforeAndAfterPrefs(
+               ".if !empty(IN_SCOPE_DEFINED:M[Nn][Oo])",
+               ".if ${IN_SCOPE_DEFINED:tl} == no",
+
+               "NOTE: filename.mk:6: \"!empty(IN_SCOPE_DEFINED:M[Nn][Oo])\" "+
+                       "can be simplified to \"${IN_SCOPE_DEFINED:tl} == no\".",
+               "AUTOFIX: filename.mk:6: "+
+                       "Replacing \"!empty(IN_SCOPE_DEFINED:M[Nn][Oo])\" "+
+                       "with \"${IN_SCOPE_DEFINED:tl} == no\".")
+}
+
+// Show in which cases the ':U' modifier is needed, and how including



Home | Main Index | Thread Index | Old Index