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