Sun Jan 24 02:03:28 2016 UTC ()
Updated pkglint to 5.3.2

Changes since 5.3.1:

Alignment of variable values is no longer checked by single line, but by
the complete block (e.g. SUBST_*).  Pkglint now checks that all variables
belonging to a block are indented consistently, so that their values are
aligned nicely.

Since pkglint does not report warnings, but only notes, and since it can
fix them automatically, the burden on the package developers will be very
low. Especially, since these notes are only printed when pkglint is called
with the -Wspace or -Wall options.

Also, pkglint supports running its unit tests now.


(rillig)
diff -r1.477 -r1.478 pkgsrc/pkgtools/pkglint/Makefile
diff -r1.6 -r1.7 pkgsrc/pkgtools/pkglint/files/check_test.go
diff -r1.6 -r1.7 pkgsrc/pkgtools/pkglint/files/globaldata.go
diff -r1.6 -r1.7 pkgsrc/pkgtools/pkglint/files/mkline_test.go
diff -r1.6 -r1.7 pkgsrc/pkgtools/pkglint/files/pkglint.go
diff -r1.7 -r1.8 pkgsrc/pkgtools/pkglint/files/mkline.go
diff -r1.1 -r1.2 pkgsrc/pkgtools/pkglint/files/mklines.go
diff -r1.4 -r1.5 pkgsrc/pkgtools/pkglint/files/pkglint_test.go

cvs diff -r1.477 -r1.478 pkgsrc/pkgtools/pkglint/Makefile (expand / switch to unified diff)

--- pkgsrc/pkgtools/pkglint/Makefile 2016/01/18 15:33:44 1.477
+++ pkgsrc/pkgtools/pkglint/Makefile 2016/01/24 02:03:28 1.478
@@ -1,50 +1,50 @@ @@ -1,50 +1,50 @@
1# $NetBSD: Makefile,v 1.477 2016/01/18 15:33:44 fhajny Exp $ 1# $NetBSD: Makefile,v 1.478 2016/01/24 02:03:28 rillig Exp $
2 2
3PKGNAME= pkglint-5.3.1 3PKGNAME= pkglint-5.3.2
4PKGREVISION= 1 
5DISTFILES= # none 4DISTFILES= # none
6CATEGORIES= pkgtools 5CATEGORIES= pkgtools
7 6
8OWNER= rillig@NetBSD.org 7OWNER= rillig@NetBSD.org
9HOMEPAGE= http://www.NetBSD.org/docs/pkgsrc/ 8HOMEPAGE= http://www.NetBSD.org/docs/pkgsrc/
10COMMENT= Verifier for NetBSD packages 9COMMENT= Verifier for NetBSD packages
11LICENSE= 2-clause-bsd 10LICENSE= 2-clause-bsd
12CONFLICTS+= pkglint4-[0-9]* 11CONFLICTS+= pkglint4-[0-9]*
13 12
14WRKSRC= ${WRKDIR}/netbsd.org/pkglint 13WRKSRC= ${WRKDIR}/netbsd.org/pkglint
15NO_CHECKSUM= yes 14NO_CHECKSUM= yes
16USE_LANGUAGES= # none 15USE_LANGUAGES= # none
 16USE_TOOLS+= pax
