-
Notifications
You must be signed in to change notification settings - Fork 3.1k
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
Enable Error Prone check: AnnotateFormatMethod #14933
Closed
ksobolew
wants to merge
9
commits into
trinodb:master
from
ksobolew:kudi/error-prone-annotate-format-method
Closed
Changes from 1 commit
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
c47502a
Fix log messages which are not format strings
ksobolew 0a47b89
Call semanticException method as a format method in SetColumnTypeTask
ksobolew ea4c436
Annotate semanticException factories as format methods
ksobolew 6479924
Make some conditional uses of NodeRepresentation#appendDetails explicit
ksobolew 2764f59
Annotate NodeRepresentation#appendDetails as a format method
ksobolew d2036b3
Annotate Failures#checkCondition as a format method
ksobolew 3a09752
Annotate format methods in trino-parquet
ksobolew d1f0b9b
Annotate all remaining cases of format methods
ksobolew 5b04fba
Enable Error Prone check: AnnotateFormatMethod
ksobolew File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,6 +22,8 @@ | |
import com.google.common.collect.LinkedHashMultimap; | ||
import com.google.common.collect.Multimap; | ||
import com.google.common.collect.Streams; | ||
import com.google.errorprone.annotations.FormatMethod; | ||
import com.google.errorprone.annotations.FormatString; | ||
import io.trino.Session; | ||
import io.trino.execution.warnings.WarningCollector; | ||
import io.trino.metadata.OperatorNotFoundException; | ||
|
@@ -758,7 +760,7 @@ protected Type visitDereferenceExpression(DereferenceExpression node, StackableA | |
for (RowType.Field rowField : rowType.getFields()) { | ||
if (fieldName.equalsIgnoreCase(rowField.getName().orElse(null))) { | ||
if (foundFieldName) { | ||
throw semanticException(AMBIGUOUS_NAME, field, "Ambiguous row field reference: " + fieldName); | ||
throw semanticException(AMBIGUOUS_NAME, field, "Ambiguous row field reference: %s", fieldName); | ||
} | ||
foundFieldName = true; | ||
rowFieldType = rowField.getType(); | ||
|
@@ -1243,7 +1245,7 @@ protected Type visitFunctionCall(FunctionCall node, StackableAstVisitorContext<C | |
Expression expression = arguments.get(0); | ||
Type expressionType = process(expression, context); | ||
if (!(expressionType instanceof VarcharType)) { | ||
throw semanticException(TYPE_MISMATCH, node, format("Expected expression of varchar, but '%s' has %s type", expression, expressionType.getDisplayName())); | ||
throw semanticException(TYPE_MISMATCH, node, "Expected expression of varchar, but '%s' has %s type", expression, expressionType.getDisplayName()); | ||
} | ||
} | ||
|
||
|
@@ -1273,7 +1275,7 @@ protected Type visitFunctionCall(FunctionCall node, StackableAstVisitorContext<C | |
// After optimization, array constructor is rewritten to a function call. | ||
// For historic reasons array constructor is allowed to have 254 arguments | ||
if (node.getArguments().size() > 254) { | ||
throw semanticException(TOO_MANY_ARGUMENTS, node, "Too many arguments for array constructor", function.getSignature().getName()); | ||
throw semanticException(TOO_MANY_ARGUMENTS, node, "Too many arguments for array constructor: %s", function.getSignature().getName()); | ||
} | ||
} | ||
else if (node.getArguments().size() > 127) { | ||
|
@@ -1491,7 +1493,7 @@ else if (frame.getType() == GROUPS) { | |
} | ||
} | ||
else { | ||
throw semanticException(NOT_SUPPORTED, frame, "Unsupported frame type: " + frame.getType()); | ||
throw semanticException(NOT_SUPPORTED, frame, "Unsupported frame type: %s", frame.getType()); | ||
} | ||
} | ||
} | ||
|
@@ -2421,7 +2423,7 @@ protected Type visitLambdaExpression(LambdaExpression node, StackableAstVisitorC | |
|
||
if (types.size() != lambdaArguments.size()) { | ||
throw semanticException(INVALID_PARAMETER_USAGE, node, | ||
format("Expected a lambda that takes %s argument(s) but got %s", types.size(), lambdaArguments.size())); | ||
"Expected a lambda that takes %s argument(s) but got %s", types.size(), lambdaArguments.size()); | ||
} | ||
|
||
ImmutableList.Builder<Field> fields = ImmutableList.builder(); | ||
|
@@ -2557,7 +2559,7 @@ public Type visitJsonValue(JsonValue node, StackableAstVisitorContext<Context> c | |
!isDateTimeType(returnedType) || | ||
returnedType.equals(INTERVAL_DAY_TIME) || | ||
returnedType.equals(INTERVAL_YEAR_MONTH)) { | ||
throw semanticException(TYPE_MISMATCH, node, "Invalid return type of function JSON_VALUE: " + node.getReturnedType().get()); | ||
throw semanticException(TYPE_MISMATCH, node, "Invalid return type of function JSON_VALUE: %s", node.getReturnedType().get()); | ||
} | ||
|
||
JsonPathAnalysis pathAnalysis = jsonPathAnalyses.get(NodeRef.of(node)); | ||
|
@@ -2803,7 +2805,7 @@ private ResolvedFunction getInputFunction(Type type, JsonFormat format, Node nod | |
if (isStringType(type)) { | ||
yield QualifiedName.of(VARBINARY_TO_JSON); | ||
} | ||
throw semanticException(TYPE_MISMATCH, node, format("Cannot read input of type %s as JSON using formatting %s", type, format)); | ||
throw semanticException(TYPE_MISMATCH, node, "Cannot read input of type %s as JSON using formatting %s", type, format); | ||
} | ||
case UTF8 -> QualifiedName.of(VARBINARY_UTF8_TO_JSON); | ||
case UTF16 -> QualifiedName.of(VARBINARY_UTF16_TO_JSON); | ||
|
@@ -2828,23 +2830,23 @@ private ResolvedFunction getOutputFunction(Type type, JsonFormat format, Node no | |
if (isStringType(type)) { | ||
yield QualifiedName.of(JSON_TO_VARBINARY); | ||
} | ||
throw semanticException(TYPE_MISMATCH, node, format("Cannot output JSON value as %s using formatting %s", type, format)); | ||
throw semanticException(TYPE_MISMATCH, node, "Cannot output JSON value as %s using formatting %s", type, format); | ||
} | ||
case UTF8 -> { | ||
if (!VARBINARY.equals(type)) { | ||
throw semanticException(TYPE_MISMATCH, node, format("Cannot output JSON value as %s using formatting %s", type, format)); | ||
throw semanticException(TYPE_MISMATCH, node, "Cannot output JSON value as %s using formatting %s", type, format); | ||
} | ||
yield QualifiedName.of(JSON_TO_VARBINARY_UTF8); | ||
} | ||
case UTF16 -> { | ||
if (!VARBINARY.equals(type)) { | ||
throw semanticException(TYPE_MISMATCH, node, format("Cannot output JSON value as %s using formatting %s", type, format)); | ||
throw semanticException(TYPE_MISMATCH, node, "Cannot output JSON value as %s using formatting %s", type, format); | ||
} | ||
yield QualifiedName.of(JSON_TO_VARBINARY_UTF16); | ||
} | ||
case UTF32 -> { | ||
if (!VARBINARY.equals(type)) { | ||
throw semanticException(TYPE_MISMATCH, node, format("Cannot output JSON value as %s using formatting %s", type, format)); | ||
throw semanticException(TYPE_MISMATCH, node, "Cannot output JSON value as %s using formatting %s", type, format); | ||
} | ||
yield QualifiedName.of(JSON_TO_VARBINARY_UTF32); | ||
} | ||
|
@@ -3137,7 +3139,8 @@ private void coerceType(StackableAstVisitorContext<Context> context, Expression | |
coerceType(expression, actualType, expectedType, message); | ||
} | ||
|
||
private Type coerceToSingleType(StackableAstVisitorContext<Context> context, Node node, String message, Expression first, Expression second) | ||
@FormatMethod | ||
ksobolew marked this conversation as resolved.
Show resolved
Hide resolved
|
||
private Type coerceToSingleType(StackableAstVisitorContext<Context> context, Node node, @FormatString String message, Expression first, Expression second) | ||
{ | ||
Type firstType = UNKNOWN; | ||
if (first != null) { | ||
|
@@ -3163,7 +3166,9 @@ private Type coerceToSingleType(StackableAstVisitorContext<Context> context, Nod | |
return superType; | ||
} | ||
|
||
throw semanticException(TYPE_MISMATCH, node, message, firstType, secondType); | ||
@SuppressWarnings("FormatStringAnnotation") // Error Prone wants the types of format arguments to be the same as where @FormatString is declared, but we need them to be different | ||
TrinoException exception = semanticException(TYPE_MISMATCH, node, message, firstType, secondType); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. new TrinoException? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't know, I think it's valid, just hits some limitations of Java type system (or Error Prone's interpretation of it)
ksobolew marked this conversation as resolved.
Show resolved
Hide resolved
|
||
throw exception; | ||
} | ||
|
||
private Type coerceToSingleType(StackableAstVisitorContext<Context> context, String description, List<Expression> expressions) | ||
|
@@ -3184,12 +3189,12 @@ private Type coerceToSingleType(StackableAstVisitorContext<Context> context, Str | |
for (Type type : types) { | ||
Optional<Type> newSuperType = typeCoercion.getCommonSuperType(superType, type); | ||
if (newSuperType.isEmpty()) { | ||
throw semanticException(TYPE_MISMATCH, Iterables.get(typeExpressions.get(type), 0).getNode(), format( | ||
throw semanticException(TYPE_MISMATCH, Iterables.get(typeExpressions.get(type), 0).getNode(), | ||
"%s must be the same type or coercible to a common type. Cannot find common type between %s and %s, all types (without duplicates): %s", | ||
description, | ||
superType, | ||
type, | ||
typeExpressions.keySet())); | ||
typeExpressions.keySet()); | ||
} | ||
superType = newSuperType.get(); | ||
} | ||
|
@@ -3200,12 +3205,12 @@ private Type coerceToSingleType(StackableAstVisitorContext<Context> context, Str | |
|
||
if (!type.equals(superType)) { | ||
if (!typeCoercion.canCoerce(type, superType)) { | ||
throw semanticException(TYPE_MISMATCH, Iterables.get(coercionCandidates, 0).getNode(), format( | ||
throw semanticException(TYPE_MISMATCH, Iterables.get(coercionCandidates, 0).getNode(), | ||
"%s must be the same type or coercible to a common type. Cannot find common type between %s and %s, all types (without duplicates): %s", | ||
description, | ||
superType, | ||
type, | ||
typeExpressions.keySet())); | ||
typeExpressions.keySet()); | ||
} | ||
addOrReplaceExpressionsCoercion(coercionCandidates, type, superType); | ||
} | ||
|
@@ -3559,7 +3564,7 @@ public static ExpressionAnalyzer createWithoutSubqueries( | |
session, | ||
TypeProvider.empty(), | ||
parameters, | ||
node -> semanticException(errorCode, node, message), | ||
node -> semanticException(errorCode, node, "%s", message), | ||
warningCollector, | ||
isDescribe); | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SET SESSION is invoked for a particular session property.
we don't need to provide the property name in the exception message, do we?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The other places that throw in this method do provide the property name, so I wanted to be consistent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
awesome. can this be a separate change, or even separate PR?
this change is orthognal to error-prone