-
Notifications
You must be signed in to change notification settings - Fork 19
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
Improve cast warnings/errors logic #337
Changes from 1 commit
298df8a
c4588df
82740f7
d71ead6
0dec947
f5c5d22
c916493
bfa5794
93a6a1a
b04007c
9b116a7
b88949f
361f487
874e594
09904ba
9862649
b8f1549
deffd1d
4f476f2
f82dc77
efeeea2
c34285f
16d69a6
4cd7e9a
cb0cb64
d7429e4
8502489
72e074e
1cfd105
e92f0c6
0658def
7991a8b
4ffe0f1
fa1439e
a15d727
bfee453
20d62af
8e0f908
91b22c9
09cc33d
24105c4
c2bea34
1ec438e
a6fb6ce
724a95e
d241446
07eaacb
4229827
fc9ad98
d06ad1f
f4ffe07
ac60c2e
0115fbe
67ba76b
0b78587
1b8f4ab
2d969fc
1b20546
b94311d
98060e3
f4d4ec1
0831233
9147d86
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
Co-authored-by: Werner Dietl <wdietl@gmail.com>
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2474,7 +2474,7 @@ protected void checkTypecastSafety(TypeCastTree typeCastTree) { | |
// We cannot do a simple test of casting, as isSubtypeOf requires | ||
// the input types to be subtypes according to Java. | ||
if (!reported) { | ||
TypecastKind castResult = isTypeCastSafe(castType, exprType); | ||
TypeCastKind castResult = isTypeCastSafe(castType, exprType); | ||
|
||
if (castResult == TypecastKind.WARNING) { | ||
checker.reportWarning( | ||
|
@@ -2492,17 +2492,17 @@ protected void checkTypecastSafety(TypeCastTree typeCastTree) { | |
} | ||
} | ||
|
||
/** To represent all possible kinds of typecast */ | ||
protected enum TypecastKind { | ||
/** The cast is safe */ | ||
/** Represents all possible kinds of typecasts. */ | ||
protected enum TypeCastKind { | ||
/** The cast is safe. */ | ||
SAFE, | ||
/** The cast is illegal */ | ||
/** The cast is illegal. */ | ||
ERROR, | ||
/** Cannot statically verify the cast, report a warning */ | ||
/** Cannot statically verify the cast, report a warning. */ | ||
WARNING, | ||
/** It's not an upcast */ | ||
/** It is not an upcast. */ | ||
NOT_UPCAST, | ||
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 think having only three possible values would be better, instead of the two extra 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. Previously, I use To remove |
||
/** It's not a downcast */ | ||
/** It is not a downcast. */ | ||
NOT_DOWNCAST | ||
} | ||
|
||
|
@@ -2516,7 +2516,7 @@ protected enum TypecastKind { | |
* @param exprType annotated type of the casted expression | ||
* @return return NOT_UPCAST, WARNING or SAFE TypecastKind. | ||
*/ | ||
protected TypecastKind isUpcast(AnnotatedTypeMirror castType, AnnotatedTypeMirror exprType) { | ||
protected TypeCastKind isUpcast(AnnotatedTypeMirror castType, AnnotatedTypeMirror exprType) { | ||
QualifierHierarchy qualifierHierarchy = atypeFactory.getQualifierHierarchy(); | ||
AnnotationMirrorSet castAnnos; | ||
TypeKind castTypeKind = castType.getKind(); | ||
|
@@ -2538,13 +2538,13 @@ protected TypecastKind isUpcast(AnnotatedTypeMirror castType, AnnotatedTypeMirro | |
} | ||
|
||
if (!atypeFactory.getTypeHierarchy().isSubtype(newExprType, newCastType)) { | ||
return TypecastKind.WARNING; | ||
return TypeCastKind.WARNING; | ||
} | ||
if (newCastType.getKind() == TypeKind.ARRAY | ||
&& newExprType.getKind() != TypeKind.ARRAY) { | ||
// Always warn if the cast contains an array, but the expression | ||
// doesn't, as in "(Object[]) o" where o is of type Object | ||
return TypecastKind.WARNING; | ||
return TypeCastKind.WARNING; | ||
} else if (newCastType.getKind() == TypeKind.DECLARED | ||
&& newExprType.getKind() == TypeKind.DECLARED) { | ||
int castSize = ((AnnotatedDeclaredType) newCastType).getTypeArguments().size(); | ||
|
@@ -2554,7 +2554,7 @@ protected TypecastKind isUpcast(AnnotatedTypeMirror castType, AnnotatedTypeMirro | |
// Always warn if the cast and expression contain a different number of type | ||
// arguments, e.g. to catch a cast from "Object" to "List<@NonNull Object>". | ||
// TODO: the same number of arguments actually doesn't guarantee anything. | ||
return TypecastKind.WARNING; | ||
return TypeCastKind.WARNING; | ||
} | ||
} else if (castTypeKind == TypeKind.TYPEVAR && exprType.getKind() == TypeKind.TYPEVAR) { | ||
// If both the cast type and the casted expression are type variables, then check | ||
|
@@ -2571,7 +2571,7 @@ protected TypecastKind isUpcast(AnnotatedTypeMirror castType, AnnotatedTypeMirro | |
&& qualifierHierarchy.isSubtype( | ||
exprType.getEffectiveAnnotations(), | ||
castType.getEffectiveAnnotations()); | ||
return result ? TypecastKind.SAFE : TypecastKind.WARNING; | ||
return result ? TypeCastKind.SAFE : TypeCastKind.WARNING; | ||
} | ||
if (castTypeKind == TypeKind.TYPEVAR) { | ||
// If the cast type is a type var, but the expression is not, then check that the | ||
|
@@ -2607,9 +2607,9 @@ protected TypecastKind isUpcast(AnnotatedTypeMirror castType, AnnotatedTypeMirro | |
// return SAFE only it satisfies the below condition | ||
if (qualifierHierarchy.isSubtype(exprLower, castLower) | ||
&& qualifierHierarchy.isSubtype(exprUpper, castUpper)) { | ||
return TypecastKind.SAFE; | ||
return TypeCastKind.SAFE; | ||
} | ||
return TypecastKind.WARNING; | ||
return TypeCastKind.WARNING; | ||
} | ||
} | ||
|
||
|
@@ -2618,12 +2618,12 @@ protected TypecastKind isUpcast(AnnotatedTypeMirror castType, AnnotatedTypeMirro | |
qualifierHierarchy.isSubtype(exprTypeWidened.getEffectiveAnnotations(), castAnnos); | ||
|
||
if (result) { | ||
return TypecastKind.SAFE; | ||
return TypeCastKind.SAFE; | ||
} else if (checkCastElementType) { | ||
// when the flag is enabled, and it is not an upcast, return a warning | ||
return TypecastKind.WARNING; | ||
return TypeCastKind.WARNING; | ||
} else { | ||
return TypecastKind.NOT_UPCAST; | ||
return TypeCastKind.NOT_UPCAST; | ||
} | ||
} | ||
|
||
|
@@ -2635,14 +2635,14 @@ protected TypecastKind isUpcast(AnnotatedTypeMirror castType, AnnotatedTypeMirro | |
* @param exprType annotated type of the casted expression | ||
* @return Can return SAFE, NOT_DOWNCAST or WARNING. | ||
*/ | ||
protected TypecastKind isSafeDowncast( | ||
protected TypeCastKind isSafeDowncast( | ||
AnnotatedTypeMirror castType, AnnotatedTypeMirror exprType) { | ||
AnnotationMirrorSet castAnnos = castType.getEffectiveAnnotations(); | ||
AnnotationMirrorSet exprAnnos = exprType.getEffectiveAnnotations(); | ||
QualifierHierarchy qualifierHierarchy = atypeFactory.getQualifierHierarchy(); | ||
|
||
if (!qualifierHierarchy.isComparable(castAnnos, exprAnnos)) { // exists an incomparable cast | ||
return TypecastKind.NOT_DOWNCAST; | ||
return TypeCastKind.NOT_DOWNCAST; | ||
} | ||
|
||
// check if the downcast can be statically verified | ||
|
@@ -2656,14 +2656,14 @@ protected TypecastKind isSafeDowncast( | |
atypeFactory.getTypeDeclarationBounds(castDeclared.getUnderlyingType()); | ||
|
||
if (AnnotationUtils.areSame(castDeclared.getAnnotations(), bounds)) { | ||
AndrewShf marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return TypecastKind.SAFE; | ||
return TypeCastKind.SAFE; | ||
} | ||
} | ||
return TypecastKind.WARNING; | ||
return TypeCastKind.WARNING; | ||
} | ||
|
||
/** | ||
* If it's an incomparable cast in terms of qualifiers, return ERROR by default. Subchecker can | ||
* If it is an incomparable cast in terms of qualifiers, return ERROR by default. Subchecker can | ||
* override this method to allow certain incomparable casts. | ||
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. What is returned if it is not ERROR? 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. addressed |
||
* | ||
* @param castType annotated type of the cast | ||
|
@@ -2672,26 +2672,26 @@ protected TypecastKind isSafeDowncast( | |
*/ | ||
protected TypecastKind isSafeIncomparableCast( | ||
AnnotatedTypeMirror castType, AnnotatedTypeMirror exprType) { | ||
return TypecastKind.ERROR; | ||
return TypeCastKind.ERROR; | ||
} | ||
|
||
/** | ||
* This method returns TypecastKind.SAFE when the typecast is an upcast or a statically | ||
* This method returns TypeCastKind.SAFE when the typecast is an upcast or a statically | ||
* verifiable downcast. Returns TypecastKind.WARNING and ERROR for those downcasts which cannot | ||
* be statically verified or some incomparable casts. | ||
* | ||
* @param castType annotated type of the cast | ||
* @param exprType annotated type of the casted expression | ||
* @return TypecastKind.SAFE if the typecast is safe, error or warning otherwise | ||
*/ | ||
protected TypecastKind isTypeCastSafe( | ||
protected TypeCastKind isTypeCastSafe( | ||
AnnotatedTypeMirror castType, AnnotatedTypeMirror exprType) { | ||
TypecastKind castResult = isUpcast(castType, exprType); | ||
TypeCastKind castResult = isUpcast(castType, exprType); | ||
|
||
// not upcast, do downcast and incomparable cast check | ||
if (castResult == TypecastKind.NOT_UPCAST) { | ||
if (castResult == TypeCastKind.NOT_UPCAST) { | ||
castResult = isSafeDowncast(castType, exprType); | ||
if (castResult == TypecastKind.NOT_DOWNCAST) { // fall into incomparable cast | ||
if (castResult == TypeCastKind.NOT_DOWNCAST) { // fall into incomparable cast | ||
return isSafeIncomparableCast(castType, exprType); | ||
} | ||
} | ||
|
@@ -2708,7 +2708,7 @@ protected TypecastKind isTypeCastSafe( | |
*/ | ||
private boolean isInvariantTypeCastSafe( | ||
AnnotatedTypeMirror castType, AnnotatedTypeMirror exprType, AnnotationMirror top) { | ||
if (isTypeCastSafe(castType, exprType) != TypecastKind.SAFE) { | ||
if (isTypeCastSafe(castType, exprType) != TypeCastKind.SAFE) { | ||
return false; | ||
} | ||
AnnotationMirror castTypeAnno = castType.getEffectiveAnnotationInHierarchy(top); | ||
|
@@ -2759,7 +2759,7 @@ public Void visitInstanceOf(InstanceOfTree tree, Void p) { | |
if (variableTree.getModifiers() != null) { | ||
AnnotatedTypeMirror variableType = atypeFactory.getAnnotatedType(variableTree); | ||
AnnotatedTypeMirror expType = atypeFactory.getAnnotatedType(tree.getExpression()); | ||
if (isTypeCastSafe(variableType, expType) != TypecastKind.SAFE) { | ||
if (isTypeCastSafe(variableType, expType) != TypeCastKind.SAFE) { | ||
checker.reportWarning(tree, "instanceof.pattern.unsafe", expType, variableTree); | ||
} | ||
} | ||
|
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.
isTypeCastSafe
previously returned a boolean, so theis
beginning makes sense. It now returns an enum. Would a different name be better to describe the wider task?computeTypeCastKind
? AlthoughKind
isn't particularly specific either... more on that with the enum.