...

Source file src/github.com/bazelbuild/buildtools/warn/warn_bazel_api_test.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  	"testing"
    22  
    23  	"github.com/bazelbuild/buildtools/tables"
    24  )
    25  
    26  func TestAttrDataConfigurationWarning(t *testing.T) {
    27  	checkFindingsAndFix(t, "attr-cfg", `
    28  rule(
    29    attrs = {
    30        "foo": attr.label_list(mandatory = True, cfg = "data"),
    31    }
    32  )
    33  
    34  attr.label_list(mandatory = True, cfg = "exec")`, `
    35  rule(
    36    attrs = {
    37        "foo": attr.label_list(mandatory = True),
    38    }
    39  )
    40  
    41  attr.label_list(mandatory = True, cfg = "exec")`,
    42  		[]string{`:3: cfg = "data" for attr definitions has no effect and should be removed.`},
    43  		scopeBzl)
    44  }
    45  
    46  func TestAttrHostConfigurationWarning(t *testing.T) {
    47  	checkFindingsAndFix(t, "attr-cfg", `
    48  rule(
    49    attrs = {
    50        "foo": attr.label_list(mandatory = True, cfg = "host"),
    51    }
    52  )
    53  
    54  attr.label_list(mandatory = True, cfg = "exec")`, `
    55  rule(
    56    attrs = {
    57        "foo": attr.label_list(mandatory = True, cfg = "exec"),
    58    }
    59  )
    60  
    61  attr.label_list(mandatory = True, cfg = "exec")`,
    62  		[]string{`:3: cfg = "host" for attr definitions should be replaced by cfg = "exec".`},
    63  		scopeBzl)
    64  }
    65  
    66  func TestDepsetItemsWarning(t *testing.T) {
    67  	checkFindings(t, "depset-items", `
    68  def f():
    69    depset(items=foo)
    70    a = depset()
    71    depset(a)
    72  `, []string{
    73  		`:2: Parameter "items" is deprecated, use "direct" and/or "transitive" instead.`,
    74  		`:4: Giving a depset as first unnamed parameter to depset() is deprecated, use the "transitive" parameter instead.`,
    75  	},
    76  		scopeEverywhere)
    77  }
    78  
    79  func TestAttrNonEmptyWarning(t *testing.T) {
    80  	checkFindingsAndFix(t, "attr-non-empty", `
    81  rule(
    82    attrs = {
    83        "foo": attr.label_list(mandatory = True, non_empty = True),
    84        "bar": attr.label_list(mandatory = True, non_empty = False),
    85        "baz": attr.label_list(mandatory = True, non_empty = foo.bar()),
    86        "qux": attr.label_list(mandatory = True, non_empty = not foo.bar()),
    87        "aaa": attr.label_list(mandatory = True, non_empty = (foo.bar())),
    88        "bbb": attr.label_list(mandatory = True, non_empty = (
    89  					not foo.bar()
    90  			)),
    91    }
    92  )`, `
    93  rule(
    94    attrs = {
    95        "foo": attr.label_list(mandatory = True, allow_empty = False),
    96        "bar": attr.label_list(mandatory = True, allow_empty = True),
    97        "baz": attr.label_list(mandatory = True, allow_empty = not foo.bar()),
    98        "qux": attr.label_list(mandatory = True, allow_empty = foo.bar()),
    99        "aaa": attr.label_list(mandatory = True, allow_empty = (not foo.bar())),
   100        "bbb": attr.label_list(mandatory = True, allow_empty = (
   101  					foo.bar()
   102  			)),
   103    }
   104  )`,
   105  		[]string{
   106  			":3: non_empty attributes for attr definitions are deprecated in favor of allow_empty.",
   107  			":4: non_empty attributes for attr definitions are deprecated in favor of allow_empty.",
   108  			":5: non_empty attributes for attr definitions are deprecated in favor of allow_empty.",
   109  			":6: non_empty attributes for attr definitions are deprecated in favor of allow_empty.",
   110  			":7: non_empty attributes for attr definitions are deprecated in favor of allow_empty.",
   111  			":8: non_empty attributes for attr definitions are deprecated in favor of allow_empty.",
   112  		},
   113  		scopeBzl)
   114  }
   115  
   116  func TestAttrSingleFileWarning(t *testing.T) {
   117  	checkFindingsAndFix(t, "attr-single-file", `
   118  rule(
   119    attrs = {
   120        "foo": attr.label_list(single_file = True, allow_files = [".cc"], mandatory = True),
   121        "bar": attr.label_list(single_file = True, mandatory = True),
   122        "baz": attr.label_list(single_file = False, mandatory = True),
   123    }
   124  )`, `
   125  rule(
   126    attrs = {
   127        "foo": attr.label_list(allow_single_file = [".cc"], mandatory = True),
   128        "bar": attr.label_list(allow_single_file = True, mandatory = True),
   129        "baz": attr.label_list(mandatory = True),
   130  	}
   131  )`,
   132  		[]string{
   133  			":3: single_file is deprecated in favor of allow_single_file.",
   134  			":4: single_file is deprecated in favor of allow_single_file.",
   135  			":5: single_file is deprecated in favor of allow_single_file.",
   136  		},
   137  		scopeBzl)
   138  }
   139  
   140  func TestCtxActionsWarning(t *testing.T) {
   141  	checkFindingsAndFix(t, "ctx-actions", `
   142  def impl(ctx):
   143    ctx.new_file(foo)
   144    ctx.new_file(foo, "foo %s " % bar)
   145    ctx.new_file(foo, name = bar)
   146    ctx.new_file(foo, bar, baz)
   147    ctx.experimental_new_directory(foo, bar)
   148    ctx.file_action(foo, bar)
   149    ctx.file_action(foo, bar, executable = True)
   150    ctx.action(foo, bar, command = "foo")
   151    ctx.action(foo, bar, executable = "bar")
   152    ctx.empty_action(foo, bar)
   153    ctx.template_action(foo, bar)
   154    ctx.template_action(foo, bar, executable = True)
   155  	ctx.foobar(foo, bar)
   156  `, `
   157  def impl(ctx):
   158    ctx.actions.declare_file(foo)
   159    ctx.actions.declare_file("foo %s " % bar, sibling = foo)
   160    ctx.actions.declare_file(bar, sibling = foo)
   161    ctx.new_file(foo, bar, baz)
   162    ctx.actions.declare_directory(foo, bar)
   163    ctx.actions.write(foo, bar)
   164    ctx.actions.write(foo, bar, is_executable = True)
   165    ctx.actions.run_shell(foo, bar, command = "foo")
   166    ctx.actions.run(foo, bar, executable = "bar")
   167    ctx.actions.do_nothing(foo, bar)
   168    ctx.actions.expand_template(foo, bar)
   169    ctx.actions.expand_template(foo, bar, is_executable = True)
   170  	ctx.foobar(foo, bar)
   171  `,
   172  		[]string{
   173  			`:2: "ctx.new_file" is deprecated in favor of "ctx.actions.declare_file".`,
   174  			`:3: "ctx.new_file" is deprecated in favor of "ctx.actions.declare_file".`,
   175  			`:4: "ctx.new_file" is deprecated in favor of "ctx.actions.declare_file".`,
   176  			`:5: "ctx.new_file" is deprecated in favor of "ctx.actions.declare_file".`,
   177  			`:6: "ctx.experimental_new_directory" is deprecated in favor of "ctx.actions.declare_directory".`,
   178  			`:7: "ctx.file_action" is deprecated in favor of "ctx.actions.write".`,
   179  			`:8: "ctx.file_action" is deprecated in favor of "ctx.actions.write".`,
   180  			`:9: "ctx.action" is deprecated in favor of "ctx.actions.run_shell".`,
   181  			`:10: "ctx.action" is deprecated in favor of "ctx.actions.run".`,
   182  			`:11: "ctx.empty_action" is deprecated in favor of "ctx.actions.do_nothing".`,
   183  			`:12: "ctx.template_action" is deprecated in favor of "ctx.actions.expand_template".`,
   184  			`:13: "ctx.template_action" is deprecated in favor of "ctx.actions.expand_template".`,
   185  		},
   186  		scopeBzl)
   187  
   188  	checkFindings(t, "ctx-actions", `
   189  def impl(ctx):
   190    ctx.new_file(foo, bar, baz)
   191  `, []string{
   192  		`:2: "ctx.new_file" is deprecated in favor of "ctx.actions.declare_file".`,
   193  	}, scopeBzl)
   194  }
   195  
   196  func TestPackageNameWarning(t *testing.T) {
   197  	checkFindingsAndFix(t, "package-name", `
   198  foo(a = PACKAGE_NAME)
   199  
   200  def f(PACKAGE_NAME):
   201      foo(a = PACKAGE_NAME)
   202  
   203  def g():
   204      foo(a = PACKAGE_NAME)
   205  `, `
   206  foo(a = native.package_name())
   207  
   208  def f(PACKAGE_NAME):
   209      foo(a = PACKAGE_NAME)
   210  
   211  def g():
   212      foo(a = native.package_name())
   213  `,
   214  		[]string{
   215  			`:1: Global variable "PACKAGE_NAME" is deprecated in favor of "native.package_name()". Please rename it.`,
   216  			`:7: Global variable "PACKAGE_NAME" is deprecated in favor of "native.package_name()". Please rename it.`,
   217  		},
   218  		scopeBzl)
   219  
   220  	checkFindings(t, "package-name", `
   221  PACKAGE_NAME = "foo"
   222  foo(a = PACKAGE_NAME)
   223  `, []string{}, scopeBzl)
   224  
   225  	checkFindings(t, "package-name", `
   226  load(":foo.bzl", "PACKAGE_NAME")
   227  foo(a = PACKAGE_NAME)
   228  `, []string{}, scopeBzl)
   229  }
   230  
   231  func TestRepositoryNameWarning(t *testing.T) {
   232  	checkFindingsAndFix(t, "repository-name", `
   233  foo(a = REPOSITORY_NAME)
   234  
   235  def f(REPOSITORY_NAME):
   236      foo(a = REPOSITORY_NAME)
   237  
   238  def g():
   239      foo(a = REPOSITORY_NAME)
   240  `, `
   241  foo(a = native.repository_name())
   242  
   243  def f(REPOSITORY_NAME):
   244      foo(a = REPOSITORY_NAME)
   245  
   246  def g():
   247      foo(a = native.repository_name())
   248  `,
   249  		[]string{
   250  			`:1: Global variable "REPOSITORY_NAME" is deprecated in favor of "native.repository_name()". Please rename it.`,
   251  			`:7: Global variable "REPOSITORY_NAME" is deprecated in favor of "native.repository_name()". Please rename it.`,
   252  		}, scopeBzl)
   253  
   254  	checkFindings(t, "repository-name", `
   255  REPOSITORY_NAME = "foo"
   256  foo(a = REPOSITORY_NAME)
   257  `, []string{}, scopeBzl)
   258  
   259  	checkFindings(t, "repository-name", `
   260  load(":foo.bzl", "REPOSITORY_NAME")
   261  foo(a = REPOSITORY_NAME)
   262  `, []string{}, scopeBzl)
   263  }
   264  
   265  func TestFileTypeNameWarning(t *testing.T) {
   266  	checkFindings(t, "filetype", `
   267  rule1(types=FileType([".cc", ".h"]))
   268  rule2(types=FileType(types=[".cc", ".h"]))
   269  
   270  FileType(foobar)
   271  
   272  def macro1():
   273      a = FileType([".py"])
   274  
   275  def macro2():
   276      FileType = foo
   277      b = FileType([".java"])
   278  `, []string{
   279  		":1: The FileType function is deprecated.",
   280  		":2: The FileType function is deprecated.",
   281  		":4: The FileType function is deprecated.",
   282  		":7: The FileType function is deprecated.",
   283  	}, scopeBzl)
   284  
   285  	checkFindings(t, "filetype", `
   286  FileType = foo
   287  
   288  rule1(types=FileType([".cc", ".h"]))
   289  rule2(types=FileType(types=[".cc", ".h"]))
   290  `, []string{}, scopeBzl)
   291  }
   292  
   293  func TestOutputGroupWarning(t *testing.T) {
   294  	checkFindingsAndFix(t, "output-group", `
   295  def _impl(ctx):
   296      bin = ctx.attr.my_dep.output_group.bin
   297  `, `
   298  def _impl(ctx):
   299      bin = ctx.attr.my_dep[OutputGroupInfo].bin
   300  `,
   301  		[]string{
   302  			`:2: "ctx.attr.dep.output_group" is deprecated in favor of "ctx.attr.dep[OutputGroupInfo]".`,
   303  		},
   304  		scopeBzl)
   305  }
   306  
   307  func TestNativeGitRepositoryWarning(t *testing.T) {
   308  	checkFindingsAndFix(t, "git-repository", `
   309  """My file"""
   310  
   311  def macro():
   312      git_repository(foo, bar)
   313  `, `
   314  """My file"""
   315  
   316  load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
   317  
   318  def macro():
   319      git_repository(foo, bar)
   320  `,
   321  		[]string{
   322  			`:4: Function "git_repository" is not global anymore and needs to be loaded from "@bazel_tools//tools/build_defs/repo:git.bzl".`,
   323  		},
   324  		scopeBzl)
   325  
   326  	checkFindingsAndFix(t, "git-repository", `
   327  """My file"""
   328  
   329  def macro():
   330      git_repository(foo, bar)
   331      new_git_repository(foo, bar)
   332  `, `
   333  """My file"""
   334  
   335  load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository", "new_git_repository")
   336  
   337  def macro():
   338      git_repository(foo, bar)
   339      new_git_repository(foo, bar)
   340  `,
   341  		[]string{
   342  			`:4: Function "git_repository" is not global anymore and needs to be loaded from "@bazel_tools//tools/build_defs/repo:git.bzl".`,
   343  			`:5: Function "new_git_repository" is not global anymore and needs to be loaded from "@bazel_tools//tools/build_defs/repo:git.bzl".`,
   344  		},
   345  		scopeBzl)
   346  
   347  	checkFindingsAndFix(t, "git-repository", `
   348  """My file"""
   349  
   350  load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
   351  
   352  def macro():
   353      git_repository(foo, bar)
   354      new_git_repository(foo, bar)
   355  `, `
   356  """My file"""
   357  
   358  load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository", "new_git_repository")
   359  
   360  def macro():
   361      git_repository(foo, bar)
   362      new_git_repository(foo, bar)
   363  `,
   364  		[]string{
   365  			`:7: Function "new_git_repository" is not global anymore and needs to be loaded from "@bazel_tools//tools/build_defs/repo:git.bzl".`,
   366  		},
   367  		scopeBzl)
   368  }
   369  
   370  func TestNativeHttpArchiveWarning(t *testing.T) {
   371  	checkFindingsAndFix(t, "http-archive", `
   372  """My file"""
   373  
   374  def macro():
   375      http_archive(foo, bar)
   376  `, `
   377  """My file"""
   378  
   379  load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
   380  
   381  def macro():
   382      http_archive(foo, bar)
   383  `,
   384  		[]string{
   385  			`:4: Function "http_archive" is not global anymore and needs to be loaded from "@bazel_tools//tools/build_defs/repo:http.bzl".`,
   386  		},
   387  		scopeBzl)
   388  }
   389  
   390  func TestContextArgsAPIWarning(t *testing.T) {
   391  	checkFindingsAndFix(t, "ctx-args", `
   392  def impl(ctx):
   393      args = ctx.actions.args()
   394      args.add(foo, bar)
   395      args.add(foo, bar, before_each = aaa)
   396      args.add(foo, bar, join_with = bbb)
   397      args.add(foo, bar, before_each = ccc, join_with = ddd)
   398      args.add(foo, bar, map_fn = eee)
   399      args.add(foo, bar, map_fn = fff, before_each = ggg)
   400      args.add(foo, bar, map_fn = hhh, join_with = iii)
   401      args.add(foo, bar, map_fn = jjj, before_each = kkk, join_with = lll)
   402  `, `
   403  def impl(ctx):
   404      args = ctx.actions.args()
   405      args.add(foo, bar)
   406      args.add_all(foo, bar, before_each = aaa)
   407      args.add_joined(foo, bar, join_with = bbb)
   408      args.add_joined(foo, bar, format_each = ccc + "%s", join_with = ddd)
   409      args.add_all(foo, bar, map_each = eee)
   410      args.add_all(foo, bar, map_each = fff, before_each = ggg)
   411      args.add_joined(foo, bar, map_each = hhh, join_with = iii)
   412      args.add_joined(foo, bar, map_each = jjj, format_each = kkk + "%s", join_with = lll)
   413  `,
   414  		[]string{
   415  			`:4: "ctx.actions.args().add()" for multiple arguments is deprecated in favor of "add_all()" or "add_joined()".`,
   416  			`:5: "ctx.actions.args().add()" for multiple arguments is deprecated in favor of "add_all()" or "add_joined()".`,
   417  			`:6: "ctx.actions.args().add()" for multiple arguments is deprecated in favor of "add_all()" or "add_joined()".`,
   418  			`:7: "ctx.actions.args().add()" for multiple arguments is deprecated in favor of "add_all()" or "add_joined()".`,
   419  			`:8: "ctx.actions.args().add()" for multiple arguments is deprecated in favor of "add_all()" or "add_joined()".`,
   420  			`:9: "ctx.actions.args().add()" for multiple arguments is deprecated in favor of "add_all()" or "add_joined()".`,
   421  			`:10: "ctx.actions.args().add()" for multiple arguments is deprecated in favor of "add_all()" or "add_joined()".`,
   422  		},
   423  		scopeBzl)
   424  }
   425  
   426  func TestAttrOutputDefault(t *testing.T) {
   427  	checkFindings(t, "attr-output-default", `
   428  rule(
   429    attrs = {
   430        "foo": attr.output(default="foo"),
   431        "bar": attr.output(not_default="foo"),
   432        "baz": attr.string(default="foo"),
   433    }
   434  )
   435  `,
   436  		[]string{
   437  			`:3: The "default" parameter for attr.output() is deprecated.`,
   438  		},
   439  		scopeBzl)
   440  }
   441  
   442  func TestAttrLicense(t *testing.T) {
   443  	checkFindings(t, "attr-license", `
   444  rule(
   445    attrs = {
   446        "foo": attr.license(foo),
   447        "bar": attr.license(),
   448        "baz": attr.no_license(),
   449    }
   450  )
   451  `, []string{
   452  		`:3: "attr.license()" is deprecated and shouldn't be used.`,
   453  		`:4: "attr.license()" is deprecated and shouldn't be used.`,
   454  	}, scopeBzl)
   455  }
   456  
   457  func TestRuleImplReturn(t *testing.T) {
   458  	checkFindings(t, "rule-impl-return", `
   459  def _impl(ctx):
   460    return struct()
   461  
   462  rule(implementation=_impl)
   463  `, []string{
   464  		`:2: Avoid using the legacy provider syntax.`,
   465  	}, scopeBzl)
   466  
   467  	checkFindings(t, "rule-impl-return", `
   468  def _impl(ctx):
   469    if True:
   470      return struct()
   471    return
   472  
   473  x = rule(_impl, attrs = {})
   474  `, []string{
   475  		`:3: Avoid using the legacy provider syntax.`,
   476  	}, scopeBzl)
   477  
   478  	checkFindings(t, "rule-impl-return", `
   479  def _impl(ctx):
   480    pass  # no return statements
   481  
   482  x = rule(_impl, attrs = {})
   483  `, []string{}, scopeBzl)
   484  
   485  	checkFindings(t, "rule-impl-return", `
   486  def _impl1():  # not used as a rule implementation function
   487    return struct()
   488  
   489  def _impl2():  # no structs returned
   490    if x:
   491      return []
   492    elif y:
   493      return foo()
   494    return
   495  
   496  x = rule(
   497    implementation=_impl2,
   498  )
   499  
   500  rule(
   501    _impl3,  # not defined here
   502  )
   503  
   504  rule(
   505    _impl1(),  # not an identifier
   506  )
   507  
   508  rule()  # no parameters
   509  rule(foo = bar)  # no matching parameters
   510  `, []string{}, scopeBzl)
   511  }
   512  
   513  func TestNativeAndroidWarning(t *testing.T) {
   514  	checkFindingsAndFix(t, "native-android", `
   515  """My file"""
   516  
   517  def macro():
   518      aar_import()
   519      android_library()
   520      native.android_library()
   521      native.android_local_test()
   522  
   523  android_binary()
   524  `, fmt.Sprintf(`
   525  """My file"""
   526  
   527  load(%q, "aar_import", "android_binary", "android_library", "android_local_test")
   528  
   529  def macro():
   530      aar_import()
   531      android_library()
   532      android_library()
   533      android_local_test()
   534  
   535  android_binary()
   536  `, tables.AndroidLoadPath),
   537  		[]string{
   538  			fmt.Sprintf(`:4: Function "aar_import" is not global anymore and needs to be loaded from "%s".`, tables.AndroidLoadPath),
   539  			fmt.Sprintf(`:5: Function "android_library" is not global anymore and needs to be loaded from "%s".`, tables.AndroidLoadPath),
   540  			fmt.Sprintf(`:6: Function "android_library" is not global anymore and needs to be loaded from "%s".`, tables.AndroidLoadPath),
   541  			fmt.Sprintf(`:7: Function "android_local_test" is not global anymore and needs to be loaded from "%s".`, tables.AndroidLoadPath),
   542  			fmt.Sprintf(`:9: Function "android_binary" is not global anymore and needs to be loaded from "%s".`, tables.AndroidLoadPath),
   543  		},
   544  		scopeBzl|scopeBuild)
   545  }
   546  
   547  func TestNativeCcWarning(t *testing.T) {
   548  	checkFindingsAndFix(t, "native-cc", `
   549  """My file"""
   550  
   551  def macro():
   552      cc_library()
   553      native.cc_binary()
   554      cc_test()
   555      cc_proto_library()
   556      native.fdo_prefetch_hints()
   557      native.objc_library()
   558      objc_import()
   559      cc_toolchain()
   560      native.cc_toolchain_suite()
   561  
   562  fdo_profile()
   563  cc_import()
   564  `, fmt.Sprintf(`
   565  """My file"""
   566  
   567  load(%q, "cc_binary", "cc_import", "cc_library", "cc_proto_library", "cc_test", "cc_toolchain", "cc_toolchain_suite", "fdo_prefetch_hints", "fdo_profile", "objc_import", "objc_library")
   568  
   569  def macro():
   570      cc_library()
   571      cc_binary()
   572      cc_test()
   573      cc_proto_library()
   574      fdo_prefetch_hints()
   575      objc_library()
   576      objc_import()
   577      cc_toolchain()
   578      cc_toolchain_suite()
   579  
   580  fdo_profile()
   581  cc_import()
   582  `, tables.CcLoadPath),
   583  		[]string{
   584  			fmt.Sprintf(`:4: Function "cc_library" is not global anymore and needs to be loaded from "%s".`, tables.CcLoadPath),
   585  			fmt.Sprintf(`:5: Function "cc_binary" is not global anymore and needs to be loaded from "%s".`, tables.CcLoadPath),
   586  			fmt.Sprintf(`:6: Function "cc_test" is not global anymore and needs to be loaded from "%s".`, tables.CcLoadPath),
   587  			fmt.Sprintf(`:7: Function "cc_proto_library" is not global anymore and needs to be loaded from "%s".`, tables.CcLoadPath),
   588  			fmt.Sprintf(`:8: Function "fdo_prefetch_hints" is not global anymore and needs to be loaded from "%s".`, tables.CcLoadPath),
   589  			fmt.Sprintf(`:9: Function "objc_library" is not global anymore and needs to be loaded from "%s".`, tables.CcLoadPath),
   590  			fmt.Sprintf(`:10: Function "objc_import" is not global anymore and needs to be loaded from "%s".`, tables.CcLoadPath),
   591  			fmt.Sprintf(`:11: Function "cc_toolchain" is not global anymore and needs to be loaded from "%s".`, tables.CcLoadPath),
   592  			fmt.Sprintf(`:12: Function "cc_toolchain_suite" is not global anymore and needs to be loaded from "%s".`, tables.CcLoadPath),
   593  			fmt.Sprintf(`:14: Function "fdo_profile" is not global anymore and needs to be loaded from "%s".`, tables.CcLoadPath),
   594  			fmt.Sprintf(`:15: Function "cc_import" is not global anymore and needs to be loaded from "%s".`, tables.CcLoadPath),
   595  		},
   596  		scopeBzl|scopeBuild)
   597  }
   598  
   599  func TestNativeJavaWarning(t *testing.T) {
   600  	checkFindingsAndFix(t, "native-java", `
   601  """My file"""
   602  
   603  def macro():
   604      java_import()
   605      java_library()
   606      native.java_library()
   607      native.java_binary()
   608  
   609  java_test()
   610  `, fmt.Sprintf(`
   611  """My file"""
   612  
   613  load(%q, "java_binary", "java_import", "java_library", "java_test")
   614  
   615  def macro():
   616      java_import()
   617      java_library()
   618      java_library()
   619      java_binary()
   620  
   621  java_test()
   622  `, tables.JavaLoadPath),
   623  		[]string{
   624  			fmt.Sprintf(`:4: Function "java_import" is not global anymore and needs to be loaded from "%s".`, tables.JavaLoadPath),
   625  			fmt.Sprintf(`:5: Function "java_library" is not global anymore and needs to be loaded from "%s".`, tables.JavaLoadPath),
   626  			fmt.Sprintf(`:6: Function "java_library" is not global anymore and needs to be loaded from "%s".`, tables.JavaLoadPath),
   627  			fmt.Sprintf(`:7: Function "java_binary" is not global anymore and needs to be loaded from "%s".`, tables.JavaLoadPath),
   628  			fmt.Sprintf(`:9: Function "java_test" is not global anymore and needs to be loaded from "%s".`, tables.JavaLoadPath),
   629  		},
   630  		scopeBzl|scopeBuild)
   631  }
   632  
   633  func TestNativePyWarning(t *testing.T) {
   634  	checkFindingsAndFix(t, "native-py", `
   635  """My file"""
   636  
   637  def macro():
   638      py_library()
   639      py_binary()
   640      native.py_test()
   641      native.py_runtime()
   642  
   643  py_test()
   644  `, fmt.Sprintf(`
   645  """My file"""
   646  
   647  load(%q, "py_binary", "py_library", "py_runtime", "py_test")
   648  
   649  def macro():
   650      py_library()
   651      py_binary()
   652      py_test()
   653      py_runtime()
   654  
   655  py_test()
   656  `, tables.PyLoadPath),
   657  		[]string{
   658  			fmt.Sprintf(`:4: Function "py_library" is not global anymore and needs to be loaded from "%s".`, tables.PyLoadPath),
   659  			fmt.Sprintf(`:5: Function "py_binary" is not global anymore and needs to be loaded from "%s".`, tables.PyLoadPath),
   660  			fmt.Sprintf(`:6: Function "py_test" is not global anymore and needs to be loaded from "%s".`, tables.PyLoadPath),
   661  			fmt.Sprintf(`:7: Function "py_runtime" is not global anymore and needs to be loaded from "%s".`, tables.PyLoadPath),
   662  			fmt.Sprintf(`:9: Function "py_test" is not global anymore and needs to be loaded from "%s".`, tables.PyLoadPath),
   663  		},
   664  		scopeBzl|scopeBuild)
   665  }
   666  
   667  func TestNativeProtoWarning(t *testing.T) {
   668  	checkFindingsAndFix(t, "native-proto", `
   669  """My file"""
   670  
   671  def macro():
   672      proto_library()
   673      proto_lang_toolchain()
   674      native.proto_lang_toolchain()
   675      native.proto_library()
   676  
   677      ProtoInfo
   678      proto_common
   679  `, fmt.Sprintf(`
   680  """My file"""
   681  
   682  load(%q, "ProtoInfo", "proto_common", "proto_lang_toolchain", "proto_library")
   683  
   684  def macro():
   685      proto_library()
   686      proto_lang_toolchain()
   687      proto_lang_toolchain()
   688      proto_library()
   689  
   690      ProtoInfo
   691      proto_common
   692  `, tables.ProtoLoadPath),
   693  		[]string{
   694  			fmt.Sprintf(`:4: Function "proto_library" is not global anymore and needs to be loaded from "%s".`, tables.ProtoLoadPath),
   695  			fmt.Sprintf(`:5: Function "proto_lang_toolchain" is not global anymore and needs to be loaded from "%s".`, tables.ProtoLoadPath),
   696  			fmt.Sprintf(`:6: Function "proto_lang_toolchain" is not global anymore and needs to be loaded from "%s".`, tables.ProtoLoadPath),
   697  			fmt.Sprintf(`:7: Function "proto_library" is not global anymore and needs to be loaded from "%s".`, tables.ProtoLoadPath),
   698  			fmt.Sprintf(`:9: Symbol "ProtoInfo" is not global anymore and needs to be loaded from "%s".`, tables.ProtoLoadPath),
   699  			fmt.Sprintf(`:10: Symbol "proto_common" is not global anymore and needs to be loaded from "%s".`, tables.ProtoLoadPath),
   700  		},
   701  		scopeBzl|scopeBuild)
   702  }
   703  
   704  func TestKeywordParameters(t *testing.T) {
   705  	checkFindingsAndFix(t, "keyword-positional-params", `
   706  foo(key = value)
   707  all(elements = [True, False])
   708  any(elements = [True, False])
   709  tuple(x = [1, 2, 3])
   710  list(x = [1, 2, 3])
   711  len(x = [1, 2, 3])
   712  str(x = foo)
   713  repr(x = foo)
   714  bool(x = 3)
   715  int(x = "3")
   716  int(x = "13", base = 8)
   717  dir(x = foo)
   718  type(x = foo)
   719  select(x = {})
   720  `, `
   721  foo(key = value)
   722  all([True, False])
   723  any([True, False])
   724  tuple([1, 2, 3])
   725  list([1, 2, 3])
   726  len([1, 2, 3])
   727  str(foo)
   728  repr(foo)
   729  bool(3)
   730  int("3")
   731  int("13", base = 8)
   732  dir(foo)
   733  type(foo)
   734  select({})
   735  `, []string{
   736  		`:2: Keyword parameter "elements" for "all" should be positional.`,
   737  		`:3: Keyword parameter "elements" for "any" should be positional.`,
   738  		`:4: Keyword parameter "x" for "tuple" should be positional.`,
   739  		`:5: Keyword parameter "x" for "list" should be positional.`,
   740  		`:6: Keyword parameter "x" for "len" should be positional.`,
   741  		`:7: Keyword parameter "x" for "str" should be positional.`,
   742  		`:8: Keyword parameter "x" for "repr" should be positional.`,
   743  		`:9: Keyword parameter "x" for "bool" should be positional.`,
   744  		`:10: Keyword parameter "x" for "int" should be positional.`,
   745  		`:11: Keyword parameter "x" for "int" should be positional.`,
   746  		`:12: Keyword parameter "x" for "dir" should be positional.`,
   747  		`:13: Keyword parameter "x" for "type" should be positional.`,
   748  		`:14: Keyword parameter "x" for "select" should be positional.`,
   749  	}, scopeEverywhere)
   750  
   751  	checkFindingsAndFix(t, "keyword-positional-params", `
   752  hasattr(
   753    x = foo,
   754    name = "bar",
   755  )
   756  getattr(
   757    x = foo,
   758    name = "bar",
   759  )
   760  getattr(
   761    x = foo,
   762    name = "bar",
   763    default = "baz",
   764  )
   765  `, `
   766  hasattr(
   767    foo,
   768    "bar",
   769  )
   770  getattr(
   771    foo,
   772    "bar",
   773  )
   774  getattr(
   775    foo,
   776    "bar",
   777    "baz",
   778  )
   779  `, []string{
   780  		`:2: Keyword parameter "x" for "hasattr" should be positional.`,
   781  		`:3: Keyword parameter "name" for "hasattr" should be positional.`,
   782  		`:6: Keyword parameter "x" for "getattr" should be positional.`,
   783  		`:7: Keyword parameter "name" for "getattr" should be positional.`,
   784  		`:10: Keyword parameter "x" for "getattr" should be positional.`,
   785  		`:11: Keyword parameter "name" for "getattr" should be positional.`,
   786  		`:12: Keyword parameter "default" for "getattr" should be positional.`,
   787  	}, scopeEverywhere)
   788  }
   789  
   790  func TestProvider(t *testing.T) {
   791  	checkFindings(t, "provider-params", `provider(doc = "doc", fields = [])`, []string{}, scopeBzl)
   792  	checkFindings(t, "provider-params", `provider("doc", fields = [])`, []string{}, scopeBzl)
   793  	checkFindings(t, "provider-params", `provider(fields = None, doc = "doc")`, []string{}, scopeBzl)
   794  
   795  	checkFindings(t, "provider-params", `provider(fields = [])`,
   796  		[]string{`1: Calls to 'provider' should provide a documentation`}, scopeBzl)
   797  	checkFindings(t, "provider-params", `provider(doc = "doc")`,
   798  		[]string{`1: Calls to 'provider' should provide a list of fields:`}, scopeBzl)
   799  	checkFindings(t, "provider-params", `p = provider()`,
   800  		[]string{`1: Calls to 'provider' should provide a list of fields and a documentation:`}, scopeBzl)
   801  }
   802  
   803  func TestAttributeNameWarning(t *testing.T) {
   804  	checkFindings(t, "attr-licenses", `
   805  def _impl(ctx):
   806      pass
   807  
   808  foo = rule(
   809      implementation = _impl,
   810      attrs = {
   811          "license": attr.string(),
   812          "licenses": attr.string(),
   813      },
   814  )
   815  `, []string{
   816  		":6: Do not use 'licenses' as an attribute name. It may cause unexpected behavior.",
   817  	}, scopeBzl)
   818  
   819  	checkFindings(t, "attr-applicable_licenses", `
   820  def _impl(ctx):
   821      pass
   822  
   823  foo = rule(
   824      implementation = _impl,
   825      attrs = {
   826          "applicable_licenses": attr.string(),
   827          "package_metadata": attr.string(),
   828      },
   829  )
   830  `, []string{
   831  		":6: Do not use 'applicable_licenses' as an attribute name. It may cause unexpected behavior.",
   832  		":6: Do not use 'package_metadata' as an attribute name. It may cause unexpected behavior.",
   833  	}, scopeBzl)
   834  }
   835  

View as plain text