mirror of
https://github.com/Guardsquare/proguard.git
synced 2026-03-13 09:50:34 +08:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f6b82b1478 | ||
|
|
789777ded5 | ||
|
|
e76e47953f | ||
|
|
836253f1da | ||
|
|
f92fc632b1 | ||
|
|
f5f04cbec5 | ||
|
|
ce2c8a8b5d | ||
|
|
0032aa037c | ||
|
|
0070bc9e80 | ||
|
|
6f3610bd7b | ||
|
|
813616d095 | ||
|
|
04123e8f9b |
@@ -109,7 +109,7 @@ buildscript {
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.guardsquare:proguard-gradle:7.4.0'
|
||||
classpath 'com.guardsquare:proguard-gradle:7.4.1'
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -116,6 +116,9 @@ public class ConfigurationConstants
|
||||
public static final String DONT_PROCESS_KOTLIN_METADATA = "-dontprocesskotlinmetadata";
|
||||
public static final String OPTIMIZE_AGGRESSIVELY = "-optimizeaggressively";
|
||||
|
||||
public static final String ALWAYS_INLINE = "-alwaysinline";
|
||||
public static final String IDENTIFIER_NAME_STRING = "-identifiernamestring";
|
||||
|
||||
public static final String ANY_FILE_KEYWORD = "**";
|
||||
|
||||
public static final String ANY_ATTRIBUTE_KEYWORD = "*";
|
||||
|
||||
@@ -230,6 +230,8 @@ public class ConfigurationParser implements AutoCloseable
|
||||
else if (ConfigurationConstants.DUMP_OPTION .startsWith(nextWord)) configuration.dump = parseOptionalFile();
|
||||
else if (ConfigurationConstants.ADD_CONFIGURATION_DEBUGGING_OPTION .startsWith(nextWord)) configuration.addConfigurationDebugging = parseNoArgument(true);
|
||||
else if (ConfigurationConstants.OPTIMIZE_AGGRESSIVELY .startsWith(nextWord)) configuration.optimizeConservatively = parseNoArgument(false);
|
||||
else if (ConfigurationConstants.ALWAYS_INLINE .startsWith(nextWord)) parseUnsupportedR8Rules(ConfigurationConstants.ALWAYS_INLINE, true);
|
||||
else if (ConfigurationConstants.IDENTIFIER_NAME_STRING .startsWith(nextWord)) parseUnsupportedR8Rules(ConfigurationConstants.IDENTIFIER_NAME_STRING, true);
|
||||
else
|
||||
{
|
||||
throw new ParseException("Unknown option " + reader.locationDescription());
|
||||
@@ -850,7 +852,7 @@ public class ConfigurationParser implements AutoCloseable
|
||||
int requiredUnsetClassAccessFlags = 0;
|
||||
|
||||
// Parse the class annotations and access modifiers until the class keyword.
|
||||
while (!ConfigurationConstants.CLASS_KEYWORD.equals(nextWord))
|
||||
while (!ConfigurationConstants.CLASS_KEYWORD.equals(nextWord) && !configurationEnd(true))
|
||||
{
|
||||
// Strip the negating sign, if any.
|
||||
boolean negated =
|
||||
@@ -1181,24 +1183,29 @@ public class ConfigurationParser implements AutoCloseable
|
||||
// Did we get just one word before the opening parenthesis?
|
||||
if (ConfigurationConstants.OPEN_ARGUMENTS_KEYWORD.equals(name))
|
||||
{
|
||||
// This must be a constructor then.
|
||||
// Make sure the type is a proper constructor name.
|
||||
if (!(type.equals(ClassConstants.METHOD_NAME_INIT) ||
|
||||
type.equals(externalClassName) ||
|
||||
type.equals(ClassUtil.externalShortClassName(externalClassName))))
|
||||
// This must be an initializer then.
|
||||
// Make sure the type is a proper initializer name.
|
||||
if (ClassUtil.isInitializer(type))
|
||||
{
|
||||
name = type; // This is either `<init>` or `<clinit>`.
|
||||
type = JavaTypeConstants.VOID;
|
||||
}
|
||||
else if (type.equals(externalClassName) ||
|
||||
type.equals(ClassUtil.externalShortClassName(externalClassName)))
|
||||
{
|
||||
name = ClassConstants.METHOD_NAME_INIT;
|
||||
type = JavaTypeConstants.VOID;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ParseException("Expecting type and name " +
|
||||
"instead of just '" + type +
|
||||
"' before " + reader.locationDescription());
|
||||
}
|
||||
|
||||
// Assign the fixed constructor type and name.
|
||||
type = JavaTypeConstants.VOID;
|
||||
name = ClassConstants.METHOD_NAME_INIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
// It's not a constructor.
|
||||
// It's not an initializer.
|
||||
// Make sure we have a proper name.
|
||||
checkNextWordIsJavaIdentifier("class member name");
|
||||
|
||||
@@ -1209,7 +1216,7 @@ public class ConfigurationParser implements AutoCloseable
|
||||
}
|
||||
|
||||
// Check if the type actually contains the use of generics.
|
||||
// Can not do it right away as we also support "<init>" as a type (see case above).
|
||||
// Can not do it right away as we also support "<init>" and "<clinit>" as a type (see case above).
|
||||
if (containsGenerics(type))
|
||||
{
|
||||
throw new ParseException("Generics are not allowed (erased) for java type" + typeLocation);
|
||||
@@ -1290,6 +1297,14 @@ public class ConfigurationParser implements AutoCloseable
|
||||
"' before " + reader.locationDescription());
|
||||
}
|
||||
|
||||
// Class initializers are not supposed to have any parameters.
|
||||
if (ClassConstants.METHOD_NAME_CLINIT.equals(name) &&
|
||||
ClassUtil.internalMethodParameterCount(descriptor) > 0)
|
||||
{
|
||||
throw new ParseException("Not expecting method parameters with initializer '" + ClassConstants.METHOD_NAME_CLINIT +
|
||||
"' before " + reader.locationDescription());
|
||||
}
|
||||
|
||||
// Read the separator after the closing parenthesis.
|
||||
readNextWord("separator '" + ConfigurationConstants.SEPARATOR_KEYWORD + "'");
|
||||
|
||||
@@ -2027,6 +2042,21 @@ public class ConfigurationParser implements AutoCloseable
|
||||
}
|
||||
|
||||
|
||||
private void parseUnsupportedR8Rules(String option, boolean parseClassSpecification) throws IOException, ParseException
|
||||
{
|
||||
readNextWord();
|
||||
|
||||
if (parseClassSpecification)
|
||||
{
|
||||
parseClassSpecificationArguments();
|
||||
}
|
||||
|
||||
System.out.println("Warning: The R8 option " + option + " is currently not supported by ProGuard.\n" +
|
||||
"This option will have no effect on the optimized artifact.");
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A main method for testing configuration parsing.
|
||||
*/
|
||||
|
||||
@@ -50,7 +50,8 @@ public class ConfigurationWriter implements AutoCloseable
|
||||
|
||||
|
||||
private final PrintWriter writer;
|
||||
private File baseDir;
|
||||
private File configurationFile;
|
||||
private String baseDirName;
|
||||
|
||||
|
||||
/**
|
||||
@@ -60,7 +61,11 @@ public class ConfigurationWriter implements AutoCloseable
|
||||
{
|
||||
this(PrintWriterUtil.createPrintWriterOut(configurationFile));
|
||||
|
||||
baseDir = configurationFile.getParentFile();
|
||||
this.configurationFile = configurationFile;
|
||||
if (configurationFile.getParentFile() != null)
|
||||
{
|
||||
baseDirName = configurationFile.getParentFile().getAbsolutePath() + File.separator;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -79,7 +84,7 @@ public class ConfigurationWriter implements AutoCloseable
|
||||
@Override
|
||||
public void close() throws IOException
|
||||
{
|
||||
PrintWriterUtil.closePrintWriter(baseDir, writer);
|
||||
PrintWriterUtil.closePrintWriter(configurationFile, writer);
|
||||
}
|
||||
|
||||
|
||||
@@ -799,13 +804,9 @@ public class ConfigurationWriter implements AutoCloseable
|
||||
String fileName = file.getAbsolutePath();
|
||||
|
||||
// See if we can convert the file name into a relative file name.
|
||||
if (baseDir != null)
|
||||
if (baseDirName != null && fileName.startsWith(baseDirName))
|
||||
{
|
||||
String baseDirName = baseDir.getAbsolutePath() + File.separator;
|
||||
if (fileName.startsWith(baseDirName))
|
||||
{
|
||||
fileName = fileName.substring(baseDirName.length());
|
||||
}
|
||||
fileName = fileName.substring(baseDirName.length());
|
||||
}
|
||||
|
||||
return quotedString(fileName);
|
||||
@@ -819,6 +820,7 @@ public class ConfigurationWriter implements AutoCloseable
|
||||
{
|
||||
return string.length() == 0 ||
|
||||
string.indexOf(' ') >= 0 ||
|
||||
string.indexOf('#') >= 0 ||
|
||||
string.indexOf('@') >= 0 ||
|
||||
string.indexOf('{') >= 0 ||
|
||||
string.indexOf('}') >= 0 ||
|
||||
@@ -827,7 +829,7 @@ public class ConfigurationWriter implements AutoCloseable
|
||||
string.indexOf(':') >= 0 ||
|
||||
string.indexOf(';') >= 0 ||
|
||||
string.indexOf(',') >= 0 ? ("'" + string + "'") :
|
||||
( string );
|
||||
( string );
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -48,7 +48,6 @@ import proguard.strip.KotlinAnnotationStripper;
|
||||
import proguard.util.ConstantMatcher;
|
||||
import proguard.util.ListParser;
|
||||
import proguard.util.NameParser;
|
||||
import proguard.util.PrintWriterUtil;
|
||||
import proguard.util.StringMatcher;
|
||||
import proguard.util.kotlin.KotlinUnsupportedVersionChecker;
|
||||
import proguard.util.kotlin.asserter.KotlinMetadataVerifier;
|
||||
@@ -297,9 +296,7 @@ public class ProGuard
|
||||
*/
|
||||
private void printConfiguration() throws IOException
|
||||
{
|
||||
PrintWriter pw = PrintWriterUtil.createPrintWriterOut(configuration.printConfiguration);
|
||||
|
||||
try (ConfigurationWriter configurationWriter = new ConfigurationWriter(pw))
|
||||
try (ConfigurationWriter configurationWriter = new ConfigurationWriter(configuration.printConfiguration))
|
||||
{
|
||||
configurationWriter.write(configuration);
|
||||
}
|
||||
|
||||
@@ -11,8 +11,11 @@ import io.kotest.assertions.throwables.shouldThrow
|
||||
import io.kotest.core.spec.style.FreeSpec
|
||||
import io.kotest.matchers.shouldBe
|
||||
import io.kotest.matchers.shouldNotBe
|
||||
import io.kotest.matchers.string.shouldContain
|
||||
import proguard.classfile.AccessConstants.PUBLIC
|
||||
import testutils.asConfiguration
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.PrintStream
|
||||
|
||||
/**
|
||||
* Some simple testcases to catch special cases when parsing the Configuration.
|
||||
@@ -61,6 +64,31 @@ class ConfigurationParserTest : FreeSpec({
|
||||
parseConfiguration("-keep class * { public protected <methods>; }")
|
||||
}
|
||||
|
||||
"Keep rule with ClassName should be valid" {
|
||||
val configuration = parseConfiguration("-keep class ClassName { ClassName(); }")
|
||||
val keep = configuration.keep.single().methodSpecifications.single()
|
||||
keep.name shouldBe "<init>"
|
||||
keep.descriptor shouldBe "()V"
|
||||
}
|
||||
|
||||
"Keep rule with ClassName and external class com.example.ClassName should be valid" {
|
||||
val configuration = parseConfiguration("-keep class com.example.ClassName { ClassName(); }")
|
||||
val keep = configuration.keep.single().methodSpecifications.single()
|
||||
keep.name shouldBe "<init>"
|
||||
keep.descriptor shouldBe "()V"
|
||||
}
|
||||
|
||||
"Keep rule with <clinit> should be valid" {
|
||||
val configuration = parseConfiguration("-keep class ** { <clinit>(); }")
|
||||
val keep = configuration.keep.single().methodSpecifications.single()
|
||||
keep.name shouldBe "<clinit>"
|
||||
keep.descriptor shouldBe "()V"
|
||||
}
|
||||
|
||||
"Keep rule with <clinit> and non-empty argument list should throw ParseException" {
|
||||
shouldThrow<ParseException> { parseConfiguration("-keep class * { void <clinit>(int) }") }
|
||||
}
|
||||
|
||||
"Keep rule with * member wildcard and return type should be valid" {
|
||||
parseConfiguration("-keep class * { java.lang.String *; }")
|
||||
}
|
||||
@@ -82,6 +110,97 @@ class ConfigurationParserTest : FreeSpec({
|
||||
}
|
||||
}
|
||||
|
||||
"A ParseException should be thrown with invalid annotation config at the end of the file" - {
|
||||
// This is a parse error without any further config after it.
|
||||
val configStr = ("-keep @MyAnnotation @ThisShouldBeInterfaceKeyword")
|
||||
|
||||
"Then the option should throw a ParseException" {
|
||||
shouldThrow<ParseException> {
|
||||
configStr.asConfiguration()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"Testing -alwaysinline parsing" - {
|
||||
"Given an empty configuration" - {
|
||||
val savedPrintStream = System.out
|
||||
val customOutputStream = ByteArrayOutputStream()
|
||||
System.setOut(PrintStream(customOutputStream))
|
||||
|
||||
parseConfiguration("")
|
||||
|
||||
"The option does not print anything" {
|
||||
customOutputStream.toString() shouldContain ""
|
||||
System.setOut(savedPrintStream)
|
||||
}
|
||||
}
|
||||
|
||||
"Given a configuration with -alwaysinline" - {
|
||||
val savedPrintStream = System.out
|
||||
val customOutputStream = ByteArrayOutputStream()
|
||||
System.setOut(PrintStream(customOutputStream))
|
||||
|
||||
parseConfiguration(
|
||||
"""-alwaysinline class * {
|
||||
@org.chromium.build.annotations.AlwaysInline *;
|
||||
}
|
||||
"""
|
||||
)
|
||||
|
||||
"The option prints out a warning" {
|
||||
customOutputStream.toString() shouldContain "Warning: The R8 option -alwaysinline is currently not supported by ProGuard.\n" +
|
||||
"This option will have no effect on the optimized artifact."
|
||||
System.setOut(savedPrintStream)
|
||||
}
|
||||
}
|
||||
|
||||
"Given a configuration with -alwaysinline with no class specification" - {
|
||||
"The parsing should throw an exception" {
|
||||
shouldThrow<ParseException> { parseConfiguration("-alwaysinline") }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"Testing -identifiernamestring parsing" - {
|
||||
"Given an empty configuration" - {
|
||||
val savedPrintStream = System.out
|
||||
val customOutputStream = ByteArrayOutputStream()
|
||||
System.setOut(PrintStream(customOutputStream))
|
||||
|
||||
parseConfiguration("")
|
||||
|
||||
"The option does not print anything" {
|
||||
customOutputStream.toString() shouldContain ""
|
||||
System.setOut(savedPrintStream)
|
||||
}
|
||||
}
|
||||
|
||||
"Given a configuration with -identifiernamestring" - {
|
||||
val savedPrintStream = System.out
|
||||
val customOutputStream = ByteArrayOutputStream()
|
||||
System.setOut(PrintStream(customOutputStream))
|
||||
|
||||
parseConfiguration(
|
||||
"""-identifiernamestring class * {
|
||||
@org.chromium.build.annotations.IdentifierNameString *;
|
||||
}
|
||||
"""
|
||||
)
|
||||
|
||||
"The option prints out a warning" {
|
||||
customOutputStream.toString() shouldContain "Warning: The R8 option -identifiernamestring is currently not supported by ProGuard.\n" +
|
||||
"This option will have no effect on the optimized artifact."
|
||||
System.setOut(savedPrintStream)
|
||||
}
|
||||
}
|
||||
|
||||
"Given a configuration with -identifiernamestring with no class specification" - {
|
||||
"The parsing should throw an exception" {
|
||||
shouldThrow<ParseException> { parseConfiguration("-identifiernamestring") }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"Wildcard type tests" - {
|
||||
class TestConfig(
|
||||
val configOption: String,
|
||||
|
||||
172
base/src/test/kotlin/proguard/ConfigurationWriterTest.kt
Normal file
172
base/src/test/kotlin/proguard/ConfigurationWriterTest.kt
Normal file
@@ -0,0 +1,172 @@
|
||||
package proguard
|
||||
|
||||
import io.kotest.core.spec.style.FreeSpec
|
||||
import io.kotest.matchers.shouldBe
|
||||
import io.kotest.matchers.string.shouldContain
|
||||
import java.io.PrintWriter
|
||||
import java.io.StringWriter
|
||||
|
||||
/**
|
||||
* Test printing of the configuration (-printconfiguration option).
|
||||
*/
|
||||
class ConfigurationWriterTest : FreeSpec({
|
||||
val EOL = System.lineSeparator()
|
||||
fun printConfiguration(rules: String): String {
|
||||
val out = StringWriter()
|
||||
val configuration = Configuration()
|
||||
|
||||
ConfigurationParser(rules, "", null, System.getProperties()).use {
|
||||
it.parse(configuration)
|
||||
}
|
||||
|
||||
ConfigurationWriter(PrintWriter(out)).use {
|
||||
it.write(configuration)
|
||||
}
|
||||
|
||||
return out.toString().trim()
|
||||
}
|
||||
|
||||
"Keep rules tests" - {
|
||||
"Keep class constructor should be kept" {
|
||||
val rules = """
|
||||
-keep class * {
|
||||
<init>();
|
||||
}
|
||||
""".trimIndent()
|
||||
val out = printConfiguration(rules)
|
||||
out shouldBe rules
|
||||
}
|
||||
|
||||
"Keep class initializer should be kept" {
|
||||
val rules = """
|
||||
-keep class * {
|
||||
<clinit>();
|
||||
}
|
||||
""".trimIndent()
|
||||
val out = printConfiguration(rules)
|
||||
val expected = """
|
||||
-keep class * {
|
||||
void <clinit>();
|
||||
}
|
||||
""".trimIndent()
|
||||
out shouldBe expected
|
||||
}
|
||||
|
||||
"Keep class initializer should respect allowobfuscation flag" {
|
||||
val rules = """
|
||||
-keep,allowobfuscation class ** extends com.example.A {
|
||||
<clinit>();
|
||||
}
|
||||
""".trimIndent()
|
||||
val out = printConfiguration(rules)
|
||||
val expected = """
|
||||
-keep,allowobfuscation class ** extends com.example.A {
|
||||
void <clinit>();
|
||||
}
|
||||
""".trimIndent()
|
||||
out shouldBe expected
|
||||
}
|
||||
}
|
||||
|
||||
"Hash character handling tests" - {
|
||||
"Option parameters with hash characters should be quoted" {
|
||||
printConfiguration("-keystorepassword '#tester'") shouldBe "-keystorepassword '#tester'"
|
||||
}
|
||||
|
||||
"Comments should not be quoted" {
|
||||
printConfiguration("# comment$EOL-keep class **") shouldBe "# comment$EOL-keep class **"
|
||||
}
|
||||
|
||||
"Hash characters in comments should not be quoted" {
|
||||
printConfiguration("# #comment$EOL-keep class **") shouldBe "# #comment$EOL-keep class **"
|
||||
}
|
||||
}
|
||||
|
||||
"Given a -dontnote rule specifying a class name" - {
|
||||
val rules = "-dontnote com.example.MyClass"
|
||||
|
||||
"When the rule is parsed and printed out again" - {
|
||||
val out = printConfiguration(rules)
|
||||
|
||||
"Then the printed rule should be the same as the given rule" {
|
||||
out shouldBe rules
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"Given a -dontnote rule specifying a class name with wildcards" - {
|
||||
val rules = "-dontnote com.example.**"
|
||||
|
||||
"When the rule is parsed and printed out again" - {
|
||||
val out = printConfiguration(rules)
|
||||
|
||||
"Then the printed rule should be the same as the given rule" {
|
||||
out shouldBe rules
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"Given a -addconfigurationdebugging rule" - {
|
||||
val rules = "-addconfigurationdebugging"
|
||||
|
||||
"When the rules are parsed and printed out again" - {
|
||||
val out = printConfiguration(rules)
|
||||
|
||||
"Then the rules should be present in the output" {
|
||||
out shouldContain rules
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"Given an -optimizeaggressively rule" - {
|
||||
val rules = "-optimizeaggressively"
|
||||
|
||||
"When the rule is parsed and printed out again" - {
|
||||
val out = printConfiguration(rules)
|
||||
|
||||
"Then the rule should be present in the output" {
|
||||
out shouldBe rules
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"Given a -alwaysinline rule" - {
|
||||
val rules = "-alwaysinline class ** {*;}"
|
||||
|
||||
"When the rule is parsed and printed out again" - {
|
||||
val out = printConfiguration(rules)
|
||||
|
||||
"Then the rule should be not be present in the output" {
|
||||
out shouldBe ""
|
||||
}
|
||||
}
|
||||
|
||||
"When the rule does not exist it shouldn't be printed out" - {
|
||||
val out = printConfiguration("")
|
||||
|
||||
"Then the rule should not be present in the output" {
|
||||
out shouldBe ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"Given a -identifiernamestring rule" - {
|
||||
val rules = "-identifiernamestring class ** {*;}"
|
||||
|
||||
"When the rule is parsed and printed out again" - {
|
||||
val out = printConfiguration(rules)
|
||||
|
||||
"Then the rule should be not be present in the output" {
|
||||
out shouldBe ""
|
||||
}
|
||||
}
|
||||
|
||||
"When the rule does not exist it shouldn't be printed out" - {
|
||||
val out = printConfiguration("")
|
||||
|
||||
"Then the rule should not be present in the output" {
|
||||
out shouldBe ""
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -1,4 +1,4 @@
|
||||
Welcome to the manual for **ProGuard** version 7.3 ([what's new?](releasenotes.md)).
|
||||
Welcome to the manual for **ProGuard** version 7.4 ([what's new?](releasenotes.md)).
|
||||
|
||||
ProGuard is an open-sourced Java class file shrinker, optimizer, obfuscator, and
|
||||
preverifier. As a result, ProGuard processed applications and libraries are smaller and faster.
|
||||
|
||||
@@ -1,3 +1,13 @@
|
||||
## Version 7.4.1
|
||||
|
||||
### Bugfixes
|
||||
|
||||
- Fix inadvertent closing of System.out when printing configuration. (#365)
|
||||
|
||||
### Added
|
||||
|
||||
- Support for parsing of `<clinit>` methods without specifying the return type in class specifications.
|
||||
|
||||
## Version 7.4
|
||||
|
||||
### Java support
|
||||
|
||||
@@ -7,7 +7,7 @@ buildscript {
|
||||
google()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.guardsquare:proguard-gradle:7.4.0'
|
||||
classpath 'com.guardsquare:proguard-gradle:7.4.1'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ buildscript {
|
||||
google()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.guardsquare:proguard-gradle:7.4.0'
|
||||
classpath 'com.guardsquare:proguard-gradle:7.4.1'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ buildscript {
|
||||
google()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.guardsquare:proguard-gradle:7.4.0'
|
||||
classpath 'com.guardsquare:proguard-gradle:7.4.1'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ class GradlePluginIntegrationTest : FreeSpec({
|
||||
}
|
||||
}
|
||||
|
||||
"gradle plugin can be configured via #configOption" - {
|
||||
"gradle plugin can be configured via #configOption" {
|
||||
include(testConfigOption("proguard"))
|
||||
include(testConfigOption("proguardWithConfigFile"))
|
||||
include(testConfigOption("proguardWithGeneratedConfigFile"))
|
||||
|
||||
@@ -32,7 +32,7 @@ import testutils.TestPluginClasspath
|
||||
|
||||
class ProguardCacheRelocateabilityIntegrationTest : FreeSpec({
|
||||
|
||||
"proguard task can be relocated" - {
|
||||
"proguard task can be relocated" {
|
||||
val cacheDir = tempdir()
|
||||
val fixture = File(ProguardCacheRelocateabilityIntegrationTest::class.java.classLoader.getResource("spring-boot").path)
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
proguardVersion = 7.4.0
|
||||
proguardVersion = 7.4.1
|
||||
|
||||
# The version of ProGuardCORE that sub-projects are built with
|
||||
proguardCoreVersion = 9.1.0
|
||||
|
||||
Reference in New Issue
Block a user