/* Copyright 2020 Google LLC Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at https://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ // Warnings about visibility of .bzl files package warn import ( "fmt" "regexp" "strings" "github.com/bazelbuild/buildtools/build" ) var internalDirectory = regexp.MustCompile("/(internal|private)[/:]") func bzlVisibilityWarning(f *build.File) []*LinterFinding { var findings []*LinterFinding if f.WorkspaceRoot == "" { // Empty workspace root means buildifier doesn't know the location of // the file relative to the workspace directory and can't warn about .bzl // file visibility correctly. return findings } for _, stmt := range f.Stmt { load, ok := stmt.(*build.LoadStmt) if !ok || load.Module == nil { continue } // A load statement may use a fully qualified module name (including a // repository name). Buildifier should check if the repository name refers // to the current repository, but because it doesn't know the current // repository name it's better to assume that it matches the repository name // in the load statement: this way it may miss some usages of private .bzl // files that aren't supposed to be visible, but won't show false-positive // warnings in case the private file is actually allowed to be used. module := load.Module.Value if strings.HasPrefix(module, "@") { if chunks := strings.SplitN(module, "//", 2); len(chunks) == 2 { module = "//" + chunks[1] } } path := f.CanonicalPath() // Canonical name of the file chunks := internalDirectory.Split(module, 2) if len(chunks) < 2 { continue } if strings.HasPrefix(path, chunks[0]) || strings.HasPrefix(strings.Replace(path, "/javatests/", "/java/", 1), chunks[0]) { continue } findings = append(findings, makeLinterFinding( load.Module, fmt.Sprintf("Module %q can only be loaded from files located inside %q, not from %q.", load.Module.Value, chunks[0], path))) } return findings }