Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[#1745] improvement(api): Add errorprone plugin to format exception message #1746

Merged
merged 2 commits into from
Feb 16, 2024

Conversation

coolderli
Copy link
Contributor

What changes were proposed in this pull request?

close #1745
Format exception message by String.format

Why are the changes needed?

Format the message of exception for better coding

Fix: #1745

Does this PR introduce any user-facing change?

  • no

How was this patch tested?

  • no need, just compile passed is OK.

@coolderli coolderli force-pushed the add-exception-format branch from 8f31b5a to 3cc2761 Compare January 28, 2024 04:58
@coolderli coolderli closed this Jan 28, 2024
@coolderli coolderli reopened this Jan 28, 2024
@yuqi1129
Copy link
Contributor

@coolderli , Thanks for your contribution, can you provide the effection this PRs introduces?

@coolderli
Copy link
Contributor Author

coolderli commented Jan 28, 2024

@coolderli , Thanks for your contribution, can you provide the effection this PRs introduces?

@yuqi1129 When concating the message of exception, we have to use + to concat the constants and variables, such as:

      catch (EntityAlreadyExistsException e1) {
      throw new CatalogAlreadyExistsException("Catalog " + ident + " already exists");
    }

In this PR, we can format the message like this:

catch (EntityAlreadyExistsException e1) {
      throw new CatalogAlreadyExistsException("Catalog %s already exists", ident);
    }

We have already done this on RESTException

But the annotation @FormatMethod and @FormatString will not work unless we apply an error-prone plugin to the project.

@coolderli
Copy link
Contributor Author

@yuqi1129 what do you think about this change? It's just a code refactor.

@yuqi1129
Copy link
Contributor

@yuqi1129 what do you think about this change? It's just a code refactor.

Is this https://github.com/tbroyer/gradle-errorprone-plugin error-prone plugin? I'm afraid it won't work well with JDK8 and JDK 17, though I agree with this optimization. Have you been able to test the plugin with JDK8, JDK11 and JDK17?

@coolderli
Copy link
Contributor Author

coolderli commented Jan 29, 2024

@yuqi1129 what do you think about this change? It's just a code refactor.

Is this https://github.com/tbroyer/gradle-errorprone-plugin error-prone plugin? I'm afraid it won't work well with JDK8 and JDK 17, though I agree with this optimization. Have you been able to test the plugin with JDK8, JDK11 and JDK17?

@yuqi1129 Yes. I already tried to test this plugin but failed to make it work. I need to try again when I have time. Do we really need this plugin? What about I remove the annotation @FormatMethod and @FormatString and just receive the code refactor?

@yuqi1129
Copy link
Contributor

@yuqi1129 what do you think about this change? It's just a code refactor.

Is this tbroyer/gradle-errorprone-plugin error-prone plugin? I'm afraid it won't work well with JDK8 and JDK 17, though I agree with this optimization. Have you been able to test the plugin with JDK8, JDK11 and JDK17?

@yuqi1129 Yes. I already tried to test this plugin but failed to make it work. I need to try again when I have time. Do we really need this plugin? What about I remove the annotation @FormatMethod and @FormatString and just receive the code refactor?

I believe the optimization is effective and meaningful, but it should work with the plugin. Can you spare some time to test the plugins?

@coolderli
Copy link
Contributor Author

@yuqi1129 what do you think about this change? It's just a code refactor.

Is this tbroyer/gradle-errorprone-plugin error-prone plugin? I'm afraid it won't work well with JDK8 and JDK 17, though I agree with this optimization. Have you been able to test the plugin with JDK8, JDK11 and JDK17?

@yuqi1129 Yes. I already tried to test this plugin but failed to make it work. I need to try again when I have time. Do we really need this plugin? What about I remove the annotation @FormatMethod and @FormatString and just receive the code refactor?

I believe the optimization is effective and meaningful, but it should work with the plugin. Can you spare some time to test the plugins?

Ok, I got it. I will try my best.

@coolderli coolderli marked this pull request as draft January 29, 2024 10:27
@jerryshao
Copy link
Contributor

We definitely need this, this is a good improvement. @coolderli can you please continue your work when you have time.

@coolderli coolderli force-pushed the add-exception-format branch from 86bed67 to 2a8ae96 Compare February 6, 2024 08:54
@coolderli coolderli changed the title [#1745] improvement(api): Format exception message by String.format [#1745] improvement(api): Add errorprone plugin to format exception message Feb 6, 2024
build.gradle.kts Outdated
options.errorprone.isEnabled.set(true)
options.errorprone.disableAllChecks.set(true)
options.errorprone.enable(
"AnnotateFormatMethod"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only enable @FormatMethod, because we enable -Werror, Or there are a lot of warnings that are treated as an error.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good improvement!I had the same problem last night.

@coolderli coolderli force-pushed the add-exception-format branch from 67877e7 to 36b8c68 Compare February 7, 2024 08:26
@@ -15,21 +15,22 @@
/** Exception converter to gravitino exception for MySQL. */
public class MysqlExceptionConverter extends JdbcExceptionConverter {

@SuppressWarnings("FormatStringAnnotation")
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The string that is annotationed by @FormatString must be a final string or a compile time constant value. a variable is not allowed, such as

new NoSuchEntityException(se.getMessage)

So I just ignore it by @SuppressWarnings("FormatStringAnnotation")

@@ -287,13 +285,13 @@ public <E extends Entity & HasIdentifier> E get(
() -> {
byte[] key = entityKeyEncoder.encode(ident, entityType, true);
if (key == null) {
throw new NoSuchEntityException(ident.toString());
throw new NoSuchEntityException("No such entity:%s", ident.toString());
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another fix is like this. We use the format string.

@@ -34,6 +35,7 @@
* <p>Referred from spark/v3.4/spark/src/test/java/org/apache/iceberg/spark/SparkTestBase.java
*/

@SuppressWarnings("FormatStringAnnotation")
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Too many changes, just ignore them.

public GravitinoRuntimeException(String message, Throwable cause) {
super(message, cause);
@FormatMethod
public GravitinoRuntimeException(Throwable cause, @FormatString String message, Object... args) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Throwable must be the first argument. Or it will throw an exception. I think it is conflict with the variable parameters in the overloaded function

@FormatMethod
  public GravitinoRuntimeException(@FormatString String message, Object... args) {
    super(String.format(message, args));
  }

@@ -115,6 +117,7 @@ private void stopSparkEnv() {
}
}

@FormatMethod
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If a method uses string.format(), it must be annotated by @FormatMethod, or there will be an error.

@coolderli
Copy link
Contributor Author

If there are some format problems, some errors will be thrown like below:

/home/mi/IdeaProjects/gravitino/core/src/test/java/com/datastrato/gravitino/TestEntityStore.java:95: 错误: [FormatStringAnnotation] Format strings must be either literals or variables. Other expressions are not valid.
              throw new NoSuchEntityException("Entity " + ident + " does not exist");
                    ^
  Invalid format string: "Entity " + ident + " does not exist"
    (see https://errorprone.info/bugpattern/FormatStringAnnotation)
/home/mi/IdeaProjects/gravitino/core/src/test/java/com/datastrato/gravitino/TestEntityStore.java:114: 错误: [FormatStringAnnotation] Format strings must be either literals or variables. Other expressions are not valid.
        throw new NoSuchEntityException("Entity " + ident + " does not exist");

/home/mi/IdeaProjects/gravitino/catalogs/catalog-hive/src/main/java/com/datastrato/gravitino/catalog/hive/HiveTableOperations.java:93: 错误: [FormatStringAnnotation] extra format arguments: used 1, provided 2
      throw new NoSuchTableException(
            ^
    (see https://errorprone.info/bugpattern/FormatStringAnnotation)
/home/mi/IdeaProjects/gravitino/catalogs/catalog-hive/src/main/java/com/datastrato/gravitino/catalog/hive/HiveTableOperations.java:97: 错误: [FormatStringAnnotation] extra format arguments: used 1, provided 2
      throw new NoSuchPartitionException(



@coolderli coolderli marked this pull request as ready for review February 7, 2024 08:56
@coolderli
Copy link
Contributor Author

@jerryshao @yuqi1129 Finally, I finished this. Please take a review when you have time. Thanks.

@yuqi1129
Copy link
Contributor

yuqi1129 commented Feb 7, 2024

@jerryshao @yuqi1129 Finally, I finished this. Please take a review when you have time. Thanks.

Thank you for your hard work, we will review it soon.

@justinmclean
Copy link
Member

If it helps (and I've not gone through them all) these checks that currently pass:

      "AlwaysThrows",
        "AnnotateFormatMethod",
        "ArrayEquals",
        "ArrayToString",
        "ArraysAsListPrimitiveArray",
        "ArrayFillIncompatibleType",
        "BoxedPrimitiveEquality",
        "ChainingConstructorIgnoresParameter",
        "CheckNotNullMultipleTimes",
        "CheckReturnValue",
        "CollectionIncompatibleType",
        "CollectionToArraySafeParameter",
        "ComparingThisWithNull",
        "ComparisonOutOfRange",
        "CompatibleWithAnnotationMisuse",
        "CompileTimeConstant",
        "ConditionalExpressionNumericPromotion",
        "ConstantOverflow",
        "DangerousLiteralNull",
        "DeadException",
        "DeadThread",
        "DoNotCall",
        "DoNotMock",
        "DuplicateMapKeys",
        "EqualsNaN",
        "EqualsNull",
        "EqualsReference",
        "EqualsWrongThing",
        "ForOverride",
        "FormatString",
        "FormatStringAnnotation",
        "GetClassOnAnnotation",
        "GetClassOnClass",
        "HashtableContains",
        "IdentityBinaryExpression",
        "IdentityHashMapBoxing",
        "Immutable",
        "Incomparable",
        "IncompatibleArgumentType",
        "IndexOfChar",
        "InfiniteRecursion",
        "InvalidJavaTimeConstant",
        "InvalidPatternSyntax",
        "IsInstanceIncompatibleType",
        "JUnit4ClassAnnotationNonStatic",
        "JUnit4SetUpNotRun",
        "JUnit4TearDownNotRun",
        "JUnit4TestNotRun",
        "JUnitAssertSameCheck",
        "LockOnBoxedPrimitive",
        "LoopConditionChecker",
        "LossyPrimitiveCompare",
        "MathRoundIntLong",
        "MissingSuperCall",
        "ModifyingCollectionWithItself",
        "NonCanonicalStaticImport",
        "NonFinalCompileTimeConstant",
        "NonRuntimeAnnotation",
        "NullTernary",
        "OptionalEquality",
        "PackageInfo",
        "ParametersButNotParameterized",
        "RandomCast",
        "RandomModInteger",
        "SelfAssignment",
        "SelfComparison",
        "SelfEquals",
        "SizeGreaterThanOrEqualsZero",
        "StreamToString",
        "StringBuilderInitWithChar",
        "SubstringOfZero",
        "ThrowNull",
        "TruthSelfEquals",
        "TryFailThrowable",
        "TypeParameterQualifier",
        "UnnecessaryCheckNotNull",
        "UnnecessaryTypeArgument",
        "UnsafeWildcard",
        "UnusedAnonymousClass",
        "UnusedCollectionModifiedInPlace",
        "VarTypeName",
        "XorPower"

So you could enable all of these

And these ones (and probably more) currently fail:

        "ArgumentSelectionDefectChecker",
        "BadImport",
        "ComparableType",
        "DefaultCharset",
        "DoubleBraceInitialization",
        "EqualsGetClass",
        "EmptyBlockTag",
        "InconsistentCapitalization",
        "JavaUtilDate",
        "MissingOverride",
        "MissingSummary",
        "NonOverridingEquals",
	"ReturnValueIgnored",
        "SameNameButDifferent",
        "StringSplitter",
	"ThrowIfUncheckedKnownChecked",
        "UnnecessaryParentheses",
        "UnusedVariable"

Which we can raise as separate issues.

@coolderli
Copy link
Contributor Author

If it helps (and I've not gone through them all) these checks that currently pass:

      "AlwaysThrows",
        "AnnotateFormatMethod",
        "ArrayEquals",
        "ArrayToString",
        "ArraysAsListPrimitiveArray",
        "ArrayFillIncompatibleType",
        "BoxedPrimitiveEquality",
        "ChainingConstructorIgnoresParameter",
        "CheckNotNullMultipleTimes",
        "CheckReturnValue",
        "CollectionIncompatibleType",
        "CollectionToArraySafeParameter",
        "ComparingThisWithNull",
        "ComparisonOutOfRange",
        "CompatibleWithAnnotationMisuse",
        "CompileTimeConstant",
        "ConditionalExpressionNumericPromotion",
        "ConstantOverflow",
        "DangerousLiteralNull",
        "DeadException",
        "DeadThread",
        "DoNotCall",
        "DoNotMock",
        "DuplicateMapKeys",
        "EqualsNaN",
        "EqualsNull",
        "EqualsReference",
        "EqualsWrongThing",
        "ForOverride",
        "FormatString",
        "FormatStringAnnotation",
        "GetClassOnAnnotation",
        "GetClassOnClass",
        "HashtableContains",
        "IdentityBinaryExpression",
        "IdentityHashMapBoxing",
        "Immutable",
        "Incomparable",
        "IncompatibleArgumentType",
        "IndexOfChar",
        "InfiniteRecursion",
        "InvalidJavaTimeConstant",
        "InvalidPatternSyntax",
        "IsInstanceIncompatibleType",
        "JUnit4ClassAnnotationNonStatic",
        "JUnit4SetUpNotRun",
        "JUnit4TearDownNotRun",
        "JUnit4TestNotRun",
        "JUnitAssertSameCheck",
        "LockOnBoxedPrimitive",
        "LoopConditionChecker",
        "LossyPrimitiveCompare",
        "MathRoundIntLong",
        "MissingSuperCall",
        "ModifyingCollectionWithItself",
        "NonCanonicalStaticImport",
        "NonFinalCompileTimeConstant",
        "NonRuntimeAnnotation",
        "NullTernary",
        "OptionalEquality",
        "PackageInfo",
        "ParametersButNotParameterized",
        "RandomCast",
        "RandomModInteger",
        "SelfAssignment",
        "SelfComparison",
        "SelfEquals",
        "SizeGreaterThanOrEqualsZero",
        "StreamToString",
        "StringBuilderInitWithChar",
        "SubstringOfZero",
        "ThrowNull",
        "TruthSelfEquals",
        "TryFailThrowable",
        "TypeParameterQualifier",
        "UnnecessaryCheckNotNull",
        "UnnecessaryTypeArgument",
        "UnsafeWildcard",
        "UnusedAnonymousClass",
        "UnusedCollectionModifiedInPlace",
        "VarTypeName",
        "XorPower"

So you could enable all of these

And these ones (and probably more) currently fail:

        "ArgumentSelectionDefectChecker",
        "BadImport",
        "ComparableType",
        "DefaultCharset",
        "DoubleBraceInitialization",
        "EqualsGetClass",
        "EmptyBlockTag",
        "InconsistentCapitalization",
        "JavaUtilDate",
        "MissingOverride",
        "MissingSummary",
        "NonOverridingEquals",
	"ReturnValueIgnored",
        "SameNameButDifferent",
        "StringSplitter",
	"ThrowIfUncheckedKnownChecked",
        "UnnecessaryParentheses",
        "UnusedVariable"

Which we can raise as separate issues.

Thanks for your reply.Because we enabled -Weeror.If I enabled all check ,I have to fix all of them in this PR. I
am agree with your suggestion ,I think we can fix them in another issue. What dou you think ?

@justinmclean
Copy link
Member

Yes, we can fix these in another issue. I've already raised some issues for them.

Copy link
Member

@justinmclean justinmclean left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM - thanks for all your work on this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Improvement] Format exception message by String.format
5 participants