17AUTO_MKDIRS= yes 17AUTO_MKDIRS= yes
18GO_SRCPATH= netbsd.org/pkglint 18GO_SRCPATH= netbsd.org/pkglint
19 19
20SUBST_CLASSES+= pkglint 20SUBST_CLASSES+= pkglint
21SUBST_STAGE.pkglint= post-configure 21SUBST_STAGE.pkglint= post-configure
22SUBST_FILES.pkglint+= main.go 22SUBST_FILES.pkglint+= main.go
23SUBST_SED.pkglint+= -e s\|@VERSION@\|${PKGNAME:S/pkglint-//}\|g 23SUBST_SED.pkglint+= -e s\|@VERSION@\|${PKGNAME:S/pkglint-//}\|g
24SUBST_SED.pkglint+= -e s\|@BMAKE@\|${MAKE:Q}\|g 24SUBST_SED.pkglint+= -e s\|@BMAKE@\|${MAKE:Q}\|g
25 25
26do-extract: 26do-extract:
27 mkdir -p ${WRKDIR}/pkglint/plist-clash 27 ${RUN} mkdir -p ${WRKDIR}/pkglint/plist-clash
28 cd ${FILESDIR} && ${PAX} -rw *.go */*.go pkglint.[01] ${WRKDIR}/pkglint 28 ${RUN} cd ${FILESDIR} && ${PAX} -rw *.go */*.go pkglint.[01] ${WRKDIR}/pkglint
29 
30do-test: 
31 cd ${WRKSRC} && go test 
32 29
33do-install: do-install-man 30do-install: do-install-man
34 31
35.include "../../mk/bsd.prefs.mk" 32.include "../../mk/bsd.prefs.mk"
36 33
37do-install-man: 34do-install-man: .PHONY
38.if !empty(MANINSTALL:Mcatinstall) 35.if !empty(MANINSTALL:Mcatinstall)
39. if defined(CATMAN_SECTION_SUFFIX) && !empty(CATMAN_SECTION_SUFFIX:M[Yy][Ee][Ss]) 36. if defined(CATMAN_SECTION_SUFFIX) && !empty(CATMAN_SECTION_SUFFIX:M[Yy][Ee][Ss])
40 ${INSTALL_MAN} ${WRKSRC}/pkglint.0 ${DESTDIR}${PREFIX}/${PKGMANDIR}/cat1/pkglint.1 37 ${INSTALL_MAN} ${WRKSRC}/pkglint.0 ${DESTDIR}${PREFIX}/${PKGMANDIR}/cat1/pkglint.1
41. else 38. else
42 ${INSTALL_MAN} ${WRKSRC}/pkglint.0 ${DESTDIR}${PREFIX}/${PKGMANDIR}/cat1 39 ${INSTALL_MAN} ${WRKSRC}/pkglint.0 ${DESTDIR}${PREFIX}/${PKGMANDIR}/cat1
43. endif 40. endif
44.endif 41.endif
45.if !empty(MANINSTALL:Mmaninstall) 42.if !empty(MANINSTALL:Mmaninstall)
46 ${INSTALL_MAN} ${WRKSRC}/pkglint.1 ${DESTDIR}${PREFIX}/${PKGMANDIR}/man1 43 ${INSTALL_MAN} ${WRKSRC}/pkglint.1 ${DESTDIR}${PREFIX}/${PKGMANDIR}/man1
47.endif 44.endif
48 45
49.include "../../lang/go/go-package.mk" 46.include "../../lang/go/go-package.mk"
 47.if !empty(PKGSRC_RUN_TEST:M[yY][eE][sS])
 48.include "../../devel/go-check/buildlink3.mk"
 49.endif
50.include "../../mk/bsd.pkg.mk" 50.include "../../mk/bsd.pkg.mk"

cvs diff -r1.6 -r1.7 pkgsrc/pkgtools/pkglint/files/Attic/check_test.go (expand / switch to unified diff)

--- pkgsrc/pkgtools/pkglint/files/Attic/check_test.go 2016/01/12 01:02:48 1.6
+++ pkgsrc/pkgtools/pkglint/files/Attic/check_test.go 2016/01/24 02:03:28 1.7
@@ -107,26 +107,34 @@ func (s *Suite) RegisterTool(toolname, v @@ -107,26 +107,34 @@ func (s *Suite) RegisterTool(toolname, v
107func (s *Suite) CreateTmpFile(c *check.C, relFname, content string) (absFname string) { 107func (s *Suite) CreateTmpFile(c *check.C, relFname, content string) (absFname string) {
108 if s.tmpdir == "" { 108 if s.tmpdir == "" {
109 s.tmpdir = filepath.ToSlash(c.MkDir()) 109 s.tmpdir = filepath.ToSlash(c.MkDir())
110 } 110 }
111 absFname = s.tmpdir + "/" + relFname 111 absFname = s.tmpdir + "/" + relFname
112 err := os.MkdirAll(path.Dir(absFname), 0777) 112 err := os.MkdirAll(path.Dir(absFname), 0777)
113 c.Assert(err, check.IsNil) 113 c.Assert(err, check.IsNil)
114 114
115 err = ioutil.WriteFile(absFname, []byte(content), 0666) 115 err = ioutil.WriteFile(absFname, []byte(content), 0666)
116 c.Check(err, check.IsNil) 116 c.Check(err, check.IsNil)
117 return 117 return
118} 118}
119 119
 120func (s *Suite) CreateTmpFileLines(c *check.C, relFname string, rawTexts ...string) (absFname string) {
 121 text := ""
 122 for _, rawText := range rawTexts {
 123 text += rawText + "\n"
 124 }
 125 return s.CreateTmpFile(c, relFname, text)
 126}
 127
120func (s *Suite) LoadTmpFile(c *check.C, relFname string) string { 128func (s *Suite) LoadTmpFile(c *check.C, relFname string) string {
121 bytes, err := ioutil.ReadFile(s.tmpdir + "/" + relFname) 129 bytes, err := ioutil.ReadFile(s.tmpdir + "/" + relFname)
122 c.Assert(err, check.IsNil) 130 c.Assert(err, check.IsNil)
123 return string(bytes) 131 return string(bytes)
124} 132}
125 133
126func (s *Suite) ExpectFatalError(action func()) { 134func (s *Suite) ExpectFatalError(action func()) {
127 if r := recover(); r != nil { 135 if r := recover(); r != nil {
128 if _, ok := r.(pkglintFatal); ok { 136 if _, ok := r.(pkglintFatal); ok {
129 action() 137 action()
130 return 138 return
131 } 139 }
132 panic(r) 140 panic(r)

cvs diff -r1.6 -r1.7 pkgsrc/pkgtools/pkglint/files/Attic/globaldata.go (expand / switch to unified diff)

--- pkgsrc/pkgtools/pkglint/files/Attic/globaldata.go 2016/01/12 01:02:48 1.6
+++ pkgsrc/pkgtools/pkglint/files/Attic/globaldata.go 2016/01/24 02:03:28 1.7
@@ -65,27 +65,27 @@ func (gd *GlobalData) Initialize() { @@ -65,27 +65,27 @@ func (gd *GlobalData) Initialize() {
65 gd.loadSuggestedUpdates() 65 gd.loadSuggestedUpdates()
66 gd.loadUserDefinedVars() 66 gd.loadUserDefinedVars()
67 gd.loadTools() 67 gd.loadTools()
68 gd.loadDeprecatedVars() 68 gd.loadDeprecatedVars()
69} 69}
70 70
71func (gd *GlobalData) loadDistSites() { 71func (gd *GlobalData) loadDistSites() {
72 fname := gd.Pkgsrcdir + "/mk/fetch/sites.mk" 72 fname := gd.Pkgsrcdir + "/mk/fetch/sites.mk"
73 lines := LoadExistingLines(fname, true) 73 lines := LoadExistingLines(fname, true)
74 74
75 names := make(map[string]bool) 75 names := make(map[string]bool)
76 url2name := make(map[string]string) 76 url2name := make(map[string]string)
77 for _, line := range lines { 77 for _, line := range lines {
78 if m, varname, _, urls, _ := MatchVarassign(line.Text); m { 78 if m, varname, _, _, urls, _ := MatchVarassign(line.Text); m {
79 if hasPrefix(varname, "MASTER_SITE_") && varname != "MASTER_SITE_BACKUP" { 79 if hasPrefix(varname, "MASTER_SITE_") && varname != "MASTER_SITE_BACKUP" {
80 names[varname] = true 80 names[varname] = true
81 for _, url := range splitOnSpace(urls) { 81 for _, url := range splitOnSpace(urls) {
82 if matches(url, `^(?:http://|https://|ftp://)`) { 82 if matches(url, `^(?:http://|https://|ftp://)`) {
83 url2name[url] = varname 83 url2name[url] = varname
84 } 84 }
85 } 85 }
86 } 86 }
87 } 87 }
88 } 88 }
89 89
90 // Explicitly allowed, although not defined in mk/fetch/sites.mk. 90 // Explicitly allowed, although not defined in mk/fetch/sites.mk.
91 names["MASTER_SITE_SUSE_UPD"] = true 91 names["MASTER_SITE_SUSE_UPD"] = true
@@ -129,27 +129,27 @@ func (gd *GlobalData) loadTools() { @@ -129,27 +129,27 @@ func (gd *GlobalData) loadTools() {
129 Fatalf(toolFiles[0], noLines, "Too few tool files.") 129 Fatalf(toolFiles[0], noLines, "Too few tool files.")
130 } 130 }
131 131
132 tools := make(map[string]bool) 132 tools := make(map[string]bool)
133 vartools := make(map[string]string) 133 vartools := make(map[string]string)
134 predefinedTools := make(map[string]bool) 134 predefinedTools := make(map[string]bool)
135 varnameToToolname := make(map[string]string) 135 varnameToToolname := make(map[string]string)
136 systemBuildDefs := make(map[string]bool) 136 systemBuildDefs := make(map[string]bool)
137 137
138 for _, basename := range toolFiles { 138 for _, basename := range toolFiles {
139 fname := G.globalData.Pkgsrcdir + "/mk/tools/" + basename 139 fname := G.globalData.Pkgsrcdir + "/mk/tools/" + basename
140 lines := LoadExistingLines(fname, true) 140 lines := LoadExistingLines(fname, true)
141 for _, line := range lines { 141 for _, line := range lines {
142 if m, varname, _, value, _ := MatchVarassign(line.Text); m { 142 if m, varname, _, _, value, _ := MatchVarassign(line.Text); m {
143 if varname == "TOOLS_CREATE" && (value == "[" || matches(value, `^?[-\w.]+$`)) { 143 if varname == "TOOLS_CREATE" && (value == "[" || matches(value, `^?[-\w.]+$`)) {
144 tools[value] = true 144 tools[value] = true
145 } else if m, toolname := match1(varname, `^(?:_TOOLS_VARNAME)\.([-\w.]+|\[)$`); m { 145 } else if m, toolname := match1(varname, `^(?:_TOOLS_VARNAME)\.([-\w.]+|\[)$`); m {
146 tools[toolname] = true 146 tools[toolname] = true
147 vartools[toolname] = value 147 vartools[toolname] = value
148 varnameToToolname[value] = toolname 148 varnameToToolname[value] = toolname
149 149
150 } else if m, toolname := match1(varname, `^(?:TOOLS_PATH|_TOOLS_DEPMETHOD)\.([-\w.]+|\[)$`); m { 150 } else if m, toolname := match1(varname, `^(?:TOOLS_PATH|_TOOLS_DEPMETHOD)\.([-\w.]+|\[)$`); m {
151 tools[toolname] = true 151 tools[toolname] = true
152 152
153 } else if m, toolname := match1(varname, `_TOOLS\.(.*)`); m { 153 } else if m, toolname := match1(varname, `_TOOLS\.(.*)`); m {
154 tools[toolname] = true 154 tools[toolname] = true
155 for _, tool := range splitOnSpace(value) { 155 for _, tool := range splitOnSpace(value) {
@@ -159,27 +159,27 @@ func (gd *GlobalData) loadTools() { @@ -159,27 +159,27 @@ func (gd *GlobalData) loadTools() {
159 } 159 }
160 } 160 }
161 } 161 }
162 162
163 { 163 {
164 basename := "bsd.pkg.mk" 164 basename := "bsd.pkg.mk"
165 fname := G.globalData.Pkgsrcdir + "/mk/" + basename 165 fname := G.globalData.Pkgsrcdir + "/mk/" + basename
166 condDepth := 0 166 condDepth := 0
167 167
168 lines := LoadExistingLines(fname, true) 168 lines := LoadExistingLines(fname, true)
169 for _, line := range lines { 169 for _, line := range lines {
170 text := line.Text 170 text := line.Text
171 171
172 if m, varname, _, value, _ := MatchVarassign(text); m { 172 if m, varname, _, _, value, _ := MatchVarassign(text); m {
173 if varname == "USE_TOOLS" { 173 if varname == "USE_TOOLS" {
174 if G.opts.DebugTools { 174 if G.opts.DebugTools {
175 line.Debugf("[condDepth=%d] %s", condDepth, value) 175 line.Debugf("[condDepth=%d] %s", condDepth, value)
176 } 176 }
177 if condDepth == 0 { 177 if condDepth == 0 {
178 for _, tool := range splitOnSpace(value) { 178 for _, tool := range splitOnSpace(value) {
179 if !containsVarRef(tool) && tools[tool] { 179 if !containsVarRef(tool) && tools[tool] {
180 predefinedTools[tool] = true 180 predefinedTools[tool] = true
181 predefinedTools["TOOLS_"+tool] = true 181 predefinedTools["TOOLS_"+tool] = true
182 } 182 }
183 } 183 }
184 } 184 }
185 185

cvs diff -r1.6 -r1.7 pkgsrc/pkgtools/pkglint/files/Attic/mkline_test.go (expand / switch to unified diff)

--- pkgsrc/pkgtools/pkglint/files/Attic/mkline_test.go 2016/01/12 01:02:49 1.6
+++ pkgsrc/pkgtools/pkglint/files/Attic/mkline_test.go 2016/01/24 02:03:28 1.7
@@ -22,69 +22,228 @@ func (s *Suite) TestChecklineMkVartype_S @@ -22,69 +22,228 @@ func (s *Suite) TestChecklineMkVartype_S
22 22
23 mkline.CheckVartype("COMMENT", opAssign, "A nice package", "") 23 mkline.CheckVartype("COMMENT", opAssign, "A nice package", "")
24 24
25 c.Check(s.Stdout(), equals, "WARN: fname:1: COMMENT should not begin with \"A\".\n") 25 c.Check(s.Stdout(), equals, "WARN: fname:1: COMMENT should not begin with \"A\".\n")
26} 26}
27 27
28func (s *Suite) TestChecklineMkVartype(c *check.C) { 28func (s *Suite) TestChecklineMkVartype(c *check.C) {
29 G.globalData.InitVartypes() 29 G.globalData.InitVartypes()
30 mkline := NewMkLine(NewLine("fname", 1, "DISTNAME=gcc-${GCC_VERSION}", nil)) 30 mkline := NewMkLine(NewLine("fname", 1, "DISTNAME=gcc-${GCC_VERSION}", nil))
31 31
32 mkline.CheckVartype("DISTNAME", opAssign, "gcc-${GCC_VERSION}", "") 32 mkline.CheckVartype("DISTNAME", opAssign, "gcc-${GCC_VERSION}", "")
33} 33}
34 34
35func (s *Suite) TestChecklineMkVaralign(c *check.C) { 35func (s *Suite) TestMkLine_CheckVaralign_Autofix(c *check.C) {
36 s.UseCommandLine(c, "-Wspace", "-f") 36 s.UseCommandLine(c, "-Wspace", "-f")
37 lines := s.NewLines("file.mk", 37 lines := s.NewLines("file.mk",
38 "VAR= value", // Indentation 7, fixed to 8. 38 "VAR= value", // Indentation 7, fixed to 8.
 39 "", //
39 "VAR= value", // Indentation 8, fixed to 8. 40 "VAR= value", // Indentation 8, fixed to 8.
40 "VAR= value", // Indentation 9, fixed to 16. 41 "", //
 42 "VAR= value", // Indentation 9, fixed to 8.
 43 "", //
41 "VAR= \tvalue", // Mixed indentation 8, fixed to 8. 44 "VAR= \tvalue", // Mixed indentation 8, fixed to 8.
 45 "", //
42 "VAR= \tvalue", // Mixed indentation 8, fixed to 8. 46 "VAR= \tvalue", // Mixed indentation 8, fixed to 8.
43 "VAR= \tvalue", // Mixed indentation 16, fixed to 16. 47 "", //
 48 "VAR= \tvalue", // Mixed indentation 16, fixed to 8.
 49 "", //
44 "VAR=\tvalue") // Already aligned with tabs only, left unchanged. 50 "VAR=\tvalue") // Already aligned with tabs only, left unchanged.
45 51
 52 varalign := new(VaralignBlock)
46 for _, line := range lines { 53 for _, line := range lines {
47 NewMkLine(line).CheckVaralign() 54 varalign.Check(NewMkLine(line))
48 } 55 }
 56 varalign.Finish()
49 57
50 c.Check(lines[0].changed, equals, true) 58 c.Check(lines[0].changed, equals, true)
51 c.Check(lines[0].rawLines()[0].String(), equals, "1:VAR=\tvalue\n") 59 c.Check(lines[0].rawLines()[0].String(), equals, "1:VAR=\tvalue\n")
52 c.Check(lines[1].changed, equals, true) 
53 c.Check(lines[1].rawLines()[0].String(), equals, "2:VAR=\tvalue\n") 
54 c.Check(lines[2].changed, equals, true) 60 c.Check(lines[2].changed, equals, true)
55 c.Check(lines[2].rawLines()[0].String(), equals, "3:VAR=\t\tvalue\n") 61 c.Check(lines[2].rawLines()[0].String(), equals, "3:VAR=\tvalue\n")
56 c.Check(lines[3].changed, equals, true) 
57 c.Check(lines[3].rawLines()[0].String(), equals, "4:VAR=\tvalue\n") 
58 c.Check(lines[4].changed, equals, true) 62 c.Check(lines[4].changed, equals, true)
59 c.Check(lines[4].rawLines()[0].String(), equals, "5:VAR=\tvalue\n") 63 c.Check(lines[4].rawLines()[0].String(), equals, "5:VAR=\tvalue\n")
60 c.Check(lines[5].changed, equals, true) 64 c.Check(lines[6].changed, equals, true)
61 c.Check(lines[5].rawLines()[0].String(), equals, "6:VAR=\t\tvalue\n") 
62 c.Check(lines[6].changed, equals, false) 
63 c.Check(lines[6].rawLines()[0].String(), equals, "7:VAR=\tvalue\n") 65 c.Check(lines[6].rawLines()[0].String(), equals, "7:VAR=\tvalue\n")
 66 c.Check(lines[8].changed, equals, true)
 67 c.Check(lines[8].rawLines()[0].String(), equals, "9:VAR=\tvalue\n")
 68 c.Check(lines[10].changed, equals, true)
 69 c.Check(lines[10].rawLines()[0].String(), equals, "11:VAR=\tvalue\n")
 70 c.Check(lines[12].changed, equals, false)
 71 c.Check(lines[12].rawLines()[0].String(), equals, "13:VAR=\tvalue\n")
64 c.Check(s.Output(), equals, ""+ 72 c.Check(s.Output(), equals, ""+
65 "NOTE: file.mk:1: Alignment of variable values should be done with tabs, not spaces.\n"+ 73 "NOTE: file.mk:1: This variable value should be aligned with tabs, not spaces, to column 9.\n"+
66 "AUTOFIX: file.mk:1: Replacing \"VAR= \" with \"VAR=\\t\".\n"+ 74 "AUTOFIX: file.mk:1: Replacing \"VAR= \" with \"VAR=\\t\".\n"+
67 "NOTE: file.mk:2: Alignment of variable values should be done with tabs, not spaces.\n"+ 75 "NOTE: file.mk:3: Variable values should be aligned with tabs, not spaces.\n"+
68 "AUTOFIX: file.mk:2: Replacing \"VAR= \" with \"VAR=\\t\".\n"+ 76 "AUTOFIX: file.mk:3: Replacing \"VAR= \" with \"VAR=\\t\".\n"+
69 "NOTE: file.mk:3: Alignment of variable values should be done with tabs, not spaces.\n"+ 77 "NOTE: file.mk:5: This variable value should be aligned with tabs, not spaces, to column 9.\n"+
70 "AUTOFIX: file.mk:3: Replacing \"VAR= \" with \"VAR=\\t\\t\".\n"+ 78 "AUTOFIX: file.mk:5: Replacing \"VAR= \" with \"VAR=\\t\".\n"+
71 "NOTE: file.mk:4: Alignment of variable values should be done with tabs, not spaces.\n"+ 79 "NOTE: file.mk:7: Variable values should be aligned with tabs, not spaces.\n"+
72 "AUTOFIX: file.mk:4: Replacing \"VAR= \\t\" with \"VAR=\\t\".\n"+ 80 "AUTOFIX: file.mk:7: Replacing \"VAR= \\t\" with \"VAR=\\t\".\n"+
73 "NOTE: file.mk:5: Alignment of variable values should be done with tabs, not spaces.\n"+ 81 "NOTE: file.mk:9: Variable values should be aligned with tabs, not spaces.\n"+
74 "AUTOFIX: file.mk:5: Replacing \"VAR= \\t\" with \"VAR=\\t\".\n"+ 82 "AUTOFIX: file.mk:9: Replacing \"VAR= \\t\" with \"VAR=\\t\".\n"+
75 "NOTE: file.mk:6: Alignment of variable values should be done with tabs, not spaces.\n"+ 83 "NOTE: file.mk:11: This variable value should be aligned with tabs, not spaces, to column 9.\n"+
76 "AUTOFIX: file.mk:6: Replacing \"VAR= \\t\" with \"VAR=\\t\\t\".\n") 84 "AUTOFIX: file.mk:11: Replacing \"VAR= \\t\" with \"VAR=\\t\".\n")
77 c.Check(tabLength("VAR= \t"), equals, 16) 85}
 86
 87func (s *Suite) TestMkLine_CheckVaralign_ReduceIndentation(c *check.C) {
 88 s.UseCommandLine(c, "-Wspace")
 89 mklines := s.NewMkLines("file.mk",
 90 "VAR= \tvalue",
 91 "VAR= \tvalue",
 92 "VAR=\t\t\t\tvalue",
 93 "",
 94 "VAR=\t\t\tneedlessly", // Nothing to be fixed here, since it looks good.
 95 "VAR=\t\t\tdeep",
 96 "VAR=\t\t\tindentation")
 97
 98 varalign := new(VaralignBlock)
 99 for _, mkline := range mklines.mklines {
 100 varalign.Check(mkline)
 101 }
 102 varalign.Finish()
 103
 104 c.Check(s.Output(), equals, ""+
 105 "NOTE: file.mk:1: Variable values should be aligned with tabs, not spaces.\n"+
 106 "NOTE: file.mk:2: This variable value should be aligned with tabs, not spaces, to column 9.\n"+
 107 "NOTE: file.mk:3: This variable value should be aligned to column 9.\n")
 108}
 109
 110func (s *Suite) TestMkLine_CheckVaralign_LongestLineEmptyAlignment(c *check.C) {
 111 s.UseCommandLine(c, "-Wspace")
 112 mklines := s.NewMkLines("file.mk",
 113 "SUBST_CLASSES+= aaaaaaaa",
 114 "SUBST_STAGE.aaaaaaaa= pre-configure",
 115 "SUBST_FILES.aaaaaaaa= *.pl",
 116 "SUBST_FILTER_CMD.aaaaaaaa=cat")
 117
 118 varalign := new(VaralignBlock)
 119 for _, mkline := range mklines.mklines {
 120 varalign.Check(mkline)
 121 }
 122 varalign.Finish()
 123
 124 c.Check(s.Output(), equals, ""+
 125 "NOTE: file.mk:1: This variable value should be aligned with tabs, not spaces, to column 33.\n"+
 126 "NOTE: file.mk:2: This variable value should be aligned with tabs, not spaces, to column 33.\n"+
 127 "NOTE: file.mk:3: This variable value should be aligned with tabs, not spaces, to column 33.\n"+
 128 "NOTE: file.mk:4: This variable value should be aligned to column 33.\n")
 129}
 130
 131func (s *Suite) TestMkLine_CheckVaralign_OnlySpaces(c *check.C) {
 132 s.UseCommandLine(c, "-Wspace")
 133 mklines := s.NewMkLines("file.mk",
 134 "SUBST_CLASSES+= aaaaaaaa",
 135 "SUBST_STAGE.aaaaaaaa= pre-configure",
 136 "SUBST_FILES.aaaaaaaa= *.pl",
 137 "SUBST_FILTER_CMD.aaaaaaaa= cat")
 138
 139 varalign := new(VaralignBlock)
 140 for _, mkline := range mklines.mklines {
 141 varalign.Check(mkline)
 142 }
 143 varalign.Finish()
 144
 145 c.Check(s.Output(), equals, ""+
 146 "NOTE: file.mk:1: This variable value should be aligned with tabs, not spaces, to column 33.\n"+
 147 "NOTE: file.mk:2: This variable value should be aligned with tabs, not spaces, to column 33.\n"+
 148 "NOTE: file.mk:3: This variable value should be aligned with tabs, not spaces, to column 33.\n"+
 149 "NOTE: file.mk:4: This variable value should be aligned with tabs, not spaces, to column 33.\n")
 150}
 151
 152func (s *Suite) TestMkLine_CheckVaralign_Advanced(c *check.C) {
 153 s.UseCommandLine(c, "-Wspace")
 154 fname := s.CreateTmpFileLines(c, "Makefile",
 155 "# $"+"NetBSD$",
 156 "",
 157 "VAR= \\", // In continuation lines, indenting with spaces is ok
 158 "\tvalue",
 159 "",
 160 "VAR= indented with one space", // Exactly one space is ok in general
 161 "VAR= indented with two spaces", // Two spaces are uncommon
 162 "",
 163 "BLOCK=\tindented with tab",
 164 "BLOCK_LONGVAR= indented with space", // This is ok, to prevent the block from being indented further
 165 "",
 166 "BLOCK=\tshort",
 167 "BLOCK_LONGVAR=\tlong",
 168 "",
 169 "GRP_A= avalue", // The values in a block should be aligned
 170 "GRP_AA= value",
 171 "GRP_AAA= value",
 172 "GRP_AAAA= value",
 173 "",
 174 "VAR=\t${VAR}${BLOCK}${BLOCK_LONGVAR} # suppress warnings about unused variables",
 175 "VAR=\t${GRP_A}${GRP_AA}${GRP_AAA}${GRP_AAAA}")
 176 mklines := NewMkLines(LoadExistingLines(fname, true))
 177
 178 mklines.Check()
 179
 180 c.Check(s.OutputCleanTmpdir(), equals, ""+
 181 "NOTE: ~/Makefile:6: This variable value should be aligned with tabs, not spaces, to column 9.\n"+
 182 "NOTE: ~/Makefile:7: This variable value should be aligned with tabs, not spaces, to column 9.\n"+
 183 "NOTE: ~/Makefile:12: This variable value should be aligned to column 17.\n"+
 184 "NOTE: ~/Makefile:15: This variable value should be aligned with tabs, not spaces, to column 17.\n"+
 185 "NOTE: ~/Makefile:16: This variable value should be aligned with tabs, not spaces, to column 17.\n"+
 186 "NOTE: ~/Makefile:17: This variable value should be aligned with tabs, not spaces, to column 17.\n"+
 187 "NOTE: ~/Makefile:18: This variable value should be aligned with tabs, not spaces, to column 17.\n")
 188
 189 s.UseCommandLine(c, "-Wspace", "--autofix")
 190
 191 mklines.Check()
 192
 193 c.Check(s.OutputCleanTmpdir(), equals, ""+
 194 "AUTOFIX: ~/Makefile:6: Replacing \"VAR= \" with \"VAR=\\t\".\n"+
 195 "AUTOFIX: ~/Makefile:7: Replacing \"VAR= \" with \"VAR=\\t\".\n"+
 196 "AUTOFIX: ~/Makefile:12: Replacing \"BLOCK=\\t\" with \"BLOCK=\\t\\t\".\n"+
 197 "AUTOFIX: ~/Makefile:15: Replacing \"GRP_A= \" with \"GRP_A=\\t\\t\".\n"+
 198 "AUTOFIX: ~/Makefile:16: Replacing \"GRP_AA= \" with \"GRP_AA=\\t\\t\".\n"+
 199 "AUTOFIX: ~/Makefile:17: Replacing \"GRP_AAA= \" with \"GRP_AAA=\\t\".\n"+
 200 "AUTOFIX: ~/Makefile:18: Replacing \"GRP_AAAA= \" with \"GRP_AAAA=\\t\".\n"+
 201 "AUTOFIX: ~/Makefile: Has been auto-fixed. Please re-run pkglint.\n")
 202 c.Check(s.LoadTmpFile(c, "Makefile"), equals, ""+
 203 "# $NetBSD: mkline_test.go,v 1.7 2016/01/24 02:03:28 rillig Exp $\n"+
 204 "\n"+
 205 "VAR= \\\n"+
 206 "\tvalue\n"+
 207 "\n"+
 208 "VAR=\tindented with one space\n"+
 209 "VAR=\tindented with two spaces\n"+
 210 "\n"+
 211 "BLOCK=\tindented with tab\n"+
 212 "BLOCK_LONGVAR= indented with space\n"+
 213 "\n"+
 214 "BLOCK=\t\tshort\n"+
 215 "BLOCK_LONGVAR=\tlong\n"+
 216 "\n"+
 217 "GRP_A=\t\tavalue\n"+
 218 "GRP_AA=\t\tvalue\n"+
 219 "GRP_AAA=\tvalue\n"+
 220 "GRP_AAAA=\tvalue\n"+
 221 "\n"+
 222 "VAR=\t${VAR}${BLOCK}${BLOCK_LONGVAR} # suppress warnings about unused variables\n"+
 223 "VAR=\t${GRP_A}${GRP_AA}${GRP_AAA}${GRP_AAAA}\n")
 224}
 225
 226func (s *Suite) TestMkLine_CheckVaralign_Misc(c *check.C) {
 227 s.UseCommandLine(c, "-Wspace")
 228 mklines := s.NewMkLines("Makefile",
 229 "# $"+"NetBSD$",
 230 "",
 231 "VAR= space",
 232 "VAR=\ttab ${VAR}")
 233
 234 mklines.Check()
 235
 236 c.Check(s.Output(), equals, "NOTE: Makefile:3: Variable values should be aligned with tabs, not spaces.\n")
78} 237}
79 238
80func (s *Suite) TestMkLine_fields(c *check.C) { 239func (s *Suite) TestMkLine_fields(c *check.C) {
81 mklines := NewMkLines(s.NewLines("test.mk", 240 mklines := NewMkLines(s.NewLines("test.mk",
82 "VARNAME.param?=value # varassign comment", 241 "VARNAME.param?=value # varassign comment",
83 "\tshell command # shell comment", 242 "\tshell command # shell comment",
84 "# whole line comment", 243 "# whole line comment",
85 "", 244 "",
86 ". if !empty(PKGNAME:M*-*) # cond comment", 245 ". if !empty(PKGNAME:M*-*) # cond comment",
87 ".include \"../../mk/bsd.prefs.mk\" # include comment", 246 ".include \"../../mk/bsd.prefs.mk\" # include comment",
88 ".include <subdir.mk> # sysinclude comment", 247 ".include <subdir.mk> # sysinclude comment",
89 "target1 target2: source1 source2", 248 "target1 target2: source1 source2",
90 "target : source", 249 "target : source",
@@ -275,27 +434,28 @@ func (s *Suite) TestMkLine_CheckVarusePe @@ -275,27 +434,28 @@ func (s *Suite) TestMkLine_CheckVarusePe
275 "COMMENT:=\t${PKGBASE}", 434 "COMMENT:=\t${PKGBASE}",
276 "PYPKGPREFIX=${PKGBASE}") 435 "PYPKGPREFIX=${PKGBASE}")
277 G.globalData.UserDefinedVars = map[string]*MkLine{ 436 G.globalData.UserDefinedVars = map[string]*MkLine{
278 "GAMES_USER": mklines.mklines[0], 437 "GAMES_USER": mklines.mklines[0],
279 } 438 }
280 439
281 mklines.Check() 440 mklines.Check()
282 441
283 c.Check(s.Output(), equals, ""+ 442 c.Check(s.Output(), equals, ""+
284 "WARN: options.mk:2: The user-defined variable GAMES_USER is used but not added to BUILD_DEFS.\n"+ 443 "WARN: options.mk:2: The user-defined variable GAMES_USER is used but not added to BUILD_DEFS.\n"+
285 "WARN: options.mk:3: PKGBASE should not be evaluated at load time.\n"+ 444 "WARN: options.mk:3: PKGBASE should not be evaluated at load time.\n"+
286 "WARN: options.mk:4: The variable PYPKGPREFIX may not be set in this file; it would be ok in pyversion.mk.\n"+ 445 "WARN: options.mk:4: The variable PYPKGPREFIX may not be set in this file; it would be ok in pyversion.mk.\n"+
287 "WARN: options.mk:4: \"${PKGBASE}\" is not valid for PYPKGPREFIX. Use one of { py27 py33 py34 } instead.\n"+ 446 "WARN: options.mk:4: \"${PKGBASE}\" is not valid for PYPKGPREFIX. Use one of { py27 py33 py34 } instead.\n"+
288 "WARN: options.mk:4: PKGBASE should not be evaluated indirectly at load time.\n") 447 "WARN: options.mk:4: PKGBASE should not be evaluated indirectly at load time.\n"+
 448 "NOTE: options.mk:4: This variable value should be aligned to column 17.\n")
289} 449}
290 450
291func (s *Suite) TestMkLine_WarnVaruseLocalbase(c *check.C) { 451func (s *Suite) TestMkLine_WarnVaruseLocalbase(c *check.C) {
292 mkline := NewMkLine(NewLine("options.mk", 56, "PKGNAME=${LOCALBASE}", nil)) 452 mkline := NewMkLine(NewLine("options.mk", 56, "PKGNAME=${LOCALBASE}", nil))
293 453
294 mkline.WarnVaruseLocalbase() 454 mkline.WarnVaruseLocalbase()
295 455
296 c.Check(s.Output(), equals, "WARN: options.mk:56: The LOCALBASE variable should not be used by packages.\n") 456 c.Check(s.Output(), equals, "WARN: options.mk:56: The LOCALBASE variable should not be used by packages.\n")
297} 457}
298 458
299func (s *Suite) TestMkLine_Misc(c *check.C) { 459func (s *Suite) TestMkLine_Misc(c *check.C) {
300 s.UseCommandLine(c, "-Wextra") 460 s.UseCommandLine(c, "-Wextra")
301 G.globalData.InitVartypes() 461 G.globalData.InitVartypes()

cvs diff -r1.6 -r1.7 pkgsrc/pkgtools/pkglint/files/Attic/pkglint.go (expand / switch to unified diff)

--- pkgsrc/pkgtools/pkglint/files/Attic/pkglint.go 2016/01/12 01:02:49 1.6
+++ pkgsrc/pkgtools/pkglint/files/Attic/pkglint.go 2016/01/24 02:03:28 1.7
@@ -293,27 +293,27 @@ func Checkfile(fname string) { @@ -293,27 +293,27 @@ func Checkfile(fname string) {
293} 293}
294 294
295func ChecklinesTrailingEmptyLines(lines []*Line) { 295func ChecklinesTrailingEmptyLines(lines []*Line) {
296 max := len(lines) 296 max := len(lines)
297 last := max 297 last := max
298 for last > 1 && lines[last-1].Text == "" { 298 for last > 1 && lines[last-1].Text == "" {
299 last-- 299 last--
300 } 300 }
301 if last != max { 301 if last != max {
302 lines[last].Note0("Trailing empty lines.") 302 lines[last].Note0("Trailing empty lines.")
303 } 303 }
304} 304}
305 305
306func MatchVarassign(text string) (m bool, varname, op, value, comment string) { 306func MatchVarassign(text string) (m bool, varname, op, valueAlign, value, comment string) {
307 i, n := 0, len(text) 307 i, n := 0, len(text)
308 308
309 for i < n && text[i] == ' ' { 309 for i < n && text[i] == ' ' {
310 i++ 310 i++
311 } 311 }
312 312
313 varnameStart := i 313 varnameStart := i
314 for ; i < n; i++ { 314 for ; i < n; i++ {
315 b := text[i] 315 b := text[i]
316 mask := uint(0) 316 mask := uint(0)
317 switch b & 0xE0 { 317 switch b & 0xE0 {
318 case 0x20: 318 case 0x20:
319 mask = 0x03ff6c10 319 mask = 0x03ff6c10
@@ -328,27 +328,27 @@ func MatchVarassign(text string) (m bool @@ -328,27 +328,27 @@ func MatchVarassign(text string) (m bool
328 } 328 }
329 varnameEnd := i 329 varnameEnd := i
330 330
331 if varnameEnd == varnameStart { 331 if varnameEnd == varnameStart {
332 return 332 return
333 } 333 }
334 334
335 for i < n && (text[i] == ' ' || text[i] == '\t') { 335 for i < n && (text[i] == ' ' || text[i] == '\t') {
336 i++ 336 i++
337 } 337 }
338 338
339 opStart := i 339 opStart := i
340 if i < n { 340 if i < n {
341 if b := text[i]; b&0xE0 == 0x20 && (uint(0x84000802)>>(b&0x1F))&1 != 0 { 341 if b := text[i]; b == '!' || b == '+' || b == ':' || b == '?' {
342 i++ 342 i++
343 } 343 }
344 } 344 }
345 if i < n && text[i] == '=' { 345 if i < n && text[i] == '=' {
346 i++ 346 i++
347 } else { 347 } else {
348 return 348 return
349 } 349 }
350 opEnd := i 350 opEnd := i
351 351
352 if text[varnameEnd-1] == '+' && varnameEnd == opStart && text[opStart] == '=' { 352 if text[varnameEnd-1] == '+' && varnameEnd == opStart && text[opStart] == '=' {
353 varnameEnd-- 353 varnameEnd--
354 opStart-- 354 opStart--
@@ -367,26 +367,27 @@ func MatchVarassign(text string) (m bool @@ -367,26 +367,27 @@ func MatchVarassign(text string) (m bool
367 break 367 break
368 } else if b != '\\' || i+1 >= n || text[i+1] != '#' { 368 } else if b != '\\' || i+1 >= n || text[i+1] != '#' {
369 valuebuf[j] = b 369 valuebuf[j] = b
370 j++ 370 j++
371 } 371 }
372 } 372 }
373 373
374 commentStart := i 374 commentStart := i
375 commentEnd := n 375 commentEnd := n
376 376
377 m = true 377 m = true
378 varname = text[varnameStart:varnameEnd] 378 varname = text[varnameStart:varnameEnd]
379 op = text[opStart:opEnd] 379 op = text[opStart:opEnd]
 380 valueAlign = text[0:valueStart]
380 value = strings.TrimSpace(string(valuebuf[:j])) 381 value = strings.TrimSpace(string(valuebuf[:j]))
381 comment = text[commentStart:commentEnd] 382 comment = text[commentStart:commentEnd]
382 return 383 return
383} 384}
384 385
385type DependencyPattern struct { 386type DependencyPattern struct {
386 pkgbase string // "freeciv-client", "{gcc48,gcc48-libs}", "${EMACS_REQD}" 387 pkgbase string // "freeciv-client", "{gcc48,gcc48-libs}", "${EMACS_REQD}"
387 lowerOp string // ">=", ">" 388 lowerOp string // ">=", ">"
388 lower string // "2.5.0", "${PYVER}" 389 lower string // "2.5.0", "${PYVER}"
389 upperOp string // "<", "<=" 390 upperOp string // "<", "<="
390 upper string // "3.0", "${PYVER}" 391 upper string // "3.0", "${PYVER}"
391 wildcard string // "[0-9]*", "1.5.*", "${PYVER}" 392 wildcard string // "[0-9]*", "1.5.*", "${PYVER}"
392} 393}

cvs diff -r1.7 -r1.8 pkgsrc/pkgtools/pkglint/files/Attic/mkline.go (expand / switch to unified diff)

--- pkgsrc/pkgtools/pkglint/files/Attic/mkline.go 2016/01/12 01:02:49 1.7
+++ pkgsrc/pkgtools/pkglint/files/Attic/mkline.go 2016/01/24 02:03:28 1.8
@@ -5,26 +5,27 @@ package main @@ -5,26 +5,27 @@ package main
5import ( 5import (
6 "fmt" 6 "fmt"
7 "os" 7 "os"
8 "strconv" 8 "strconv"
9 "strings" 9 "strings"
10) 10)
11 11
12type MkLine struct { 12type MkLine struct {
13 Line *Line 13 Line *Line
14 14
15 xtype uint8 15 xtype uint8
16 xmustexist bool 16 xmustexist bool
17 xop MkOperator 17 xop MkOperator
 18 xvalign string
18 xs1 string 19 xs1 string
19 xs2 string 20 xs2 string
20 xs3 string 21 xs3 string
21 xvalue string 22 xvalue string
22 xcomment string 23 xcomment string
23} 24}
24 25
25func (mkline *MkLine) Error1(format, arg1 string) { mkline.Line.Error1(format, arg1) } 26func (mkline *MkLine) Error1(format, arg1 string) { mkline.Line.Error1(format, arg1) }
26func (mkline *MkLine) Warn0(format string) { mkline.Line.Warn0(format) } 27func (mkline *MkLine) Warn0(format string) { mkline.Line.Warn0(format) }
27func (mkline *MkLine) Warn1(format, arg1 string) { mkline.Line.Warn1(format, arg1) } 28func (mkline *MkLine) Warn1(format, arg1 string) { mkline.Line.Warn1(format, arg1) }
28func (mkline *MkLine) Warn2(format, arg1, arg2 string) { mkline.Line.Warn2(format, arg1, arg2) } 29func (mkline *MkLine) Warn2(format, arg1, arg2 string) { mkline.Line.Warn2(format, arg1, arg2) }
29func (mkline *MkLine) Note0(format string) { mkline.Line.Note0(format) } 30func (mkline *MkLine) Note0(format string) { mkline.Line.Note0(format) }
30func (mkline *MkLine) Note2(format, arg1, arg2 string) { mkline.Line.Note2(format, arg1, arg2) } 31func (mkline *MkLine) Note2(format, arg1, arg2 string) { mkline.Line.Note2(format, arg1, arg2) }
@@ -34,35 +35,36 @@ func (mkline *MkLine) Debug2(format, arg @@ -34,35 +35,36 @@ func (mkline *MkLine) Debug2(format, arg
34func NewMkLine(line *Line) (mkline *MkLine) { 35func NewMkLine(line *Line) (mkline *MkLine) {
35 mkline = &MkLine{Line: line} 36 mkline = &MkLine{Line: line}
36 37
37 text := line.Text 38 text := line.Text
38 39
39 if hasPrefix(text, " ") { 40 if hasPrefix(text, " ") {
40 mkline.Warn0("Makefile lines should not start with space characters.") 41 mkline.Warn0("Makefile lines should not start with space characters.")
41 Explain3( 42 Explain3(
42 "If you want this line to contain a shell program, use a tab", 43 "If you want this line to contain a shell program, use a tab",
43 "character for indentation. Otherwise please remove the leading", 44 "character for indentation. Otherwise please remove the leading",
44 "white-space.") 45 "white-space.")
45 } 46 }
46 47
47 if m, varname, op, value, comment := MatchVarassign(text); m { 48 if m, varname, op, valueAlign, value, comment := MatchVarassign(text); m {
48 value = strings.Replace(value, "\\#", "#", -1) 49 value = strings.Replace(value, "\\#", "#", -1)
49 varparam := varnameParam(varname) 50 varparam := varnameParam(varname)
50 51
51 mkline.xtype = 1 52 mkline.xtype = 1
52 mkline.xs1 = varname 53 mkline.xs1 = varname
53 mkline.xs2 = varnameCanon(varname) 54 mkline.xs2 = varnameCanon(varname)
54 mkline.xs3 = varparam 55 mkline.xs3 = varparam
55 mkline.xop = NewMkOperator(op) 56 mkline.xop = NewMkOperator(op)
 57 mkline.xvalign = valueAlign
56 mkline.xvalue = value 58 mkline.xvalue = value
57 mkline.xcomment = comment 59 mkline.xcomment = comment
58 mkline.Tokenize(value) 60 mkline.Tokenize(value)
59 return 61 return
60 } 62 }
61 63
62 if hasPrefix(text, "\t") { 64 if hasPrefix(text, "\t") {
63 mkline.xtype = 2 65 mkline.xtype = 2
64 mkline.xs1 = text[1:] 66 mkline.xs1 = text[1:]
65 mkline.Tokenize(mkline.xs1) 67 mkline.Tokenize(mkline.xs1)
66 return 68 return
67 } 69 }
68 70
@@ -112,26 +114,27 @@ func NewMkLine(line *Line) (mkline *MkLi @@ -112,26 +114,27 @@ func NewMkLine(line *Line) (mkline *MkLi
112 if matches(text, `^(<<<<<<<|=======|>>>>>>>)`) { 114 if matches(text, `^(<<<<<<<|=======|>>>>>>>)`) {
113 return 115 return
114 } 116 }
115 117
116 line.Error0("Unknown Makefile line format.") 118 line.Error0("Unknown Makefile line format.")
117 return mkline 119 return mkline
118} 120}
119 121
120func (mkline *MkLine) IsVarassign() bool { return mkline.xtype == 1 } 122func (mkline *MkLine) IsVarassign() bool { return mkline.xtype == 1 }
121func (mkline *MkLine) Varname() string { return mkline.xs1 } 123func (mkline *MkLine) Varname() string { return mkline.xs1 }
122func (mkline *MkLine) Varcanon() string { return mkline.xs2 } 124func (mkline *MkLine) Varcanon() string { return mkline.xs2 }
123func (mkline *MkLine) Varparam() string { return mkline.xs3 } 125func (mkline *MkLine) Varparam() string { return mkline.xs3 }
124func (mkline *MkLine) Op() MkOperator { return mkline.xop } 126func (mkline *MkLine) Op() MkOperator { return mkline.xop }
 127func (mkline *MkLine) ValueAlign() string { return mkline.xvalign }
125func (mkline *MkLine) Value() string { return mkline.xvalue } 128func (mkline *MkLine) Value() string { return mkline.xvalue }
126func (mkline *MkLine) Comment() string { return mkline.xcomment } 129func (mkline *MkLine) Comment() string { return mkline.xcomment }
127func (mkline *MkLine) IsShellcmd() bool { return mkline.xtype == 2 } 130func (mkline *MkLine) IsShellcmd() bool { return mkline.xtype == 2 }
128func (mkline *MkLine) Shellcmd() string { return mkline.xs1 } 131func (mkline *MkLine) Shellcmd() string { return mkline.xs1 }
129func (mkline *MkLine) IsComment() bool { return mkline.xtype == 3 } 132func (mkline *MkLine) IsComment() bool { return mkline.xtype == 3 }
130func (mkline *MkLine) IsEmpty() bool { return mkline.xtype == 4 } 133func (mkline *MkLine) IsEmpty() bool { return mkline.xtype == 4 }
131func (mkline *MkLine) IsCond() bool { return mkline.xtype == 5 } 134func (mkline *MkLine) IsCond() bool { return mkline.xtype == 5 }
132func (mkline *MkLine) Indent() string { return mkline.xs1 } 135func (mkline *MkLine) Indent() string { return mkline.xs1 }
133func (mkline *MkLine) Directive() string { return mkline.xs2 } 136func (mkline *MkLine) Directive() string { return mkline.xs2 }
134func (mkline *MkLine) Args() string { return mkline.xs3 } 137func (mkline *MkLine) Args() string { return mkline.xs3 }
135func (mkline *MkLine) IsInclude() bool { return mkline.xtype == 6 } 138func (mkline *MkLine) IsInclude() bool { return mkline.xtype == 6 }
136func (mkline *MkLine) MustExist() bool { return mkline.xmustexist } 139func (mkline *MkLine) MustExist() bool { return mkline.xmustexist }
137func (mkline *MkLine) Includefile() string { return mkline.xs1 } 140func (mkline *MkLine) Includefile() string { return mkline.xs1 }
@@ -743,45 +746,26 @@ func (mkline *MkLine) withoutMakeVariabl @@ -743,45 +746,26 @@ func (mkline *MkLine) withoutMakeVariabl
743 for { 746 for {
744 var m []string 747 var m []string
745 if m, valueNovar = replaceFirst(valueNovar, `\$\{([^{}]*)\}`, ""); m != nil { 748 if m, valueNovar = replaceFirst(valueNovar, `\$\{([^{}]*)\}`, ""); m != nil {
746 varuse := m[1] 749 varuse := m[1]
747 if !qModifierAllowed && hasSuffix(varuse, ":Q") { 750 if !qModifierAllowed && hasSuffix(varuse, ":Q") {
748 mkline.Warn0("The :Q operator should only be used in lists and shell commands.") 751 mkline.Warn0("The :Q operator should only be used in lists and shell commands.")
749 } 752 }
750 } else { 753 } else {
751 return valueNovar 754 return valueNovar
752 } 755 }
753 } 756 }
754} 757}
755 758
756func (mkline *MkLine) CheckVaralign() { 
757 if !G.opts.WarnSpace { 
758 return 
759 } 
760 
761 if m, prefix, align := match2(mkline.Line.Text, `^( *[-*+A-Z_a-z0-9.${}\[]+\s*[!:?]?=)(\s*)`); m { 
762 if align != " " && strings.Trim(align, "\t") != "" { 
763 alignedWidth := tabLength(prefix + align) 
764 tabs := "" 
765 for tabLength(prefix+tabs) < alignedWidth { 
766 tabs += "\t" 
767 } 
768 if !mkline.Line.AutofixReplace(prefix+align, prefix+tabs) { 
769 mkline.Note0("Alignment of variable values should be done with tabs, not spaces.") 
770 } 
771 } 
772 } 
773} 
774 
775func (mkline *MkLine) CheckText(text string) { 759func (mkline *MkLine) CheckText(text string) {
776 if G.opts.DebugTrace { 760 if G.opts.DebugTrace {
777 defer tracecall1(text)() 761 defer tracecall1(text)()
778 } 762 }
779 763
780 if m, varname := match1(text, `^(?:[^#]*[^\$])?\$(\w+)`); m { 764 if m, varname := match1(text, `^(?:[^#]*[^\$])?\$(\w+)`); m {
781 mkline.Warn1("$%[1]s is ambiguous. Use ${%[1]s} if you mean a Makefile variable or $$%[1]s if you mean a shell variable.", varname) 765 mkline.Warn1("$%[1]s is ambiguous. Use ${%[1]s} if you mean a Makefile variable or $$%[1]s if you mean a shell variable.", varname)
782 } 766 }
783 767
784 if mkline.Line.firstLine == 1 { 768 if mkline.Line.firstLine == 1 {
785 mkline.Line.CheckRcsid(`# `, "# ") 769 mkline.Line.CheckRcsid(`# `, "# ")
786 } 770 }
787 771

cvs diff -r1.1 -r1.2 pkgsrc/pkgtools/pkglint/files/Attic/mklines.go (expand / switch to unified diff)

--- pkgsrc/pkgtools/pkglint/files/Attic/mklines.go 2016/01/12 01:02:49 1.1
+++ pkgsrc/pkgtools/pkglint/files/Attic/mklines.go 2016/01/24 02:03:28 1.2
@@ -74,82 +74,82 @@ func (mklines *MkLines) UseVar(mkline *M @@ -74,82 +74,82 @@ func (mklines *MkLines) UseVar(mkline *M
74 74
75func (mklines *MkLines) VarValue(varname string) (value string, found bool) { 75func (mklines *MkLines) VarValue(varname string) (value string, found bool) {
76 if mkline := mklines.vardef[varname]; mkline != nil { 76 if mkline := mklines.vardef[varname]; mkline != nil {
77 return mkline.Value(), true 77 return mkline.Value(), true
78 } 78 }
79 return "", false 79 return "", false
80} 80}
81 81
82func (mklines *MkLines) Check() { 82func (mklines *MkLines) Check() {
83 if G.opts.DebugTrace { 83 if G.opts.DebugTrace {
84 defer tracecall1(mklines.lines[0].Fname)() 84 defer tracecall1(mklines.lines[0].Fname)()
85 } 85 }
86 86
87 allowedTargets := make(map[string]bool) 
88 substcontext := new(SubstContext) 
89 
90 G.Mk = mklines 87 G.Mk = mklines
91 defer func() { G.Mk = nil }() 88 defer func() { G.Mk = nil }()
92 89
93 mklines.DetermineUsedVariables() 90 allowedTargets := make(map[string]bool)
94 
95 prefixes := splitOnSpace("pre do post") 91 prefixes := splitOnSpace("pre do post")
96 actions := splitOnSpace("fetch extract patch tools wrapper configure build test install package clean") 92 actions := splitOnSpace("fetch extract patch tools wrapper configure build test install package clean")
97 for _, prefix := range prefixes { 93 for _, prefix := range prefixes {
98 for _, action := range actions { 94 for _, action := range actions {
99 allowedTargets[prefix+"-"+action] = true 95 allowedTargets[prefix+"-"+action] = true
100 } 96 }
101 } 97 }
102 98
103 // In the first pass, all additions to BUILD_DEFS and USE_TOOLS 99 // In the first pass, all additions to BUILD_DEFS and USE_TOOLS
104 // are collected to make the order of the definitions irrelevant. 100 // are collected to make the order of the definitions irrelevant.
 101 mklines.DetermineUsedVariables()
105 mklines.determineDefinedVariables() 102 mklines.determineDefinedVariables()
106 103
107 // In the second pass, the actual checks are done. 104 // In the second pass, the actual checks are done.
108 105
109 mklines.lines[0].CheckRcsid(`#\s+`, "# ") 106 mklines.lines[0].CheckRcsid(`#\s+`, "# ")
110 107
 108 substcontext := new(SubstContext)
 109 varalign := new(VaralignBlock)
111 for _, mkline := range mklines.mklines { 110 for _, mkline := range mklines.mklines {
112 mkline.Line.CheckTrailingWhitespace() 111 mkline.Line.CheckTrailingWhitespace()
113 mkline.Line.CheckValidCharacters(`[\t -~]`) 112 mkline.Line.CheckValidCharacters(`[\t -~]`)
 113 varalign.Check(mkline)
114 114
115 switch { 115 switch {
116 case mkline.IsEmpty(): 116 case mkline.IsEmpty():
117 substcontext.Finish(mkline) 117 substcontext.Finish(mkline)
118 118
119 case mkline.IsVarassign(): 119 case mkline.IsVarassign():
120 mklines.target = "" 120 mklines.target = ""
121 mkline.CheckVaralign() 
122 mkline.CheckVarassign() 121 mkline.CheckVarassign()
123 substcontext.Varassign(mkline) 122 substcontext.Varassign(mkline)
124 123
125 case mkline.IsShellcmd(): 124 case mkline.IsShellcmd():
126 shellcmd := mkline.Shellcmd() 125 shellcmd := mkline.Shellcmd()
127 mkline.CheckText(shellcmd) 126 mkline.CheckText(shellcmd)
128 NewShellLine(mkline).CheckShellCommandLine(shellcmd) 127 NewShellLine(mkline).CheckShellCommandLine(shellcmd)
129 128
130 case mkline.IsInclude(): 129 case mkline.IsInclude():
131 mklines.target = "" 130 mklines.target = ""
132 mklines.checklineInclude(mkline) 131 mklines.checklineInclude(mkline)
133 132
134 case mkline.IsCond(): 133 case mkline.IsCond():
135 mklines.checklineCond(mkline) 134 mklines.checklineCond(mkline)
136 135
137 case mkline.IsDependency(): 136 case mkline.IsDependency():
138 mklines.checklineDependencyRule(mkline, mkline.Targets(), mkline.Sources(), allowedTargets) 137 mklines.checklineDependencyRule(mkline, mkline.Targets(), mkline.Sources(), allowedTargets)
139 } 138 }
140 } 139 }
141 lastMkline := mklines.mklines[len(mklines.mklines)-1] 140 lastMkline := mklines.mklines[len(mklines.mklines)-1]
142 substcontext.Finish(lastMkline) 141 substcontext.Finish(lastMkline)
 142 varalign.Finish()
143 143
144 ChecklinesTrailingEmptyLines(mklines.lines) 144 ChecklinesTrailingEmptyLines(mklines.lines)
145 145
146 if len(mklines.indentation) != 1 && mklines.IndentDepth() != 0 { 146 if len(mklines.indentation) != 1 && mklines.IndentDepth() != 0 {
147 lastMkline.Line.Errorf("Directive indentation is not 0, but %d.", mklines.IndentDepth()) 147 lastMkline.Line.Errorf("Directive indentation is not 0, but %d.", mklines.IndentDepth())
148 } 148 }
149 149
150 SaveAutofixChanges(mklines.lines) 150 SaveAutofixChanges(mklines.lines)
151} 151}
152 152
153func (mklines *MkLines) determineDefinedVariables() { 153func (mklines *MkLines) determineDefinedVariables() {
154 for _, mkline := range mklines.mklines { 154 for _, mkline := range mklines.mklines {
155 if !mkline.IsVarassign() { 155 if !mkline.IsVarassign() {
@@ -369,13 +369,139 @@ func (mklines *MkLines) checklineInclude @@ -369,13 +369,139 @@ func (mklines *MkLines) checklineInclude
369 if matches(includefile, `/x11-links/buildlink3\.mk$`) { 369 if matches(includefile, `/x11-links/buildlink3\.mk$`) {
370 mkline.Error1("%s must not be included directly. Include \"../../mk/x11.buildlink3.mk\" instead.", includefile) 370 mkline.Error1("%s must not be included directly. Include \"../../mk/x11.buildlink3.mk\" instead.", includefile)
371 } 371 }
372 if matches(includefile, `/jpeg/buildlink3\.mk$`) { 372 if matches(includefile, `/jpeg/buildlink3\.mk$`) {
373 mkline.Error1("%s must not be included directly. Include \"../../mk/jpeg.buildlink3.mk\" instead.", includefile) 373 mkline.Error1("%s must not be included directly. Include \"../../mk/jpeg.buildlink3.mk\" instead.", includefile)
374 } 374 }
375 if matches(includefile, `/intltool/buildlink3\.mk$`) { 375 if matches(includefile, `/intltool/buildlink3\.mk$`) {
376 mkline.Warn0("Please write \"USE_TOOLS+= intltool\" instead of this line.") 376 mkline.Warn0("Please write \"USE_TOOLS+= intltool\" instead of this line.")
377 } 377 }
378 if m, dir := match1(includefile, `(.*)/builtin\.mk$`); m { 378 if m, dir := match1(includefile, `(.*)/builtin\.mk$`); m {
379 mkline.Line.Error2("%s must not be included directly. Include \"%s/buildlink3.mk\" instead.", includefile, dir) 379 mkline.Line.Error2("%s must not be included directly. Include \"%s/buildlink3.mk\" instead.", includefile, dir)
380 } 380 }
381} 381}
 382
 383type VaralignBlock struct {
 384 info []struct {
 385 mkline *MkLine
 386 prefix string
 387 align string
 388 }
 389 skip bool
 390 differ bool
 391 maxPrefixWidth int
 392 maxSpaceWidth int
 393 maxTabWidth int
 394}
 395
 396func (va *VaralignBlock) Check(mkline *MkLine) {
 397 if !G.opts.WarnSpace || mkline.Line.IsMultiline() || mkline.IsComment() || mkline.IsCond() {
 398 return
 399 }
 400 if mkline.IsEmpty() {
 401 va.Finish()
 402 return
 403 }
 404 if !mkline.IsVarassign() {
 405 va.skip = true
 406 return
 407 }
 408
 409 valueAlign := mkline.ValueAlign()
 410 prefix := strings.TrimRight(valueAlign, " \t")
 411 align := valueAlign[len(prefix):]
 412
 413 va.info = append(va.info, struct {
 414 mkline *MkLine
 415 prefix string
 416 align string
 417 }{mkline, prefix, align})
 418
 419 alignedWidth := tabLength(valueAlign)
 420 if contains(align, " ") {
 421 if va.maxSpaceWidth != 0 && alignedWidth != va.maxSpaceWidth {
 422 va.differ = true
 423 }
 424 if alignedWidth > va.maxSpaceWidth {
 425 va.maxSpaceWidth = alignedWidth
 426 }
 427 } else {
 428 if va.maxTabWidth != 0 && alignedWidth != va.maxTabWidth {
 429 va.differ = true
 430 }
 431 if alignedWidth > va.maxTabWidth {
 432 va.maxTabWidth = alignedWidth
 433 }
 434 }
 435
 436 va.maxPrefixWidth = imax(va.maxPrefixWidth, tabLength(prefix))
 437}
 438
 439func (va *VaralignBlock) Finish() {
 440 if !va.skip {
 441 for _, info := range va.info {
 442 if !info.mkline.Line.IsMultiline() {
 443 va.fixalign(info.mkline, info.prefix, info.align)
 444 }
 445 }
 446 }
 447 *va = VaralignBlock{}
 448}
 449
 450func (va *VaralignBlock) fixalign(mkline *MkLine, prefix, oldalign string) {
 451 if mkline.Value() == "" && mkline.Comment() == "" {
 452 return
 453 }
 454
 455 hasSpace := contains(oldalign, " ")
 456 if hasSpace &&
 457 va.maxTabWidth != 0 &&
 458 va.maxSpaceWidth > va.maxTabWidth &&
 459 tabLength(prefix+oldalign) == va.maxSpaceWidth {
 460 return
 461 }
 462
 463 goodWidth := va.maxTabWidth
 464 if goodWidth == 0 && va.differ {
 465 goodWidth = va.maxSpaceWidth
 466 }
 467 minWidth := va.maxPrefixWidth + 1
 468 if goodWidth == 0 || minWidth < goodWidth && va.differ {
 469 goodWidth = minWidth
 470 }
 471 goodWidth = (goodWidth + 7) & -8
 472
 473 newalign := ""
 474 for tabLength(prefix+newalign) < goodWidth {
 475 newalign += "\t"
 476 }
 477 if newalign == oldalign {
 478 return
 479 }
 480
 481 if !mkline.Line.AutofixReplace(prefix+oldalign, prefix+newalign) {
 482 wrongColumn := tabLength(prefix+oldalign) != tabLength(prefix+newalign)
 483 switch {
 484 case hasSpace && wrongColumn:
 485 mkline.Line.Notef("This variable value should be aligned with tabs, not spaces, to column %d.", goodWidth+1)
 486 case hasSpace:
 487 mkline.Line.Notef("Variable values should be aligned with tabs, not spaces.")
 488 case wrongColumn:
 489 mkline.Line.Notef("This variable value should be aligned to column %d.", goodWidth+1)
 490 }
 491 if wrongColumn {
 492 Explain(
 493 "Normally, all variable values in a block should start at the same",
 494 "column. There are some exceptions to this rule:",
 495 "",
 496 "Definitions for long variable names may be indented with a single",
 497 "space instead of tabs, but only if they appear in a block that is",
 498 "otherwise indented using tabs.",
 499 "",
 500 "Variable definitions that span multiple lines are not checked for",
 501 "alignment at all.",
 502 "",
 503 "When the block contains something else than variable definitions,",
 504 "it is not checked at all.")
 505 }
 506 }
 507}

cvs diff -r1.4 -r1.5 pkgsrc/pkgtools/pkglint/files/Attic/pkglint_test.go (expand / switch to unified diff)

--- pkgsrc/pkgtools/pkglint/files/Attic/pkglint_test.go 2016/01/12 01:02:49 1.4
+++ pkgsrc/pkgtools/pkglint/files/Attic/pkglint_test.go 2016/01/24 02:03:28 1.5
@@ -75,54 +75,54 @@ func (s *Suite) TestChecklineRcsid(c *ch @@ -75,54 +75,54 @@ func (s *Suite) TestChecklineRcsid(c *ch
75 "$"+"FreeBSD$") 75 "$"+"FreeBSD$")
76 76
77 for _, line := range lines { 77 for _, line := range lines {
78 line.CheckRcsid(``, "") 78 line.CheckRcsid(``, "")
79 } 79 }
80 80
81 c.Check(s.Output(), equals, ""+ 81 c.Check(s.Output(), equals, ""+
82 "ERROR: fname:3: Expected \"$"+"NetBSD$\".\n"+ 82 "ERROR: fname:3: Expected \"$"+"NetBSD$\".\n"+
83 "ERROR: fname:4: Expected \"$"+"NetBSD$\".\n"+ 83 "ERROR: fname:4: Expected \"$"+"NetBSD$\".\n"+
84 "ERROR: fname:5: Expected \"$"+"NetBSD$\".\n") 84 "ERROR: fname:5: Expected \"$"+"NetBSD$\".\n")
85} 85}
86 86
87func (s *Suite) TestMatchVarassign(c *check.C) { 87func (s *Suite) TestMatchVarassign(c *check.C) {
88 checkVarassign := func(text string, ck check.Checker, varname, op, value, comment string) { 88 checkVarassign := func(text string, ck check.Checker, varname, op, align, value, comment string) {
89 type va struct { 89 type va struct {
90 varname, op, value, comment string 90 varname, op, align, value, comment string
91 } 91 }
92 expected := va{varname, op, value, comment} 92 expected := va{varname, op, align, value, comment}
93 am, avarname, aop, avalue, acomment := MatchVarassign(text) 93 am, avarname, aop, aalign, avalue, acomment := MatchVarassign(text)
94 if !am { 94 if !am {
95 c.Errorf("Text %q doesn’t match variable assignment", text) 95 c.Errorf("Text %q doesn’t match variable assignment", text)
96 return 96 return
97 } 97 }
98 actual := va{avarname, aop, avalue, acomment} 98 actual := va{avarname, aop, aalign, avalue, acomment}
99 c.Check(actual, ck, expected) 99 c.Check(actual, ck, expected)
100 } 100 }
101 checkNotVarassign := func(text string) { 101 checkNotVarassign := func(text string) {
102 m, _, _, _, _ := MatchVarassign(text) 102 m, _, _, _, _, _ := MatchVarassign(text)
103 if m { 103 if m {
104 c.Errorf("Text %q matches variable assignment, but shouldn’t.", text) 104 c.Errorf("Text %q matches variable assignment, but shouldn’t.", text)
105 } 105 }
106 } 106 }
107 107
108 checkVarassign("C++=c11", equals, "C+", "+=", "c11", "") 108 checkVarassign("C++=c11", equals, "C+", "+=", "C++=", "c11", "")
109 checkVarassign("V=v", equals, "V", "=", "v", "") 109 checkVarassign("V=v", equals, "V", "=", "V=", "v", "")
110 checkVarassign("VAR=#comment", equals, "VAR", "=", "", "#comment") 110 checkVarassign("VAR=#comment", equals, "VAR", "=", "VAR=", "", "#comment")
111 checkVarassign("VAR=\\#comment", equals, "VAR", "=", "#comment", "") 111 checkVarassign("VAR=\\#comment", equals, "VAR", "=", "VAR=", "#comment", "")
112 checkVarassign("VAR=\\\\\\##comment", equals, "VAR", "=", "\\\\#", "#comment") 112 checkVarassign("VAR=\\\\\\##comment", equals, "VAR", "=", "VAR=", "\\\\#", "#comment")
113 checkVarassign("VAR=\\", equals, "VAR", "=", "\\", "") 113 checkVarassign("VAR=\\", equals, "VAR", "=", "VAR=", "\\", "")
114 checkVarassign("VAR += value", equals, "VAR", "+=", "value", "") 114 checkVarassign("VAR += value", equals, "VAR", "+=", "VAR += ", "value", "")
115 checkVarassign(" VAR=value", equals, "VAR", "=", "value", "") 115 checkVarassign(" VAR=value", equals, "VAR", "=", " VAR=", "value", "")
116 checkNotVarassign("\tVAR=value") 116 checkNotVarassign("\tVAR=value")
117 checkNotVarassign("?=value") 117 checkNotVarassign("?=value")
118 checkNotVarassign("<=value") 118 checkNotVarassign("<=value")
119} 119}
120 120
121func (s *Suite) TestPackage_LoadPackageMakefile(c *check.C) { 121func (s *Suite) TestPackage_LoadPackageMakefile(c *check.C) {
122 makefile := s.CreateTmpFile(c, "category/package/Makefile", ""+ 122 makefile := s.CreateTmpFile(c, "category/package/Makefile", ""+
123 "# $"+"NetBSD$\n"+ 123 "# $"+"NetBSD$\n"+
124 "\n"+ 124 "\n"+
125 "PKGNAME=pkgname-1.67\n"+ 125 "PKGNAME=pkgname-1.67\n"+
126 "DISTNAME=distfile_1_67\n"+ 126 "DISTNAME=distfile_1_67\n"+
127 ".include \"../../category/package/Makefile\"\n") 127 ".include \"../../category/package/Makefile\"\n")
128 pkg := NewPackage("category/package") 128 pkg := NewPackage("category/package")