Received: by mail.netbsd.org (Postfix, from userid 605) id C9BB884D96; Sun, 6 Jun 2021 11:46:46 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by mail.netbsd.org (Postfix) with ESMTP id 1058184D25 for ; Sun, 6 Jun 2021 11:46:46 +0000 (UTC) X-Virus-Scanned: amavisd-new at netbsd.org Received: from mail.netbsd.org ([127.0.0.1]) by localhost (mail.netbsd.org [127.0.0.1]) (amavisd-new, port 10025) with ESMTP id X_hjB-Ee92l1 for ; Sun, 6 Jun 2021 11:46:44 +0000 (UTC) Received: from cvs.NetBSD.org (ivanova.netbsd.org [199.233.217.197]) by mail.netbsd.org (Postfix) with ESMTP id 84EBB84CE0 for ; Sun, 6 Jun 2021 11:46:44 +0000 (UTC) Received: by cvs.NetBSD.org (Postfix, from userid 500) id 7E9B2FA95; Sun, 6 Jun 2021 11:46:44 +0000 (UTC) Content-Transfer-Encoding: 7bit Content-Type: multipart/mixed; boundary="_----------=_1622980004183400" MIME-Version: 1.0 Date: Sun, 6 Jun 2021 11:46:44 +0000 From: "Roland Illig" Subject: CVS commit: pkgsrc/pkgtools/pkglint To: pkgsrc-changes@NetBSD.org Reply-To: rillig@netbsd.org X-Mailer: log_accum Message-Id: <20210606114644.7E9B2FA95@cvs.NetBSD.org> Sender: pkgsrc-changes-owner@NetBSD.org List-Id: Precedence: bulk List-Unsubscribe: This is a multi-part message in MIME format. --_----------=_1622980004183400 Content-Disposition: inline Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset="US-ASCII" Module Name: pkgsrc Committed By: rillig Date: Sun Jun 6 11:46:44 UTC 2021 Modified Files: pkgsrc/pkgtools/pkglint: Makefile pkgsrc/pkgtools/pkglint/files: category.go mkcondchecker.go mkline.go vardefs.go vartype.go vartypecheck.go vartypecheck_test.go pkgsrc/pkgtools/pkglint/files/licenses: licenses.go pkgsrc/pkgtools/pkglint/files/textproc: lexer.go lexer_test.go Log Message: pkgtools/pkglint: update to 21.1.4 Changes since 21.1.3: Allow slash in Git tags like 'refs/tags/v1.0.0', as well as in make targets like 'subdir/build'. To generate a diff of this commit: cvs rdiff -u -r1.687 -r1.688 pkgsrc/pkgtools/pkglint/Makefile cvs rdiff -u -r1.35 -r1.36 pkgsrc/pkgtools/pkglint/files/category.go cvs rdiff -u -r1.10 -r1.11 pkgsrc/pkgtools/pkglint/files/mkcondchecker.go cvs rdiff -u -r1.83 -r1.84 pkgsrc/pkgtools/pkglint/files/mkline.go cvs rdiff -u -r1.101 -r1.102 pkgsrc/pkgtools/pkglint/files/vardefs.go cvs rdiff -u -r1.51 -r1.52 pkgsrc/pkgtools/pkglint/files/vartype.go cvs rdiff -u -r1.94 -r1.95 pkgsrc/pkgtools/pkglint/files/vartypecheck.go cvs rdiff -u -r1.86 -r1.87 pkgsrc/pkgtools/pkglint/files/vartypecheck_test.go cvs rdiff -u -r1.7 -r1.8 pkgsrc/pkgtools/pkglint/files/licenses/licenses.go cvs rdiff -u -r1.10 -r1.11 pkgsrc/pkgtools/pkglint/files/textproc/lexer.go \ pkgsrc/pkgtools/pkglint/files/textproc/lexer_test.go Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. --_----------=_1622980004183400 Content-Disposition: inline Content-Length: 19446 Content-Transfer-Encoding: binary Content-Type: text/x-diff; charset=us-ascii Modified files: Index: pkgsrc/pkgtools/pkglint/Makefile diff -u pkgsrc/pkgtools/pkglint/Makefile:1.687 pkgsrc/pkgtools/pkglint/Makefile:1.688 --- pkgsrc/pkgtools/pkglint/Makefile:1.687 Sun Jun 6 07:41:34 2021 +++ pkgsrc/pkgtools/pkglint/Makefile Sun Jun 6 11:46:43 2021 @@ -1,6 +1,6 @@ -# $NetBSD: Makefile,v 1.687 2021/06/06 07:41:34 rillig Exp $ +# $NetBSD: Makefile,v 1.688 2021/06/06 11:46:43 rillig Exp $ -PKGNAME= pkglint-21.1.3 +PKGNAME= pkglint-21.1.4 CATEGORIES= pkgtools DISTNAME= tools MASTER_SITES= ${MASTER_SITE_GITHUB:=golang/} Index: pkgsrc/pkgtools/pkglint/files/category.go diff -u pkgsrc/pkgtools/pkglint/files/category.go:1.35 pkgsrc/pkgtools/pkglint/files/category.go:1.36 --- pkgsrc/pkgtools/pkglint/files/category.go:1.35 Mon Mar 22 23:26:30 2021 +++ pkgsrc/pkgtools/pkglint/files/category.go Sun Jun 6 11:46:43 2021 @@ -25,7 +25,7 @@ func CheckdirCategory(dir CurrPath) { if mlex.SkipIf(func(mkline *MkLine) bool { return mkline.IsVarassign() && mkline.Varname() == "COMMENT" }) { mkline := mlex.PreviousMkLine() - valid := textproc.NewByteSet("--- '(),/0-9A-Za-z") + valid := textproc.NewByteSet("- '(),/0-9A-Za-z") invalid := invalidCharacters(mkline.Value(), valid) if invalid != "" { mkline.Warnf("%s contains invalid characters (%s).", Index: pkgsrc/pkgtools/pkglint/files/mkcondchecker.go diff -u pkgsrc/pkgtools/pkglint/files/mkcondchecker.go:1.10 pkgsrc/pkgtools/pkglint/files/mkcondchecker.go:1.11 --- pkgsrc/pkgtools/pkglint/files/mkcondchecker.go:1.10 Wed Jul 1 13:17:41 2020 +++ pkgsrc/pkgtools/pkglint/files/mkcondchecker.go Sun Jun 6 11:46:43 2021 @@ -152,11 +152,13 @@ func (ck *MkCondChecker) checkEmptyType( // mkCondStringLiteralUnquoted contains a safe subset of the characters // that may be used without surrounding quotes in a comparison such as // ${PKGPATH} == category/package. -var mkCondStringLiteralUnquoted = textproc.NewByteSet("+---./0-9@A-Z_a-z") +// TODO: Check whether the ',' really needs to be here. +var mkCondStringLiteralUnquoted = textproc.NewByteSet("-+,./0-9@A-Z_a-z") // mkCondModifierPatternLiteral contains a safe subset of the characters // that are interpreted literally in the :M and :N modifiers. -var mkCondModifierPatternLiteral = textproc.NewByteSet("+---./0-9<=>@A-Z_a-z") +// TODO: Check whether the ',' really needs to be here. +var mkCondModifierPatternLiteral = textproc.NewByteSet("-+,./0-9<=>@A-Z_a-z") // simplify replaces an unnecessarily complex condition with // a simpler condition that's still equivalent. Index: pkgsrc/pkgtools/pkglint/files/mkline.go diff -u pkgsrc/pkgtools/pkglint/files/mkline.go:1.83 pkgsrc/pkgtools/pkglint/files/mkline.go:1.84 --- pkgsrc/pkgtools/pkglint/files/mkline.go:1.83 Sat Apr 17 18:10:14 2021 +++ pkgsrc/pkgtools/pkglint/files/mkline.go Sun Jun 6 11:46:43 2021 @@ -700,7 +700,7 @@ func (mkline *MkLine) RelMkLine(other *M } var ( - LowerDash = textproc.NewByteSet("a-z---") + LowerDash = textproc.NewByteSet("a-z-") AlnumDot = textproc.NewByteSet("A-Za-z0-9_.") unescapeMkCommentSafeChars = textproc.NewByteSet("\\#[\n").Inverse() ) @@ -1327,8 +1327,10 @@ func (ind *Indentation) CheckFinish(file // TODO: The allowed characters differ between the basename and the parameter // of the variable. The square bracket is only allowed in the parameter part. var ( - VarbaseBytes = textproc.NewByteSet("A-Za-z_0-9+---") - VarparamBytes = textproc.NewByteSet("A-Za-z_0-9#*+---./[") + // TODO: remove the ',' + VarbaseBytes = textproc.NewByteSet("A-Za-z_0-9-+,") + // TODO: Check whether the ',' really needs to be here. + VarparamBytes = textproc.NewByteSet("A-Za-z_0-9-#*+,./[") ) func MatchMkInclude(text string) (m bool, indentation, directive string, filename RelPath) { Index: pkgsrc/pkgtools/pkglint/files/vardefs.go diff -u pkgsrc/pkgtools/pkglint/files/vardefs.go:1.101 pkgsrc/pkgtools/pkglint/files/vardefs.go:1.102 --- pkgsrc/pkgtools/pkglint/files/vardefs.go:1.101 Mon Oct 26 22:13:23 2020 +++ pkgsrc/pkgtools/pkglint/files/vardefs.go Sun Jun 6 11:46:43 2021 @@ -1032,8 +1032,8 @@ func (reg *VarTypeRegistry) Init(src *Pk reg.pkglist("BUILD_ENV", BtShellWord) reg.sys("BUILD_MAKE_CMD", BtShellCommand) reg.pkglist("BUILD_MAKE_FLAGS", BtShellWord) - reg.pkglist("BUILD_TARGET", BtIdentifierIndirect) - reg.pkglist("BUILD_TARGET.*", BtIdentifierIndirect) + reg.pkglist("BUILD_TARGET", BtMakeTarget) + reg.pkglist("BUILD_TARGET.*", BtMakeTarget) reg.pkg("BUILD_USES_MSGFMT", BtYes) reg.acl("BUILTIN_PKG", BtIdentifierDirect, PackageSettable, @@ -1143,12 +1143,12 @@ func (reg *VarTypeRegistry) Init(src *Pk reg.pkg("DISTNAME", BtFilename) reg.pkg("DIST_SUBDIR", BtPathname) reg.pkglist("DJB_BUILD_ARGS", BtShellWord) - reg.pkglist("DJB_BUILD_TARGETS", BtIdentifierIndirect) + reg.pkglist("DJB_BUILD_TARGETS", BtMakeTarget) reg.pkgappend("DJB_CONFIG_CMDS", BtShellCommands) reg.pkglist("DJB_CONFIG_DIRS", BtWrksrcSubdirectory) reg.pkg("DJB_CONFIG_HOME", BtFilename) reg.pkg("DJB_CONFIG_PREFIX", BtPathname) - reg.pkglist("DJB_INSTALL_TARGETS", BtIdentifierIndirect) + reg.pkglist("DJB_INSTALL_TARGETS", BtMakeTarget) reg.pkg("DJB_MAKE_TARGETS", BtYesNo) reg.pkg("DJB_RESTRICTED", BtYesNo) reg.pkg("DJB_SLASHPACKAGE", BtYesNo) @@ -1230,7 +1230,7 @@ func (reg *VarTypeRegistry) Init(src *Pk reg.pkglistbl3rat("GCC_REQD", BtGccReqd) reg.pkgappend("GENERATE_PLIST", BtShellCommands) reg.pkg("GITHUB_PROJECT", BtIdentifierIndirect) - reg.pkg("GITHUB_TAG", BtIdentifierIndirect) + reg.pkg("GITHUB_TAG", BtGitTag) reg.pkg("GITHUB_RELEASE", BtFilename) reg.pkg("GITHUB_TYPE", enum("tag release")) reg.pkgrat("GMAKE_REQD", BtVersion) @@ -1282,7 +1282,7 @@ func (reg *VarTypeRegistry) Init(src *Pk reg.syslist("INSTALL_SCRIPTS_ENV", BtShellWord) reg.sys("INSTALL_SCRIPT_DIR", BtShellCommand) reg.pkglist("INSTALL_SRC", BtPathname) - reg.pkglist("INSTALL_TARGET", BtIdentifierIndirect) + reg.pkglist("INSTALL_TARGET", BtMakeTarget) reg.pkglist("INSTALL_TEMPLATES", BtPathname) reg.pkgload("INSTALL_UNSTRIPPED", BtYesNo) reg.pkglist("INTERACTIVE_STAGE", enum("fetch extract configure build test install")) @@ -1729,7 +1729,7 @@ func (reg *VarTypeRegistry) Init(src *Pk reg.pkglist("TEST_DEPENDS", BtDependencyWithPath) reg.pkglist("TEST_DIRS", BtWrksrcSubdirectory) reg.pkglist("TEST_ENV", BtShellWord) - reg.pkglist("TEST_TARGET", BtIdentifierIndirect) + reg.pkglist("TEST_TARGET", BtMakeTarget) reg.pkglistrat("TEXINFO_REQD", BtVersion) reg.pkglistbl3("TOOL_DEPENDS", BtDependencyWithPath) reg.syslist("TOOLS_ALIASES", BtFilename) Index: pkgsrc/pkgtools/pkglint/files/vartype.go diff -u pkgsrc/pkgtools/pkglint/files/vartype.go:1.51 pkgsrc/pkgtools/pkglint/files/vartype.go:1.52 --- pkgsrc/pkgtools/pkglint/files/vartype.go:1.51 Sat Jun 6 20:42:56 2020 +++ pkgsrc/pkgtools/pkglint/files/vartype.go Sun Jun 6 11:46:43 2021 @@ -358,6 +358,7 @@ func (bt *BasicType) NeedsQ() bool { BtEmulPlatform, BtFileMode, BtFilename, + BtGitTag, BtIdentifierDirect, BtIdentifierIndirect, BtInteger, @@ -428,6 +429,7 @@ var ( BtFilePattern = &BasicType{"FilePattern", (*VartypeCheck).FilePattern} BtFileMode = &BasicType{"FileMode", (*VartypeCheck).FileMode} BtGccReqd = &BasicType{"GccReqd", (*VartypeCheck).GccReqd} + BtGitTag = &BasicType{"GitTag", (*VartypeCheck).GitTag} BtHomepage = &BasicType{"Homepage", (*VartypeCheck).Homepage} BtIdentifierDirect = &BasicType{"Identifier", (*VartypeCheck).IdentifierDirect} BtIdentifierIndirect = &BasicType{"Identifier", (*VartypeCheck).IdentifierIndirect} @@ -438,6 +440,7 @@ var ( BtMachinePlatform = &BasicType{"MachinePlatform", (*VartypeCheck).MachinePlatform} BtMachinePlatformPattern = &BasicType{"MachinePlatformPattern", (*VartypeCheck).MachinePlatformPattern} BtMailAddress = &BasicType{"MailAddress", (*VartypeCheck).MailAddress} + BtMakeTarget = &BasicType{"MakeTarget", (*VartypeCheck).MakeTarget} BtMessage = &BasicType{"Message", (*VartypeCheck).Message} BtOption = &BasicType{"Option", (*VartypeCheck).Option} BtPathlist = &BasicType{"Pathlist", (*VartypeCheck).Pathlist} Index: pkgsrc/pkgtools/pkglint/files/vartypecheck.go diff -u pkgsrc/pkgtools/pkglint/files/vartypecheck.go:1.94 pkgsrc/pkgtools/pkglint/files/vartypecheck.go:1.95 --- pkgsrc/pkgtools/pkglint/files/vartypecheck.go:1.94 Fri Jul 31 22:39:36 2020 +++ pkgsrc/pkgtools/pkglint/files/vartypecheck.go Sun Jun 6 11:46:43 2021 @@ -21,7 +21,7 @@ type VartypeCheck struct { Varname string Op MkOperator Value string - ValueNoVar string + ValueNoVar string // The Value with all expressions removed. MkComment string // The comment including the "#". Guessed bool // Whether the type definition is guessed (based on the variable name) or explicitly defined (see vardefs.go). } @@ -676,6 +676,29 @@ func (cv *VartypeCheck) GccReqd() { } } +// GitTag checks for a fixed reference to a Git commit. +// +// https://git-scm.com/docs/gitrevisions +func (cv *VartypeCheck) GitTag() { + tag := cv.ValueNoVar + + valid := textproc.NewByteSet("0-9A-Za-z-+._/") + invalid := invalidCharacters(tag, valid) + if invalid != "" { + cv.Warnf("Invalid characters %q in Git tag.", invalid) + return + } + + if tag == "master" || hasPrefix(tag, "refs/heads/") { + cv.Warnf("The Git tag %q refers to a moving target.", tag) + return + } + + if len(tag) < 7 && matches(tag, `^[A-Fa-f0-9]+$`) { + cv.Warnf("The git commit name %q is too short to be reliable.", tag) + } +} + func (cv *VartypeCheck) Homepage() { cv.URL() @@ -683,8 +706,8 @@ func (cv *VartypeCheck) Homepage() { ck.Check() } -// Identifier checks for valid identifiers in various contexts, limiting the -// valid characters to A-Za-z0-9_. +// IdentifierDirect checks for valid identifiers in various contexts, +// limiting the valid characters to A-Za-z0-9_. func (cv *VartypeCheck) IdentifierDirect() { if cv.Op == opUseMatch { if cv.Value == cv.ValueNoVar && !matches(cv.Value, `^[\w*\-?\[\]]+$`) { @@ -703,8 +726,8 @@ func (cv *VartypeCheck) IdentifierDirect } } -// Identifier checks for valid identifiers in various contexts, limiting the -// valid characters to A-Za-z0-9_. +// IdentifierIndirect checks for valid identifiers in various contexts, +// limiting the valid characters to A-Za-z0-9_. func (cv *VartypeCheck) IdentifierIndirect() { if cv.Value == cv.ValueNoVar { cv.IdentifierDirect() @@ -847,6 +870,16 @@ func (cv *VartypeCheck) MailAddress() { } } +func (cv *VartypeCheck) MakeTarget() { + if cv.Op == opUseMatch || cv.ValueNoVar != cv.Value { + return + } + + if !matches(cv.ValueNoVar, `^[+\-.\w/]+$`) { + cv.Warnf("Invalid make target %q.", cv.Value) + } +} + // Message is a plain string. When defining a message variable, it should // not be enclosed in quotes since that is the job of the code that uses // the message. @@ -980,8 +1013,9 @@ func (cv *VartypeCheck) Pathname() { invalid) } -// Like Pathname, but may contain spaces as well. -// Because the spaces must be quoted, backslashes and quotes are allowed as well. +// PathnameSpace is like Pathname, but may contain spaces as well. +// Because the spaces must be quoted, backslashes and quotes are allowed as +// well. func (cv *VartypeCheck) PathnameSpace() { valid := regex.Pattern(condStr( cv.Op == opUseMatch, @@ -1108,7 +1142,7 @@ func (cv *VartypeCheck) PlistIdentifier( } if cv.Op == opUseMatch { - invalidPatternChars := textproc.NewByteSet("A-Za-z0-9---_*?[]") + invalidPatternChars := textproc.NewByteSet("A-Za-z0-9-_*?[]") invalid := invalidCharacters(cond, invalidPatternChars) if invalid != "" { cv.Warnf("PLIST identifier pattern %q contains invalid characters (%s).", @@ -1120,7 +1154,7 @@ func (cv *VartypeCheck) PlistIdentifier( return } - invalidChars := textproc.NewByteSet("A-Za-z0-9---_") + invalidChars := textproc.NewByteSet("A-Za-z0-9-_") invalid := invalidCharacters(cond, invalidChars) if invalid != "" { cv.Errorf("PLIST identifier %q contains invalid characters (%s).", @@ -1448,7 +1482,7 @@ func (cv *VartypeCheck) UserGroupName() if value != cv.ValueNoVar { return } - invalid := invalidCharacters(value, textproc.NewByteSet("---0-9_a-z")) + invalid := invalidCharacters(value, textproc.NewByteSet("-0-9_a-z")) if invalid != "" { cv.Warnf("User or group name %q contains invalid characters: %s", value, invalid) Index: pkgsrc/pkgtools/pkglint/files/vartypecheck_test.go diff -u pkgsrc/pkgtools/pkglint/files/vartypecheck_test.go:1.86 pkgsrc/pkgtools/pkglint/files/vartypecheck_test.go:1.87 --- pkgsrc/pkgtools/pkglint/files/vartypecheck_test.go:1.86 Fri Jul 31 22:39:36 2020 +++ pkgsrc/pkgtools/pkglint/files/vartypecheck_test.go Sun Jun 6 11:46:43 2021 @@ -1126,6 +1126,32 @@ func (s *Suite) Test_VartypeCheck_GccReq "WARN: filename.mk:7: GCC version numbers should only contain the major version (7).") } +func (s *Suite) Test_VartypeCheck_GitTag(c *check.C) { + vt := NewVartypeCheckTester(s.Init(c), BtGitTag) + + vt.Varname("GITHUB_TAG") + vt.Values( + "master", // Bad since it is a moving target. + "v1.2.3", + "refs/heads/devel", // Bad since it is a moving target. + "refs/tags/v1.2.3", + "v${PKGVERSION_NOREV}", + "1234567812345678123456781234567812345678", + "1234567", + "123456", // Too short in practice. + "${DISTNAME}", + "invalid:char", // Bad since ':' is not supported. + "invalid:;char", // Bad since neither ':' nor ';' is supported. + "jdk-11.0.10+9-1", + ) + vt.Output( + "WARN: filename.mk:1: The Git tag \"master\" refers to a moving target.", + "WARN: filename.mk:3: The Git tag \"refs/heads/devel\" refers to a moving target.", + "WARN: filename.mk:8: The git commit name \"123456\" is too short to be reliable.", + "WARN: filename.mk:10: Invalid characters \":\" in Git tag.", + "WARN: filename.mk:11: Invalid characters \": ;\" in Git tag.") +} + func (s *Suite) Test_VartypeCheck_Homepage(c *check.C) { t := s.Init(c) vt := NewVartypeCheckTester(t, BtHomepage) @@ -1448,6 +1474,33 @@ func (s *Suite) Test_VartypeCheck_MailAd "WARN: filename.mk:4: \"user1@example.org,user2@example.org\" is not a valid mail address.") } +func (s *Suite) Test_VartypeCheck_MakeTarget(c *check.C) { + t := s.Init(c) + vt := NewVartypeCheckTester(t, BtMakeTarget) + + vt.Varname("BUILD_TARGET") + vt.Values( + "${OTHER_VAR}", + "spaces in target lists are ok", + "target/may/contain/slashes", + "target:must:not:contain:colons", + "id-${OTHER_VAR}", + "") + + vt.Output( + "WARN: filename.mk:4: Invalid make target " + + "\"target:must:not:contain:colons\".") + + vt.Op(opUseMatch) + vt.Values( + "[A-Z]", + "[A-Z.]", + "${PKG_OPTIONS:Moption}", + "A*B") + + vt.OutputEmpty() +} + func (s *Suite) Test_VartypeCheck_Message(c *check.C) { vt := NewVartypeCheckTester(s.Init(c), BtMessage) Index: pkgsrc/pkgtools/pkglint/files/licenses/licenses.go diff -u pkgsrc/pkgtools/pkglint/files/licenses/licenses.go:1.7 pkgsrc/pkgtools/pkglint/files/licenses/licenses.go:1.8 --- pkgsrc/pkgtools/pkglint/files/licenses/licenses.go:1.7 Sat Nov 30 20:35:11 2019 +++ pkgsrc/pkgtools/pkglint/files/licenses/licenses.go Sun Jun 6 11:46:44 2021 @@ -67,7 +67,7 @@ type licenseLexer struct { error string } -var licenseNameChars = textproc.NewByteSet("A-Za-z0-9---._") +var licenseNameChars = textproc.NewByteSet("A-Za-z0-9-._") func (lexer *licenseLexer) Lex(llval *liyySymType) int { lex := lexer.lexer Index: pkgsrc/pkgtools/pkglint/files/textproc/lexer.go diff -u pkgsrc/pkgtools/pkglint/files/textproc/lexer.go:1.10 pkgsrc/pkgtools/pkglint/files/textproc/lexer.go:1.11 --- pkgsrc/pkgtools/pkglint/files/textproc/lexer.go:1.10 Sat Jan 4 19:53:14 2020 +++ pkgsrc/pkgtools/pkglint/files/textproc/lexer.go Sun Jun 6 11:46:44 2021 @@ -240,8 +240,8 @@ func (l *Lexer) Copy() *Lexer { return & func (l *Lexer) Commit(other *Lexer) bool { l.rest = other.rest; return true } // NewByteSet creates a bit mask out of a string like "0-9A-Za-z_". -// To add an actual hyphen to the bit mask, write it as "---" -// (a range from hyphen to hyphen). +// To add an actual hyphen to the bit mask, write it either at the beginning +// or at the end of the string, or directly after a range like "a-z". // // The bit mask can be used with Lexer.NextBytesSet. func NewByteSet(chars string) *ByteSet { Index: pkgsrc/pkgtools/pkglint/files/textproc/lexer_test.go diff -u pkgsrc/pkgtools/pkglint/files/textproc/lexer_test.go:1.10 pkgsrc/pkgtools/pkglint/files/textproc/lexer_test.go:1.11 --- pkgsrc/pkgtools/pkglint/files/textproc/lexer_test.go:1.10 Sat Jan 4 19:53:14 2020 +++ pkgsrc/pkgtools/pkglint/files/textproc/lexer_test.go Sun Jun 6 11:46:44 2021 @@ -359,18 +359,81 @@ func (s *Suite) Test_NewByteSet(c *check } // Demonstrates how to specify a byte set that includes a hyphen, -// since that is also used for byte ranges. -// The hyphen must be written as ---, which is a range from hyphen to hyphen. -func (s *Suite) Test_NewByteSet__range_hyphen(c *check.C) { +// since that character is also used for byte ranges. +// The hyphen is written as ---, which is a range from hyphen to hyphen. +func (s *Suite) Test_NewByteSet__range_hyphen_beginning(c *check.C) { set := NewByteSet("---a-z") - expected := "abcdefghijklmnopqrstuvwxyz-" + var actual strings.Builder for i := 0; i < 256; i++ { - c.Check( - set.Contains(byte(i)), - equals, - strings.IndexByte(expected, byte(i)) != -1) + if set.Contains(byte(i)) { + actual.WriteByte(byte(i)) + } + } + + c.Check(actual.String(), equals, "-abcdefghijklmnopqrstuvwxyz") +} + +// The byte set "x---a" is interpreted as 3 parts: "x--", "-", "a". +// +// The range "x--" is empty since U+0078 'x' comes later in Unicode than +// U+002D '-'. +func (s *Suite) Test_NewByteSet__range_hyphen_middle(c *check.C) { + set := NewByteSet("x---a") + + var actual strings.Builder + for i := 0; i < 256; i++ { + if set.Contains(byte(i)) { + actual.WriteByte(byte(i)) + } + } + + c.Check(actual.String(), equals, "-a") +} + +// When a hyphen is listed at the very beginning, it is not considered part +// of a byte range but interpreted literally. +func (s *Suite) Test_NewByteSet__hyphen_beginning(c *check.C) { + set := NewByteSet("-ax") + + var actual strings.Builder + for i := 0; i < 256; i++ { + if set.Contains(byte(i)) { + actual.WriteByte(byte(i)) + } } + + c.Check(actual.String(), equals, "-ax") +} + +// When a hyphen is listed directly after a range ('+-+' in this case), +// it is interpreted literally. +func (s *Suite) Test_NewByteSet__hyphen_after_range(c *check.C) { + set := NewByteSet("+-+-") + + var actual strings.Builder + for i := 0; i < 256; i++ { + if set.Contains(byte(i)) { + actual.WriteByte(byte(i)) + } + } + + c.Check(actual.String(), equals, "+-") +} + +// When a hyphen is listed at the very end, it is not considered part +// of a byte range but interpreted literally. +func (s *Suite) Test_NewByteSet__hyphen_end(c *check.C) { + set := NewByteSet("ax-") + + var actual strings.Builder + for i := 0; i < 256; i++ { + if set.Contains(byte(i)) { + actual.WriteByte(byte(i)) + } + } + + c.Check(actual.String(), equals, "-ax") } func (s *Suite) Test_ByteSet_Inverse(c *check.C) { --_----------=_1622980004183400--