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 21.2.2



details:   https://anonhg.NetBSD.org/pkgsrc/rev/c27bd691c4f6
branches:  trunk
changeset: 456792:c27bd691c4f6
user:      rillig <rillig%pkgsrc.org@localhost>
date:      Sun Aug 08 22:04:15 2021 +0000

description:
pkgtools/pkglint: update to 21.2.2

Changes since 21.2.1:

Check the variable names of OPSYS-specific variables for typos, such as
'Dragonfly' with a lowercase 'f'.  Suggested by David A. Holland in
PR pkg/56352.

Warn if variables like CFLAGS are assigned using the operator '='.
Suggested by David A. Holland in PR pkg/56352.

diffstat:

 pkgtools/pkglint/Makefile                      |    5 +-
 pkgtools/pkglint/files/makepat/pat.go          |  199 ++++++++++++++++--------
 pkgtools/pkglint/files/makepat/pat_test.go     |   53 ++++++-
 pkgtools/pkglint/files/mkassignchecker.go      |   77 +++++++++-
 pkgtools/pkglint/files/mkassignchecker_test.go |   47 +++++
 pkgtools/pkglint/files/pkgsrc.go               |   13 +
 pkgtools/pkglint/files/textproc/lexer.go       |    6 +-
 pkgtools/pkglint/files/vartype.go              |   32 ++-
 8 files changed, 338 insertions(+), 94 deletions(-)

diffs (truncated from 672 to 300 lines):

diff -r 19297c2a63ef -r c27bd691c4f6 pkgtools/pkglint/Makefile
--- a/pkgtools/pkglint/Makefile Sun Aug 08 21:22:12 2021 +0000
+++ b/pkgtools/pkglint/Makefile Sun Aug 08 22:04:15 2021 +0000
@@ -1,7 +1,6 @@
-# $NetBSD: Makefile,v 1.691 2021/07/13 11:36:37 bsiegert Exp $
+# $NetBSD: Makefile,v 1.692 2021/08/08 22:04:15 rillig Exp $
 
-PKGNAME=       pkglint-21.2.1
-PKGREVISION=   1
+PKGNAME=       pkglint-21.2.2
 CATEGORIES=    pkgtools
 DISTNAME=      tools
 MASTER_SITES=  ${MASTER_SITE_GITHUB:=golang/}
