...

Source file src/github.com/bazelbuild/buildtools/warn/warn_naming.go

Documentation: github.com/bazelbuild/buildtools/warn

     1  /*
     2  Copyright 2020 Google LLC
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      https://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package warn
    18  
    19  import (
    20  	"fmt"
    21  	"strings"
    22  
    23  	"github.com/bazelbuild/buildtools/build"
    24  	"github.com/bazelbuild/buildtools/bzlenv"
    25  )
    26  
    27  var ambiguousNames = map[string]bool{
    28  	"I": true,
    29  	"l": true,
    30  	"O": true,
    31  }
    32  
    33  // ambiguousNameCheck checks for the names of idents and functions
    34  func ambiguousNameCheck(expr build.Expr, name string, findings []*LinterFinding) []*LinterFinding {
    35  	if ambiguousNames[name] {
    36  		findings = append(findings,
    37  			makeLinterFinding(expr, `Never use 'l', 'I', or 'O' as names (they're too easily confused with 'I', 'l', or '0').`))
    38  	}
    39  	return findings
    40  }
    41  
    42  func confusingNameWarning(f *build.File) []*LinterFinding {
    43  	var findings []*LinterFinding
    44  	// check for global variable names
    45  	for _, ident := range collectLocalVariables(f.Stmt) {
    46  		findings = ambiguousNameCheck(ident, ident.Name, findings)
    47  	}
    48  
    49  	build.Walk(f, func(expr build.Expr, stack []build.Expr) {
    50  		switch expr := expr.(type) {
    51  		case *build.DefStmt:
    52  			findings = ambiguousNameCheck(expr, expr.Name, findings)
    53  			for _, param := range expr.Params {
    54  				name, _ := build.GetParamName(param)
    55  				findings = ambiguousNameCheck(param, name, findings)
    56  			}
    57  			for _, ident := range collectLocalVariables(expr.Body) {
    58  				findings = ambiguousNameCheck(ident, ident.Name, findings)
    59  			}
    60  		case *build.Comprehension:
    61  			for _, clause := range expr.Clauses {
    62  				forClause, ok := clause.(*build.ForClause)
    63  				if !ok {
    64  					continue
    65  				}
    66  				for _, ident := range bzlenv.CollectLValues(forClause.Vars) {
    67  					findings = ambiguousNameCheck(ident, ident.Name, findings)
    68  				}
    69  			}
    70  		}
    71  	})
    72  
    73  	return findings
    74  }
    75  
    76  func isUpperCamelCase(name string) bool {
    77  	if strings.HasPrefix(name, "_") {
    78  		// Private providers are allowed
    79  		name = name[1:]
    80  	}
    81  	return !strings.ContainsRune(name, '_') && name == strings.Title(name)
    82  }
    83  
    84  func isLowerSnakeCase(name string) bool {
    85  	return name == strings.ToLower(name)
    86  }
    87  
    88  func isUpperSnakeCase(name string) bool {
    89  	return name == strings.ToUpper(name)
    90  }
    91  
    92  func nameConventionsWarning(f *build.File) []*LinterFinding {
    93  	var findings []*LinterFinding
    94  
    95  	build.WalkStatements(f, func(stmt build.Expr, stack []build.Expr) (err error) {
    96  		// looking for provider declaration statements: `xxx = provider()`
    97  		// note that the code won't trigger on complex assignments, such as `x, y = foo, provider()`
    98  		binary, ok := stmt.(*build.AssignExpr)
    99  		if !ok {
   100  			return
   101  		}
   102  		for _, ident := range bzlenv.CollectLValues(binary.LHS) {
   103  			if isLowerSnakeCase(ident.Name) || isUpperSnakeCase(ident.Name) {
   104  				continue
   105  			}
   106  			if isUpperCamelCase(ident.Name) && strings.HasSuffix(ident.Name, "Info") {
   107  				continue
   108  			}
   109  			findings = append(findings,
   110  				makeLinterFinding(ident,
   111  					fmt.Sprintf(`Variable name "%s" should be lower_snake_case (for variables), UPPER_SNAKE_CASE (for constants), or UpperCamelCase ending with 'Info' (for providers).`, ident.Name)))
   112  		}
   113  		return
   114  	})
   115  
   116  	return findings
   117  }
   118  

View as plain text