diff --git a/src/com/google/common/css/JobDescription.java b/src/com/google/common/css/JobDescription.java index f9c94e2e..08d70571 100644 --- a/src/com/google/common/css/JobDescription.java +++ b/src/com/google/common/css/JobDescription.java @@ -48,6 +48,7 @@ public class JobDescription { public final boolean eliminateDeadStyles; public final boolean allowDefPropagation; public final boolean allowUnrecognizedFunctions; + public final boolean allowDuplicateDeclarations; public final Set allowedNonStandardFunctions; public final boolean allowUnrecognizedProperties; public final Set allowedUnrecognizedProperties; @@ -127,6 +128,7 @@ public enum SourceMapDetailLevel { ALL, DEFAULT } boolean swapLeftRightInUrl, boolean simplifyCss, boolean eliminateDeadStyles, boolean allowDefPropagation, boolean allowUnrecognizedFunctions, + boolean allowDuplicateDeclarations, Set allowedNonStandardFunctions, boolean allowUnrecognizedProperties, Set allowedUnrecognizedProperties, boolean allowUndefinedConstants, @@ -167,6 +169,7 @@ public enum SourceMapDetailLevel { ALL, DEFAULT } this.eliminateDeadStyles = eliminateDeadStyles; this.allowDefPropagation = allowDefPropagation; this.allowUnrecognizedFunctions = allowUnrecognizedFunctions; + this.allowDuplicateDeclarations = allowDuplicateDeclarations; this.allowedNonStandardFunctions = ImmutableSet.copyOf( allowedNonStandardFunctions); this.allowUnrecognizedProperties = allowUnrecognizedProperties; diff --git a/src/com/google/common/css/JobDescriptionBuilder.java b/src/com/google/common/css/JobDescriptionBuilder.java index 0f4a9d5e..62f6774b 100644 --- a/src/com/google/common/css/JobDescriptionBuilder.java +++ b/src/com/google/common/css/JobDescriptionBuilder.java @@ -52,6 +52,7 @@ public class JobDescriptionBuilder { boolean eliminateDeadStyles; boolean allowDefPropagation; boolean allowUnrecognizedFunctions; + boolean allowDuplicateDeclarations; Set allowedNonStandardFunctions; boolean allowUnrecognizedProperties; Set allowedUnrecognizedProperties; @@ -91,6 +92,7 @@ public JobDescriptionBuilder() { this.eliminateDeadStyles = false; this.allowDefPropagation = false; this.allowUnrecognizedFunctions = false; + this.allowDuplicateDeclarations = false; this.allowedNonStandardFunctions = Sets.newHashSet(); this.allowUnrecognizedProperties = false; this.allowedUnrecognizedProperties = Sets.newHashSet(); @@ -129,6 +131,7 @@ public JobDescriptionBuilder copyFrom(JobDescription jobToCopy) { this.eliminateDeadStyles = jobToCopy.eliminateDeadStyles; this.allowDefPropagation = jobToCopy.allowDefPropagation; this.allowUnrecognizedFunctions = jobToCopy.allowUnrecognizedFunctions; + this.allowDuplicateDeclarations = jobToCopy.allowDuplicateDeclarations; this.allowedNonStandardFunctions = ImmutableSet.copyOf(jobToCopy.allowedNonStandardFunctions); this.allowUnrecognizedProperties = jobToCopy.allowUnrecognizedProperties; @@ -341,6 +344,16 @@ public JobDescriptionBuilder setAllowedNonStandardFunctions( return this; } + public JobDescriptionBuilder setAllowDuplicateDeclarations(boolean allow) { + checkJobIsNotAlreadyCreated(); + this.allowDuplicateDeclarations = allow; + return this; + } + + public JobDescriptionBuilder allowDuplicateDeclarations() { + return setAllowDuplicateDeclarations(true); + } + public JobDescriptionBuilder setAllowUnrecognizedProperties(boolean allow) { checkJobIsNotAlreadyCreated(); this.allowUnrecognizedProperties = allow; @@ -487,8 +500,9 @@ public JobDescription getJobDescription() { copyrightNotice, outputFormat, inputOrientation, outputOrientation, optimize, trueConditionNames, useInternalBidiFlipper, swapLtrRtlInUrl, swapLeftRightInUrl, simplifyCss, eliminateDeadStyles, - allowDefPropagation, allowUnrecognizedFunctions, allowedNonStandardFunctions, - allowUnrecognizedProperties, allowedUnrecognizedProperties, allowUndefinedConstants, + allowDefPropagation, allowUnrecognizedFunctions, allowDuplicateDeclarations, + allowedNonStandardFunctions, allowUnrecognizedProperties, + allowedUnrecognizedProperties, allowUndefinedConstants, allowMozDocument, vendor, allowKeyframes, allowWebkitKeyframes, processDependencies, allowedAtRules, cssRenamingPrefix, excludedClassesFromRenaming, diff --git a/src/com/google/common/css/compiler/commandline/ClosureCommandLineCompiler.java b/src/com/google/common/css/compiler/commandline/ClosureCommandLineCompiler.java index c33996e8..6c93e52f 100644 --- a/src/com/google/common/css/compiler/commandline/ClosureCommandLineCompiler.java +++ b/src/com/google/common/css/compiler/commandline/ClosureCommandLineCompiler.java @@ -162,6 +162,10 @@ static class Flags { "Allow unrecognized functions.") private boolean allowUnrecognizedFunctions = false; + @Option(name = "--allow-duplicate-declarations", usage = + "Allow duplicate declarations.") + private boolean allowDuplicateDeclarations = false; + @Option(name = "--allowed-non-standard-function", usage = "Specify a non-standard function to whitelist, like alpha()") private List allowedNonStandardFunctions = Lists.newArrayList(); @@ -237,6 +241,7 @@ JobDescription createJobDescription() { builder.setTrueConditionNames(trueConditions); builder.setAllowDefPropagation(allowDefPropagation); builder.setAllowUnrecognizedFunctions(allowUnrecognizedFunctions); + builder.setAllowDuplicateDeclarations(allowDuplicateDeclarations); builder.setAllowedNonStandardFunctions(allowedNonStandardFunctions); builder.setAllowedUnrecognizedProperties(allowedUnrecognizedProperties); builder.setAllowUnrecognizedProperties(allowUnrecognizedProperties); diff --git a/src/com/google/common/css/compiler/passes/PassRunner.java b/src/com/google/common/css/compiler/passes/PassRunner.java index 61557648..54a68885 100644 --- a/src/com/google/common/css/compiler/passes/PassRunner.java +++ b/src/com/google/common/css/compiler/passes/PassRunner.java @@ -142,10 +142,12 @@ public void runPasses(CssTree cssTree) { new AbbreviatePositionalValues( cssTree.getMutatingVisitController()).runPass(); } - if (job.eliminateDeadStyles) { - // Report errors for duplicate declarations + // Report errors for duplicate declarations + if (!job.allowDuplicateDeclarations) { new DisallowDuplicateDeclarations( cssTree.getVisitController(), errorManager).runPass(); + } + if (job.eliminateDeadStyles) { // Split rules by selector and declaration. new SplitRulesetNodes(cssTree.getMutatingVisitController()).runPass(); // Dead code elimination. diff --git a/tests/com/google/common/css/compiler/commandline/ClosureCommandLineCompilerTest.java b/tests/com/google/common/css/compiler/commandline/ClosureCommandLineCompilerTest.java index a81a9ae7..f53b7519 100644 --- a/tests/com/google/common/css/compiler/commandline/ClosureCommandLineCompilerTest.java +++ b/tests/com/google/common/css/compiler/commandline/ClosureCommandLineCompilerTest.java @@ -76,6 +76,15 @@ public void testAllowDefPropagationDefaultsToTrue() throws Exception { @Test + public void testAllowDuplicateDeclarationsDefaultsToFalse() throws Exception { + ClosureCommandLineCompiler.Flags flags = + ClosureCommandLineCompiler.parseArgs(new String[] {"/dev/null"}, EXIT_CODE_HANDLER); + JobDescription jobDescription = flags.createJobDescription(); + assertThat(jobDescription.allowDuplicateDeclarations).isFalse(); + } + + @Test + public void testEmptyImportBlocks() throws Exception { // See b/29995881 ErrorManager errorManager = new NewFunctionalTestBase.TestErrorManager(new String[0]);