diff -r 19297c2a63ef -r c27bd691c4f6 pkgtools/pkglint/files/makepat/pat.go
--- a/pkgtools/pkglint/files/makepat/pat.go     Sun Aug 08 21:22:12 2021 +0000
+++ b/pkgtools/pkglint/files/makepat/pat.go     Sun Aug 08 22:04:15 2021 +0000
@@ -32,20 +32,16 @@
 
        lex := textproc.NewLexer(pattern)
        for !lex.EOF() {
+               ch := lex.NextByte()
 
-               if lex.SkipByte('*') {
+               switch ch {
+               case '*':
                        p.AddTransition(s, 0, 255, s)
-                       continue
-               }
-
-               if lex.SkipByte('?') {
+               case '?':
                        next := p.AddState(false)
                        p.AddTransition(s, 0, 255, next)
                        s = next
-                       continue
-               }
-
-               if lex.SkipByte('\\') {
+               case '\\':
                        if lex.EOF() {
                                return nil, errors.New("unfinished escape sequence")
                        }
@@ -53,23 +49,17 @@
                        next := p.AddState(false)
                        p.AddTransition(s, ch, ch, next)
                        s = next
-                       continue
-               }
-
-               ch := lex.NextByte()
-               if ch != '[' {
+               case '[':
+                       next, err := compileCharClass(&p, lex, ch, s)
+                       if err != nil {
+                               return nil, err
+                       }
+                       s = next
+               default:
                        next := p.AddState(false)
                        p.AddTransition(s, ch, ch, next)
                        s = next
-                       continue
                }
-
-               next, err := compileCharClass(&p, lex, ch, s)
-               if err != nil {
-                       return nil, err
-               }
-
-               s = next
        }
 
        p.states[s].end = true
@@ -144,13 +134,17 @@
 
 // Match tests whether a pattern matches the given string.
 func (p *Pattern) Match(s string) bool {
+       if len(p.states) == 0 {
+               return false
+       }
+
        curr := make([]bool, len(p.states))
        next := make([]bool, len(p.states))
 
        curr[0] = true
        for _, ch := range []byte(s) {
                ok := false
-               for i, _ := range next {
+               for i := range next {
                        next[i] = false
                }
 
@@ -183,21 +177,33 @@
 // match at the same time.
 func Intersect(p1, p2 *Pattern) *Pattern {
        var res Pattern
-       for i1 := 0; i1 < len(p1.states); i1++ {
-               for i2 := 0; i2 < len(p2.states); i2++ {
-                       res.AddState(p1.states[i1].end && p2.states[i2].end)
+
+       newState := make(map[[2]StateID]StateID)
+
+       // stateFor returns the state ID in the intersection,
+       // creating it if necessary.
+       stateFor := func(s1, s2 StateID) StateID {
+               key := [2]StateID{s1, s2}
+               ns, ok := newState[key]
+               if !ok {
+                       ns = res.AddState(p1.states[s1].end && p2.states[s2].end)
+                       newState[key] = ns
                }
+               return ns
        }
 
-       for i1 := 0; i1 < len(p1.states); i1++ {
-               for i2 := 0; i2 < len(p2.states); i2++ {
-                       for _, t1 := range p1.states[i1].transitions {
-                               for _, t2 := range p2.states[i2].transitions {
+       // Each pattern needs a start node.
+       stateFor(0, 0)
+
+       for i1, s1 := range p1.states {
+               for i2, s2 := range p2.states {
+                       for _, t1 := range s1.transitions {
+                               for _, t2 := range s2.transitions {
                                        min := bmax(t1.min, t2.min)
                                        max := bmin(t1.max, t2.max)
                                        if min <= max {
-                                               from := StateID(i1*len(p2.states) + i2)
-                                               to := t1.to*StateID(len(p2.states)) + t2.to
+                                               from := stateFor(StateID(i1), StateID(i2))
+                                               to := stateFor(t1.to, t2.to)
                                                res.AddTransition(from, min, max, to)
                                        }
                                }
@@ -209,33 +215,101 @@
 }
 
 func (p *Pattern) optimized() *Pattern {
-       var opt Pattern
+       reachable := p.reachable()
+       relevant := p.relevant(reachable)
+       return p.compressed(relevant)
+}
 
-       var todo []StateID
-       hasNewID := make([]bool, len(p.states))
-       newIDs := make([]StateID, len(p.states))
+// reachable returns all states that are reachable from the start state.
+// In optimized patterns, each state is reachable.
+func (p *Pattern) reachable() []bool {
+       reachable := make([]bool, len(p.states))
 
-       todo = append(todo, 0)
-       newIDs[0] = opt.AddState(p.states[0].end)
-       hasNewID[0] = true
+       progress := make([]int, len(p.states)) // 0 = unseen, 1 = to do, 2 = done
+
+       progress[0] = 1
 
-       for len(todo) > 0 {
-               oldStateID := todo[len(todo)-1]
-               todo = todo[:len(todo)-1]
-
-               oldState := p.states[oldStateID]
+       for {
+               changed := false
+               for i, pr := range progress {
+                       if pr == 1 {
+                               reachable[i] = true
+                               progress[i] = 2
+                               changed = true
+                               for _, tr := range p.states[i].transitions {
+                                       if progress[tr.to] == 0 {
+                                               progress[tr.to] = 1
+                                       }
+                               }
+                       }
+               }
 
-               for _, t := range oldState.transitions {
-                       if !hasNewID[t.to] {
-                               hasNewID[t.to] = true
-                               newIDs[t.to] = opt.AddState(p.states[t.to].end)
-                               todo = append(todo, t.to)
-                       }
-                       opt.AddTransition(newIDs[oldStateID], t.min, t.max, newIDs[t.to])
+               if !changed {
+                       break
                }
        }
 
-       // TODO: remove transitions that point to a dead end
+       return reachable
+}
+
+// relevant returns all states from which and end state is reachable.
+// In optimized patterns, each state is relevant.
+func (p *Pattern) relevant(reachable []bool) []bool {
+       relevant := make([]bool, len(p.states))
+
+       progress := make([]int, len(p.states)) // 0 = unseen, 1 = to do, 2 = done
+
+       for i, state := range p.states {
+               if state.end && reachable[i] {
+                       progress[i] = 1
+               }
+       }
+
+       for {
+               changed := false
+               for to, pr := range progress {
+                       if pr != 1 {
+                               continue
+                       }
+                       progress[to] = 2
+                       relevant[to] = true
+                       changed = true
+                       for from, st := range p.states {
+                               for _, tr := range st.transitions {
+                                       if tr.to == StateID(to) && reachable[from] &&
+                                               progress[from] == 0 {
+                                               progress[from] = 1
+                                       }
+                               }
+                       }
+               }
+
+               if !changed {
+                       break
+               }
+       }
+
+       return relevant
+}
+
+// compressed creates a pattern that contains only the relevant states.
+func (p *Pattern) compressed(relevant []bool) *Pattern {
+       var opt Pattern
+
+       newIDs := make([]StateID, len(p.states))
+       for i, r := range relevant {
+               if r {
+                       newIDs[i] = opt.AddState(p.states[i].end)
+               }
+       }
+
+       for from, s := range p.states {
+               for _, t := range s.transitions {
+                       if relevant[from] && relevant[t.to] {
+                               opt.AddTransition(newIDs[from], t.min, t.max, newIDs[t.to])
+                       }
+               }
+       }
 
        return &opt
 }
@@ -246,24 +320,11 @@
 //  [^]
 //  Intersect("*.c", "*.h")
 func (p *Pattern) CanMatch() bool {
-       reachable := make([]bool, len(p.states))
-       reachable[0] = true
+       if len(p.states) == 0 {
+               return false
+       }
 
-again:
-       changed := false
-       for i, s := range p.states {
-               if reachable[i] {
-                       for _, t := range s.transitions {
-                               if !reachable[t.to] {
-                                       reachable[t.to] = true
-                                       changed = true
-                               }
-                       }
-               }
-       }
-       if changed {
-               goto again
-       }
+       reachable := p.reachable()
 
        for i, s := range p.states {
                if reachable[i] && s.end {
diff -r 19297c2a63ef -r c27bd691c4f6 pkgtools/pkglint/files/makepat/pat_test.go
--- a/pkgtools/pkglint/files/makepat/pat_test.go        Sun Aug 08 21:22:12 2021 +0000
+++ b/pkgtools/pkglint/files/makepat/pat_test.go        Sun Aug 08 22:04:15 2021 +0000
@@ -44,10 +44,11 @@
                        p, err := Compile(tt.pattern)
                        if err != nil {
                                t.Fail()
-                       }
-                       got := p.Match(tt.str)
-                       if got != tt.want {
-                               t.Errorf("got %v, want %v", got, tt.want)
+                       } else {
+                               got := p.Match(tt.str)
+                               if got != tt.want {



Home | Main Index | Thread Index | Old Index