Perform additional validation & fail earlier for incorrect arguments#87
Perform additional validation & fail earlier for incorrect arguments#87Marcono1234 wants to merge 6 commits intopalantir:developfrom
Conversation
MethodSpec and ParameterSpec already had this.
|
Thanks for your interest in palantir/javapoet, @Marcono1234! Before we can accept your pull request, you need to sign our contributor license agreement - just visit https://cla.palantir.com/ and follow the instructions. Once you sign, I'll automatically update this pull request. |
Generate changelog in
|
| checkState(enclosingClassName == null || enclosingClassName.packageName.equals(packageName), | ||
| "enclosing class is in wrong package"); |
There was a problem hiding this comment.
I think this is impossible with the public API currently, but I added this check nonetheless to be safe.
| protected final List<AnnotationSpec> concatAnnotations(List<AnnotationSpec> annotations) { | ||
| final List<AnnotationSpec> concatAnnotations(List<AnnotationSpec> annotations) { |
There was a problem hiding this comment.
Changed this because if I understand it correctly TypeName cannot be subclassed by users, so it makes no sense that they see this method if they cannot use it anyway.
| static ArrayTypeName get(ArrayType mirror, Map<TypeParameterElement, TypeVariableName> typeVariables) { | ||
| checkNotNull(mirror, "mirror == null"); |
There was a problem hiding this comment.
For all these get(... mirror, Map typeVariables) methods in the ...TypeName classes I wasn't completely sure if typeVariables can be null either. So for now I did not add a null check.
| // Compact constructor. | ||
| // Canonical record constructor. |
There was a problem hiding this comment.
This just writes the canonical constructor, whether it is also "compact" depends on whether MethodSpec.compactConstructorBuilder() was used.
| throw new UnsupportedOperationException(kind + " can't have record constructor"); | ||
| } | ||
| checkState(this.kind == Kind.RECORD, "%s can't have record constructor", this.kind); | ||
| checkState(this.recordConstructor == null, "record constructor already set to %s", this.recordConstructor); |
There was a problem hiding this comment.
This "record constructor already set" is probably consistent with most other builder methods, which don't allow overwriting values:
TypeSpec.Builder#superclassMethodSpec.Builder#defaultValueFieldSpec.Builder#initializer
(but there are some exceptions)
| public Builder addEnumConstant(String name, TypeSpec typeSpec) { | ||
| checkNotNull(name, "name == null"); | ||
| checkNotNull(typeSpec, "typeSpec == null"); | ||
| checkState(kind == Kind.ENUM, "only enums can have enum constants"); |
There was a problem hiding this comment.
Side note: This "only enums can have enum constants" is currently also checked in build() (with message "%s is not enum" there)
| checkArgument(methodSpec.defaultValue() == null || kind == Kind.ANNOTATION, | ||
| "method with default value is only allowed for annotation type"); |
There was a problem hiding this comment.
Side note: This defaultValue() check already exists in build() as well
| a = ParameterSpec.builder(int.class, "i").addModifiers(Modifier.STATIC).build(); | ||
| b = ParameterSpec.builder(int.class, "i").addModifiers(Modifier.STATIC).build(); | ||
| a = ParameterSpec.builder(int.class, "i").addModifiers(Modifier.FINAL).build(); | ||
| b = ParameterSpec.builder(int.class, "i").addModifiers(Modifier.FINAL).build(); |
There was a problem hiding this comment.
This includes the fix from #85 (comment), where it was previously not delegating the call, and this addModifiers overload did not validate the modifiers.
|
Currently still waiting for an answer to my questions regarding the CLA, see #84 (comment). |
|
This PR has been automatically marked as stale because it has not been touched in the last 14 days. If you'd like to keep it open, please leave a comment or add the 'long-lived' label, otherwise it'll be closed in 7 days. |
|
Have created #342 now to track this feature request. |
Resolves #342
Before this PR
nullThis would probably often have lead to delayed
NullPointerExceptions, or might have even caused different behavior in casenullhad internally a special meaning.Sometimes
IllegalArgumentExceptionwas thrown fornull; in two casesUnsupportedOperationExceptionwas thrown instead ofIllegalStateException.build(), and not already when calling builder methodsNote: I only changed a few cases; maybe would be worth to investigate this more in depth in the future. But this applies mainly to immutable state of a builder, e.g. a
TypeSpec.Builderforclasswill keep that kind and it cannot be changed toenum. For other validation is probably fine and better to do this inbuild().After this PR
NullPointerExceptionis thrown for unexpectednullIllegalStateExceptionis thrown when methods are called on wrong type, e.g. adding record constructor to regular classaddModifier(Iterable)overloads, see Fix incompletetoBuilderimplementations and add tests #85 (comment)Possible downsides?
I hope these changes do not accidentally disallow arguments which should be allowed.