From 1013c5289a1aea587bc1fdf765dc0140eab910df Mon Sep 17 00:00:00 2001 From: Googler Date: Fri, 5 Jan 2024 10:41:16 -0800 Subject: [PATCH] Refactor name conflict detection and error messaging This change is a no-op. - The idiom of checking the `targets` map for a newly added target and failing if it finds one, is factored into a new helper checkNameConflict(). - Updated javadoc to checkForConflicts(). Ensured that all existing checks are mentioned, and deleted reference to two conditions that don't appear to actually be checked: "no rule with errors is inserted into the package" -- we seem to do the opposite and propagate error bits from rules to the package; and "the generating rule of every output must itself be in the package" -- perhaps this is enforced elsewhere, but it's not part of this method. - Add TODO of me pondering whether we care if an output file prefix clashes with a non-output-file target. - Merge duplicateOutputFile() into nameConflict(). (This doesn't change the error message because nameConflict() was never called with an OutputFile as its first arg.) - Add TODO identifying that we don't actually verify that an output doesn't clash with its own generating rule, even though we check it against other previously introduced rules. - Rename conflictingOutputFile() -> overlappingOutputFilePrefixes() to distinguish from the other kinds of conflicts we're talking about. - Inline checkForInputOutputConflicts() and inputOutputNameConflict(), which each only had one call site and are more readable as part of checkForConflicts(). - Use String.format() more. Work toward #19922. PiperOrigin-RevId: 596031120 Change-Id: I02ed6bb4d0f4c1f5aa2bfa16c91835d92e4cef39 --- .../devtools/build/lib/packages/Package.java | 166 ++++++++---------- .../devtools/build/lib/packages/Rule.java | 4 +- 2 files changed, 79 insertions(+), 91 deletions(-) diff --git a/src/main/java/com/google/devtools/build/lib/packages/Package.java b/src/main/java/com/google/devtools/build/lib/packages/Package.java index 50eb695027b44f..c29c09e99230ad 100644 --- a/src/main/java/com/google/devtools/build/lib/packages/Package.java +++ b/src/main/java/com/google/devtools/build/lib/packages/Package.java @@ -915,7 +915,7 @@ private enum NameConflictCheckingPolicy { * file having that prefix. Used for error reporting. * *

This field is null if name conflict checking is disabled. It is also null after the - * package is built. + * package is built. The content of the map is manipulated only in {@link #checkForConflicts}. */ @Nullable private Map outputFilePrefixes = new HashMap<>(); @@ -1472,11 +1472,7 @@ void addPackageGroup( repoRootMeansCurrentRepo, eventHandler, location); - Target existing = targets.get(group.getName()); - if (existing != null) { - throw nameConflict(group, existing); - } - + checkNameConflict(group); targets.put(group.getName(), group); if (group.containsErrors()) { @@ -1526,12 +1522,9 @@ void addEnvironmentGroup( EnvironmentGroup group = new EnvironmentGroup(createLabel(name), pkg, environments, defaults, location); - Target existing = targets.get(group.getName()); - if (existing != null) { - throw nameConflict(group, existing); - } - + checkNameConflict(group); targets.put(group.getName(), group); + // Invariant: once group is inserted into targets, it must also: // (a) be inserted into environmentGroups, or // (b) have its group.processMemberEnvironments called. @@ -1587,6 +1580,10 @@ private void ensureNameConflictChecking() { this.nameConflictCheckingPolicy = NameConflictCheckingPolicy.ENABLED; } + /** + * Adds a rule and its outputs to the targets map, and propagates the error bit from the rule to + * the package. + */ private void addRuleInternal(Rule rule) { Preconditions.checkArgument(rule.getPackage() == pkg); for (OutputFile outputFile : rule.getOutputFiles()) { @@ -1775,40 +1772,49 @@ private InputFile addInputFile(InputFile inputFile) { } /** - * Precondition check for addRule. We must maintain these invariants of the package: + * Precondition check for {@link #addRule}. Verifies that: * *

*/ + // TODO(bazel-team): We verify that all prefixes of output files are distinct from other output + // file names, but not that they're distinct from other target names in the package. What + // happens if you define an input file "abc" and output file "abc/xyz"? private void checkForConflicts(Rule rule, List