summaryrefslogtreecommitdiff
path: root/pkgtools/pkglint/files/mkline.go
diff options
context:
space:
mode:
authorrillig <rillig@pkgsrc.org>2016-07-09 09:43:48 +0000
committerrillig <rillig@pkgsrc.org>2016-07-09 09:43:48 +0000
commit0f9e2b17c5f087d3f18d6a558eff4a1e7b308a13 (patch)
treeeeb2068d09d1ea0f28fbde1461acd2b485e2c3f7 /pkgtools/pkglint/files/mkline.go
parent015903966416e18ed697ee02e778c8b8fc414f53 (diff)
downloadpkgsrc-0f9e2b17c5f087d3f18d6a558eff4a1e7b308a13.tar.gz
Updated pkglint to 5.4.4.
Changes since 5.4.3: * Improved detection for undocumented patches from Git * Added warning about unnecessary space after variable names * Lots of internal housekeeping
Diffstat (limited to 'pkgtools/pkglint/files/mkline.go')
-rw-r--r--pkgtools/pkglint/files/mkline.go110
1 files changed, 50 insertions, 60 deletions
diff --git a/pkgtools/pkglint/files/mkline.go b/pkgtools/pkglint/files/mkline.go
index 10b886d18d5..8b3bb1a8f58 100644
--- a/pkgtools/pkglint/files/mkline.go
+++ b/pkgtools/pkglint/files/mkline.go
@@ -44,7 +44,20 @@ func NewMkLine(line *Line) (mkline *MkLine) {
"white-space.")
}
- if m, varname, op, valueAlign, value, comment := MatchVarassign(text); m {
+ if m, varname, spaceAfterVarname, op, valueAlign, value, comment := MatchVarassign(text); m {
+ if G.opts.WarnSpace && spaceAfterVarname != "" {
+ switch {
+ case hasSuffix(varname, "+") && op == "=":
+ break
+ case matches(varname, `^[a-z]`) && op == ":=":
+ break
+ default:
+ if !line.AutofixReplace(varname+spaceAfterVarname+op, varname+op) {
+ line.Warn1("Unnecessary space after variable name %q.", varname)
+ }
+ }
+ }
+
value = strings.Replace(value, "\\#", "#", -1)
varparam := varnameParam(varname)
@@ -243,7 +256,7 @@ func (mkline *MkLine) checkCond(forVars map[string]bool) {
indentation.Push(indentation.Depth() + 2)
}
- reDirectivesWithArgs := `^(?:if|ifdef|ifndef|elif|for|undef)$`
+ const reDirectivesWithArgs = `^(?:if|ifdef|ifndef|elif|for|undef)$`
if matches(directive, reDirectivesWithArgs) && args == "" {
mkline.Error1("\".%s\" requires arguments.", directive)
@@ -295,7 +308,7 @@ func (mkline *MkLine) checkCond(forVars map[string]bool) {
}
forLoopType := &Vartype{lkSpace, CheckvarUnchecked, []AclEntry{{"*", aclpAllRead}}, guessed}
- forLoopContext := &VarUseContext{forLoopType, vucTimeParse, vucQuotFor, vucExtentWord}
+ forLoopContext := &VarUseContext{forLoopType, vucTimeParse, vucQuotFor, false}
for _, forLoopVar := range mkline.extractUsedVariables(values) {
mkline.CheckVaruse(&MkVarUse{forLoopVar, nil}, forLoopContext)
}
@@ -640,7 +653,7 @@ func (mkline *MkLine) CheckVaruseShellword(varname string, vartype *Vartype, vuc
} else if needsQuoting == nqYes {
correctMod := strippedMod + ifelseStr(needMstar, ":M*:Q", ":Q")
- if correctMod == mod+":Q" && vuc.extent == vucExtentWordpart && !vartype.IsShell() {
+ if correctMod == mod+":Q" && vuc.IsWordPart && !vartype.IsShell() {
mkline.Line.Warnf("The list variable %s should not be embedded in a word.", varname)
Explain(
"When a list variable has multiple elements, this expression expands",
@@ -848,12 +861,8 @@ func (mkline *MkLine) checkVarassignVaruseMk(vartype *Vartype, time vucTime) {
if token.Varuse != nil {
spaceLeft := i-1 < 0 || matches(tokens[i-1].Text, `\s$`)
spaceRight := i+1 >= len(tokens) || matches(tokens[i+1].Text, `^\s`)
- extent := vucExtentWordpart
- if spaceLeft && spaceRight {
- extent = vucExtentWord
- }
-
- vuc := &VarUseContext{vartype, time, vucQuotPlain, extent}
+ isWordPart := !(spaceLeft && spaceRight)
+ vuc := &VarUseContext{vartype, time, vucQuotPlain, isWordPart}
mkline.CheckVaruse(token.Varuse, vuc)
}
}
@@ -864,27 +873,21 @@ func (mkline *MkLine) checkVarassignVaruseShell(vartype *Vartype, time vucTime)
defer tracecall(vartype, time)()
}
- extent := func(tokens []*ShAtom, i int) vucExtent {
- if i-1 >= 0 {
- typ := tokens[i-1].Type
- if typ != shtSpace && typ != shtSemicolon && typ != shtParenOpen && typ != shtParenClose {
- return vucExtentWordpart
- }
+ isWordPart := func(tokens []*ShAtom, i int) bool {
+ if i-1 >= 0 && tokens[i-1].Type.IsWord() {
+ return true
}
- if i+1 < len(tokens) {
- typ := tokens[i+1].Type
- if typ != shtSpace && typ != shtSemicolon && typ != shtParenOpen && typ != shtParenClose {
- return vucExtentWordpart
- }
+ if i+1 < len(tokens) && tokens[i+1].Type.IsWord() {
+ return true
}
- return vucExtentWord
+ return false
}
atoms := NewShTokenizer(mkline.Line, mkline.Value(), false).ShAtoms()
for i, atom := range atoms {
if atom.Type == shtVaruse {
- extent := extent(atoms, i)
- vuc := &VarUseContext{vartype, time, atom.Quoting.ToVarUseContext(), extent}
+ isWordPart := isWordPart(atoms, i)
+ vuc := &VarUseContext{vartype, time, atom.Quoting.ToVarUseContext(), isWordPart}
mkline.CheckVaruse(atom.Data.(*MkVarUse), vuc)
}
}
@@ -1028,46 +1031,42 @@ func (mkline *MkLine) CheckVartype(varname string, op MkOperator, value, comment
}
case vartype.kindOfList == lkNone:
- mkline.CheckVartypePrimitive(varname, vartype.checker, op, value, comment, vartype.IsConsideredList(), vartype.guessed)
+ mkline.CheckVartypePrimitive(varname, vartype.checker, op, value, comment, vartype.guessed)
case value == "":
break
case vartype.kindOfList == lkSpace:
for _, word := range splitOnSpace(value) {
- mkline.CheckVartypePrimitive(varname, vartype.checker, op, word, comment, true, vartype.guessed)
+ mkline.CheckVartypePrimitive(varname, vartype.checker, op, word, comment, vartype.guessed)
}
case vartype.kindOfList == lkShell:
words, _ := splitIntoMkWords(mkline.Line, value)
for _, word := range words {
- mkline.CheckVartypePrimitive(varname, vartype.checker, op, word, comment, true, vartype.guessed)
+ mkline.CheckVartypePrimitive(varname, vartype.checker, op, word, comment, vartype.guessed)
}
}
}
// For some variables (like `BuildlinkDepth`), `op` influences the valid values.
// The `comment` parameter comes from a variable assignment, when a part of the line is commented out.
-func (mkline *MkLine) CheckVartypePrimitive(varname string, checker *VarChecker, op MkOperator, value, comment string, isList bool, guessed bool) {
+func (mkline *MkLine) CheckVartypePrimitive(varname string, checker *VarChecker, op MkOperator, value, comment string, guessed bool) {
if G.opts.Debug {
- defer tracecall(varname, checker.name, op, value, comment, isList, guessed)()
+ defer tracecall(varname, checker.name, op, value, comment, guessed)()
}
- valueNoVar := mkline.withoutMakeVariables(value, isList)
- ctx := &VartypeCheck{mkline, mkline.Line, varname, op, value, valueNoVar, comment, isList, guessed}
+ valueNoVar := mkline.withoutMakeVariables(value)
+ ctx := &VartypeCheck{mkline, mkline.Line, varname, op, value, valueNoVar, comment, guessed}
checker.checker(ctx)
}
-func (mkline *MkLine) withoutMakeVariables(value string, qModifierAllowed bool) string {
+func (mkline *MkLine) withoutMakeVariables(value string) string {
valueNovar := value
for {
var m []string
- if m, valueNovar = replaceFirst(valueNovar, `\$\{([^{}]*)\}`, ""); m != nil {
- varuse := m[1]
- if !qModifierAllowed && hasSuffix(varuse, ":Q") {
- mkline.Warn0("The :Q operator should only be used in lists and shell commands.")
- }
- } else {
+ m, valueNovar = replaceFirst(valueNovar, `\$\{[^{}]*\}`, "")
+ if m == nil {
return valueNovar
}
}
@@ -1198,7 +1197,7 @@ func (mkline *MkLine) rememberUsedVariables(cond *Tree) {
cond.Visit("compareVarVar", arg2varuse)
}
-func (mkline *MkLine) CheckValidCharactersInValue(reValid string) {
+func (mkline *MkLine) CheckValidCharactersInValue(reValid RegexPattern) {
rest := regcomp(reValid).ReplaceAllString(mkline.Value(), "")
if rest != "" {
uni := ""
@@ -1335,7 +1334,7 @@ func (mkline *MkLine) variableNeedsQuoting(varname string, vartype *Vartype, vuc
if vartype.kindOfList == lkNone {
return nqDoesntMatter
}
- if vartype.kindOfList == lkShell && vuc.extent != vucExtentWordpart {
+ if vartype.kindOfList == lkShell && !vuc.IsWordPart {
return nqNo
}
}
@@ -1355,7 +1354,7 @@ func (mkline *MkLine) variableNeedsQuoting(varname string, vartype *Vartype, vuc
}
// A shell word may appear as part of a shell word, for example COMPILER_RPATH_FLAG.
- if vuc.extent == vucExtentWordpart && vuc.quoting == vucQuotPlain {
+ if vuc.IsWordPart && vuc.quoting == vucQuotPlain {
if vartype.kindOfList == lkNone && vartype.checker == CheckvarShellWord {
return nqNo
}
@@ -1364,7 +1363,7 @@ func (mkline *MkLine) variableNeedsQuoting(varname string, vartype *Vartype, vuc
// Both of these can be correct, depending on the situation:
// 1. echo ${PERL5:Q}
// 2. xargs ${PERL5}
- if vuc.extent == vucExtentWord && vuc.quoting == vucQuotPlain {
+ if !vuc.IsWordPart && vuc.quoting == vucQuotPlain {
if wantList && haveList {
return nqDontKnow
}
@@ -1375,7 +1374,7 @@ func (mkline *MkLine) variableNeedsQuoting(varname string, vartype *Vartype, vuc
if G.globalData.Tools.byVarname[varname] != nil {
switch vuc.quoting {
case vucQuotPlain:
- if vuc.extent != vucExtentWordpart {
+ if !vuc.IsWordPart {
return nqNo
}
case vucQuotBackt:
@@ -1389,7 +1388,7 @@ func (mkline *MkLine) variableNeedsQuoting(varname string, vartype *Vartype, vuc
// to be quoted. An exception is in the case of backticks,
// because the whole backticks expression is parsed as a single
// shell word by pkglint.
- if vuc.extent == vucExtentWordpart && vuc.vartype != nil && vuc.vartype.IsShell() && vuc.quoting != vucQuotBackt {
+ if vuc.IsWordPart && vuc.vartype != nil && vuc.vartype.IsShell() && vuc.quoting != vucQuotBackt {
return nqYes
}
@@ -1401,7 +1400,7 @@ func (mkline *MkLine) variableNeedsQuoting(varname string, vartype *Vartype, vuc
// Assigning lists to lists does not require any quoting, though
// there may be cases like "CONFIGURE_ARGS+= -libs ${LDFLAGS:Q}"
// where quoting is necessary.
- if wantList && haveList && vuc.extent != vucExtentWordpart {
+ if wantList && haveList && !vuc.IsWordPart {
return nqDoesntMatter
}
@@ -1419,7 +1418,7 @@ func (mkline *MkLine) variableNeedsQuoting(varname string, vartype *Vartype, vuc
// Bad: LDADD += -l${LIBS}
// Good: LDADD += ${LIBS:@lib@-l${lib} @}
- if wantList && haveList && vuc.extent == vucExtentWordpart {
+ if wantList && haveList && vuc.IsWordPart {
return nqYes
}
@@ -1586,10 +1585,10 @@ func (mkline *MkLine) determineUsedVariables() (varnames []string) {
// checked against the variable type. For example, comparing OPSYS to
// x86_64 doesn’t make sense.
type VarUseContext struct {
- vartype *Vartype
- time vucTime
- quoting vucQuoting
- extent vucExtent
+ vartype *Vartype
+ time vucTime
+ quoting vucQuoting
+ IsWordPart bool // Example: echo ${LOCALBASE} LOCALBASE=${LOCALBASE}
}
type vucTime uint8
@@ -1633,21 +1632,12 @@ func (q vucQuoting) String() string {
return [...]string{"unknown", "plain", "dquot", "squot", "backt", "mk-for"}[q]
}
-type vucExtent uint8
-
-const (
- vucExtentWord vucExtent = iota // Example: echo ${LOCALBASE}
- vucExtentWordpart // Example: echo LOCALBASE=${LOCALBASE}
-)
-
-func (e vucExtent) String() string { return [...]string{"word", "wordpart"}[e] }
-
func (vuc *VarUseContext) String() string {
typename := "no-type"
if vuc.vartype != nil {
typename = vuc.vartype.String()
}
- return fmt.Sprintf("(%s time:%s quoting:%s extent:%s)", typename, vuc.time, vuc.quoting, vuc.extent)
+ return fmt.Sprintf("(%s time:%s quoting:%s wordpart:%v)", typename, vuc.time, vuc.quoting, vuc.IsWordPart)
}
type Indentation struct {