...

Source file src/github.com/bazelbuild/buildtools/warn/warn_bazel_operation.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  // Warnings about deprecated Bazel-related operations
    18  
    19  package warn
    20  
    21  import (
    22  	"fmt"
    23  
    24  	"github.com/bazelbuild/buildtools/build"
    25  )
    26  
    27  func depsetUnionWarning(f *build.File) []*LinterFinding {
    28  	var findings []*LinterFinding
    29  	addWarning := func(expr build.Expr) {
    30  		findings = append(findings,
    31  			makeLinterFinding(expr, `Depsets should be joined using the "depset()" constructor.`))
    32  	}
    33  
    34  	types := DetectTypes(f)
    35  	build.Walk(f, func(expr build.Expr, stack []build.Expr) {
    36  		switch expr := expr.(type) {
    37  		case *build.BinaryExpr:
    38  			// `depset1 + depset2` or `depset1 | depset2`
    39  			if types[expr.X] != Depset && types[expr.Y] != Depset {
    40  				return
    41  			}
    42  			switch expr.Op {
    43  			case "+", "|":
    44  				addWarning(expr)
    45  			}
    46  		case *build.AssignExpr:
    47  			// `depset1 += depset2` or `depset1 |= depset2`
    48  			if types[expr.LHS] != Depset && types[expr.RHS] != Depset {
    49  				return
    50  			}
    51  			switch expr.Op {
    52  			case "+=", "|=":
    53  				addWarning(expr)
    54  			}
    55  		case *build.CallExpr:
    56  			// `depset1.union(depset2)`
    57  			if len(expr.List) == 0 {
    58  				return
    59  			}
    60  			dot, ok := expr.X.(*build.DotExpr)
    61  			if !ok {
    62  				return
    63  			}
    64  			if dot.Name != "union" {
    65  				return
    66  			}
    67  			if types[dot.X] != Depset && types[expr.List[0]] != Depset {
    68  				return
    69  			}
    70  			addWarning(expr)
    71  		}
    72  	})
    73  	return findings
    74  }
    75  
    76  func depsetIterationWarning(f *build.File) []*LinterFinding {
    77  	var findings []*LinterFinding
    78  
    79  	addFinding := func(expr *build.Expr) {
    80  		_, end := (*expr).Span()
    81  		newNode := &build.CallExpr{
    82  			X: &build.DotExpr{
    83  				X:    *expr,
    84  				Name: "to_list",
    85  			},
    86  			End: build.End{Pos: end},
    87  		}
    88  		findings = append(findings,
    89  			makeLinterFinding(*expr, `Depset iteration is deprecated, use the "to_list()" method instead.`, LinterReplacement{expr, newNode}))
    90  	}
    91  
    92  	types := DetectTypes(f)
    93  	build.WalkPointers(f, func(e *build.Expr, stack []build.Expr) {
    94  		switch expr := (*e).(type) {
    95  		case *build.ForStmt:
    96  			if types[expr.X] != Depset {
    97  				return
    98  			}
    99  			addFinding(&expr.X)
   100  		case *build.ForClause:
   101  			if types[expr.X] != Depset {
   102  				return
   103  			}
   104  			addFinding(&expr.X)
   105  		case *build.BinaryExpr:
   106  			if expr.Op != "in" && expr.Op != "not in" {
   107  				return
   108  			}
   109  			if types[expr.Y] != Depset {
   110  				return
   111  			}
   112  			addFinding(&expr.Y)
   113  		case *build.CallExpr:
   114  			ident, ok := expr.X.(*build.Ident)
   115  			if !ok {
   116  				return
   117  			}
   118  			switch ident.Name {
   119  			case "all", "any", "depset", "len", "sorted", "max", "min", "list", "tuple":
   120  				if len(expr.List) != 1 {
   121  					return
   122  				}
   123  				if types[expr.List[0]] != Depset {
   124  					return
   125  				}
   126  				addFinding(&expr.List[0])
   127  				if ident.Name == "list" {
   128  					// `list(d.to_list())` can be simplified to just `d.to_list()`
   129  					findings[len(findings)-1].Replacement[0].Old = e
   130  				}
   131  			case "zip":
   132  				for i, arg := range expr.List {
   133  					if types[arg] != Depset {
   134  						continue
   135  					}
   136  					addFinding(&expr.List[i])
   137  				}
   138  			}
   139  		}
   140  		return
   141  	})
   142  	return findings
   143  }
   144  
   145  func overlyNestedDepsetWarning(f *build.File) []*LinterFinding {
   146  	var findings []*LinterFinding
   147  	build.WalkStatements(f, func(expr build.Expr, stack []build.Expr) (err error) {
   148  		// Are we inside a for-loop?
   149  		isForLoop := false
   150  		for _, e := range stack {
   151  			if _, ok := e.(*build.ForStmt); ok {
   152  				isForLoop = true
   153  				break
   154  			}
   155  		}
   156  		if !isForLoop {
   157  			return
   158  		}
   159  
   160  		// Search for assignment statements
   161  		assign, ok := expr.(*build.AssignExpr)
   162  		if !ok {
   163  			return
   164  		}
   165  		// Is the LHS an ident?
   166  		lhs, ok := assign.LHS.(*build.Ident)
   167  		if !ok {
   168  			return
   169  		}
   170  		// Is the RHS a depset constructor?
   171  		call, ok := assign.RHS.(*build.CallExpr)
   172  		if !ok {
   173  			return
   174  		}
   175  		if ident, ok := call.X.(*build.Ident); !ok || ident.Name != "depset" {
   176  			return
   177  		}
   178  		_, _, param := getParam(call.List, "transitive")
   179  		if param == nil {
   180  			return
   181  		}
   182  		transitives, ok := param.RHS.(*build.ListExpr)
   183  		if !ok {
   184  			return
   185  		}
   186  		for _, transitive := range transitives.List {
   187  			if ident, ok := transitive.(*build.Ident); ok && ident.Name == lhs.Name {
   188  				findings = append(findings, makeLinterFinding(assign, fmt.Sprintf("Depset %q is potentially overly nested.", lhs.Name)))
   189  				return
   190  			}
   191  		}
   192  		return
   193  	})
   194  	return findings
   195  }
   196  

View as plain text