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

Perform additional validation & fail earlier for incorrect arguments #87

Open
wants to merge 6 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ public static AnnotationSpec get(Annotation annotation) {
}

public static AnnotationSpec get(Annotation annotation, boolean includeDefaultValues) {
checkNotNull(annotation, "annotation == null");
Builder builder = builder(annotation.annotationType());
try {
Method[] methods = annotation.annotationType().getDeclaredMethods();
Expand Down Expand Up @@ -157,6 +158,7 @@ public static AnnotationSpec get(Annotation annotation, boolean includeDefaultVa
}

public static AnnotationSpec get(AnnotationMirror annotation) {
checkNotNull(annotation, "annotation == null");
TypeElement element = (TypeElement) annotation.getAnnotationType().asElement();
AnnotationSpec.Builder builder = AnnotationSpec.builder(ClassName.get(element));
Visitor visitor = new Visitor(builder);
Expand Down Expand Up @@ -230,6 +232,8 @@ public Builder addMember(String name, String format, Object... args) {
}

public Builder addMember(String name, CodeBlock codeBlock) {
checkNotNull(name, "name == null");
checkNotNull(codeBlock, "codeBlock == null");
List<CodeBlock> values = members.computeIfAbsent(name, _k -> new ArrayList<>());
values.add(codeBlock);
return this;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ private ArrayTypeName(TypeName componentType) {

private ArrayTypeName(TypeName componentType, List<AnnotationSpec> annotations) {
super(annotations);
this.componentType = checkNotNull(componentType, "rawType == null");
this.componentType = checkNotNull(componentType, "componentType == null");
}

public TypeName componentType() {
Expand Down Expand Up @@ -100,6 +100,7 @@ public static ArrayTypeName get(ArrayType mirror) {
}

static ArrayTypeName get(ArrayType mirror, Map<TypeParameterElement, TypeVariableName> typeVariables) {
checkNotNull(mirror, "mirror == null");
Comment on lines 102 to +103
Copy link
Contributor Author

Choose a reason for hiding this comment

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

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.

return new ArrayTypeName(get(mirror.getComponentType(), typeVariables));
}

Expand All @@ -109,6 +110,6 @@ public static ArrayTypeName get(GenericArrayType type) {
}

static ArrayTypeName get(GenericArrayType type, Map<Type, TypeVariableName> map) {
return ArrayTypeName.of(get(type.getGenericComponentType(), map));
return of(get(type.getGenericComponentType(), map));
}
}
11 changes: 7 additions & 4 deletions javapoet/src/main/java/com/palantir/javapoet/ClassName.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@

import static com.palantir.javapoet.Util.checkArgument;
import static com.palantir.javapoet.Util.checkNotNull;
import static com.palantir.javapoet.Util.checkState;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import javax.lang.model.element.Element;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
Expand Down Expand Up @@ -68,9 +68,11 @@ private ClassName(String packageName, ClassName enclosingClassName, String simpl
private ClassName(
String packageName, ClassName enclosingClassName, String simpleName, List<AnnotationSpec> annotations) {
super(annotations);
this.packageName = Objects.requireNonNull(packageName, "packageName == null");
this.packageName = checkNotNull(packageName, "packageName == null");
checkState(enclosingClassName == null || enclosingClassName.packageName.equals(packageName),
"enclosing class is in wrong package");
Comment on lines +72 to +73
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think this is impossible with the public API currently, but I added this check nonetheless to be safe.

this.enclosingClassName = enclosingClassName;
this.simpleName = simpleName;
this.simpleName = checkNotNull(simpleName, "simpleName == null");
this.canonicalName = enclosingClassName != null
? (enclosingClassName.canonicalName + '.' + simpleName)
: (packageName.isEmpty() ? simpleName : packageName + '.' + simpleName);
Expand Down Expand Up @@ -168,7 +170,7 @@ public String simpleName() {
/**
* Returns the full class name of this class.
* Like {@code "java.util.Map.Entry"} for {@link Map.Entry}.
* */
*/
public String canonicalName() {
return canonicalName;
}
Expand Down Expand Up @@ -250,6 +252,7 @@ public ClassName defaultAction(Element _enclosingElement, Void _p) {
* instances without such restrictions.
*/
public static ClassName bestGuess(String classNameString) {
checkNotNull(classNameString, "classNameString == null");
// Add the package name, like "java.util.concurrent", or "" for no package.
int p = 0;
while (p < classNameString.length() && Character.isLowerCase(classNameString.codePointAt(p))) {
Expand Down
16 changes: 16 additions & 0 deletions javapoet/src/main/java/com/palantir/javapoet/CodeBlock.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package com.palantir.javapoet;

import static com.palantir.javapoet.Util.checkArgument;
import static com.palantir.javapoet.Util.checkNotNull;

import java.io.IOException;
import java.io.UncheckedIOException;
Expand Down Expand Up @@ -129,6 +130,8 @@ public static CodeBlock of(String format, Object... args) {
* would produce {@code String s, Object o, int i}.
*/
public static CodeBlock join(Iterable<CodeBlock> codeBlocks, String separator) {
checkNotNull(codeBlocks, "codeBlocks == null");
checkNotNull(separator, "separator == null");
return StreamSupport.stream(codeBlocks.spliterator(), false).collect(joining(separator));
}

Expand All @@ -138,6 +141,7 @@ public static CodeBlock join(Iterable<CodeBlock> codeBlocks, String separator) {
* {@code int i} using {@code ", "} would produce {@code String s, Object o, int i}.
*/
public static Collector<CodeBlock, ?, CodeBlock> joining(String separator) {
checkNotNull(separator, "separator == null");
return Collector.of(
() -> new CodeBlockJoiner(separator, builder()),
CodeBlockJoiner::add,
Expand All @@ -151,6 +155,9 @@ public static CodeBlock join(Iterable<CodeBlock> codeBlocks, String separator) {
* {@code int i} using {@code ", "} would produce {@code String s, Object o, int i}.
*/
public static Collector<CodeBlock, ?, CodeBlock> joining(String separator, String prefix, String suffix) {
checkNotNull(separator, "separator == null");
checkNotNull(prefix, "prefix == null");
checkNotNull(suffix, "suffix == null");
Builder builder = builder().add("$N", prefix);
return Collector.of(
() -> new CodeBlockJoiner(separator, builder), CodeBlockJoiner::add, CodeBlockJoiner::merge, joiner -> {
Expand Down Expand Up @@ -192,6 +199,8 @@ public boolean isEmpty() {
* value {@code java.lang.Integer.class} in the argument map.
*/
public Builder addNamed(String format, Map<String, ?> arguments) {
checkNotNull(format, "format == null");
checkNotNull(arguments, "arguments == null");
int p = 0;

for (String argument : arguments.keySet()) {
Expand Down Expand Up @@ -243,6 +252,7 @@ public Builder addNamed(String format, Map<String, ?> arguments) {
}

public Builder add(CodeBlock codeBlock) {
checkNotNull(codeBlock, "codeBlock == null");
formatParts.addAll(codeBlock.formatParts);
args.addAll(codeBlock.args);
return this;
Expand All @@ -260,6 +270,8 @@ public Builder add(CodeBlock codeBlock) {
* error.
*/
public Builder add(String format, Object... args) {
checkNotNull(format, "format == null");
checkNotNull(args, "args == null");
boolean hasRelative = false;
boolean hasIndexed = false;

Expand Down Expand Up @@ -421,6 +433,7 @@ private TypeName argToType(Object o) {
* Shouldn't contain braces or newline characters.
*/
public Builder beginControlFlow(String controlFlow, Object... args) {
checkNotNull(controlFlow, "controlFlow == null"); // otherwise string concat turns this into non-null
add(controlFlow + " {\n", args);
indent();
return this;
Expand All @@ -431,6 +444,7 @@ public Builder beginControlFlow(String controlFlow, Object... args) {
* Shouldn't contain braces or newline characters.
*/
public Builder nextControlFlow(String controlFlow, Object... args) {
checkNotNull(controlFlow, "controlFlow == null"); // otherwise string concat turns this into non-null
unindent();
add("} " + controlFlow + " {\n", args);
indent();
Expand All @@ -448,6 +462,7 @@ public Builder endControlFlow() {
* "while(foo == 20)". Only used for "do/while" control flows.
*/
public Builder endControlFlow(String controlFlow, Object... args) {
checkNotNull(controlFlow, "controlFlow == null"); // otherwise string concat turns this into non-null
unindent();
add("} " + controlFlow + ";\n", args);
return this;
Expand All @@ -461,6 +476,7 @@ public Builder addStatement(String format, Object... args) {
}

public Builder addStatement(CodeBlock codeBlock) {
checkNotNull(codeBlock, "codeBlock == null");
return addStatement("$L", codeBlock);
}

Expand Down
11 changes: 11 additions & 0 deletions javapoet/src/main/java/com/palantir/javapoet/CodeWriter.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package com.palantir.javapoet;

import static com.palantir.javapoet.Util.checkArgument;
import static com.palantir.javapoet.Util.checkNoNullElement;
import static com.palantir.javapoet.Util.checkNotNull;
import static com.palantir.javapoet.Util.checkState;
import static com.palantir.javapoet.Util.stringLiteralWithDoubleQuotes;
Expand Down Expand Up @@ -133,6 +134,7 @@ public CodeWriter popPackage() {
}

public CodeWriter pushType(TypeSpec type) {
checkNotNull(type, "type == null");
this.typeSpecStack.add(type);
return this;
}
Expand All @@ -143,6 +145,7 @@ public CodeWriter popType() {
}

public void emitComment(CodeBlock codeBlock) throws IOException {
checkNotNull(codeBlock, "codeBlock == null");
trailingNewline = true; // Force the '//' prefix for the comment.
comment = true;
try {
Expand All @@ -154,6 +157,7 @@ public void emitComment(CodeBlock codeBlock) throws IOException {
}

public void emitJavadoc(CodeBlock javadocCodeBlock) throws IOException {
checkNotNull(javadocCodeBlock, "javadocCodeBlock == null");
if (javadocCodeBlock.isEmpty()) {
return;
}
Expand All @@ -169,6 +173,7 @@ public void emitJavadoc(CodeBlock javadocCodeBlock) throws IOException {
}

public void emitAnnotations(List<AnnotationSpec> annotations, boolean inline) throws IOException {
checkNoNullElement(annotations, "annotations");
for (AnnotationSpec annotationSpec : annotations) {
annotationSpec.emit(this, inline);
emit(inline ? " " : "\n");
Expand All @@ -180,6 +185,8 @@ public void emitAnnotations(List<AnnotationSpec> annotations, boolean inline) th
* be emitted.
*/
public void emitModifiers(Set<Modifier> modifiers, Set<Modifier> implicitModifiers) throws IOException {
checkNoNullElement(modifiers, "modifiers");
checkNoNullElement(implicitModifiers, "implicitModifiers");
if (modifiers.isEmpty()) {
return;
}
Expand All @@ -201,6 +208,7 @@ public void emitModifiers(Set<Modifier> modifiers) throws IOException {
* everywhere else bounds are omitted.
*/
public void emitTypeVariables(List<TypeVariableName> typeVariables) throws IOException {
checkNoNullElement(typeVariables, "typeVariables");
if (typeVariables.isEmpty()) {
return;
}
Expand Down Expand Up @@ -258,6 +266,7 @@ public void emitJavadocWithParameters(CodeBlock javadoc, Iterable<ParameterSpec>
}

public void popTypeVariables(List<TypeVariableName> typeVariables) {
checkNoNullElement(typeVariables, "typeVariables");
typeVariables.forEach(typeVariable -> currentTypeVariables.remove(typeVariable.name()));
}

Expand All @@ -274,6 +283,7 @@ public CodeWriter emit(CodeBlock codeBlock) throws IOException {
}

public CodeWriter emit(CodeBlock codeBlock, boolean ensureTrailingNewline) throws IOException {
checkNotNull(codeBlock, "codeBlock == null");
int a = 0;
ClassName deferredTypeName = null; // used by "import static" logic
ListIterator<String> partIterator = codeBlock.formatParts().listIterator();
Expand Down Expand Up @@ -518,6 +528,7 @@ private ClassName stackClassName(int stackDepth, String simpleName) {
* unnecessary trailing whitespace.
*/
CodeWriter emitAndIndent(String s) throws IOException {
checkNotNull(s, "s == null");
boolean first = true;
for (String line : LINE_BREAKING_PATTERN.split(s, -1)) {
// Emit a newline character. Make sure blank lines in Javadoc & comments look good.
Expand Down
20 changes: 15 additions & 5 deletions javapoet/src/main/java/com/palantir/javapoet/FieldSpec.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import static com.palantir.javapoet.Util.checkArgument;
import static com.palantir.javapoet.Util.checkNotNull;
import static com.palantir.javapoet.Util.checkState;
import static com.palantir.javapoet.Util.nonNullList;

import java.io.IOException;
import java.io.UncheckedIOException;
Expand Down Expand Up @@ -116,6 +117,7 @@ public String toString() {

public static Builder builder(TypeName type, String name, Modifier... modifiers) {
checkNotNull(type, "type == null");
checkNotNull(name, "name == null");
checkArgument(SourceVersion.isName(name), "not a valid name: %s", name);
return new Builder(type, name).addModifiers(modifiers);
}
Expand Down Expand Up @@ -159,29 +161,37 @@ public Builder addJavadoc(CodeBlock block) {
}

public Builder addAnnotations(Iterable<AnnotationSpec> annotationSpecs) {
checkArgument(annotationSpecs != null, "annotationSpecs == null");
checkNotNull(annotationSpecs, "annotationSpecs == null");
for (AnnotationSpec annotationSpec : annotationSpecs) {
this.annotations.add(annotationSpec);
addAnnotation(annotationSpec);
}
return this;
}

public Builder addAnnotation(AnnotationSpec annotationSpec) {
checkNotNull(annotationSpec, "annotationSpec == null");
this.annotations.add(annotationSpec);
return this;
}

public Builder addAnnotation(ClassName annotation) {
this.annotations.add(AnnotationSpec.builder(annotation).build());
return this;
return addAnnotation(AnnotationSpec.builder(annotation).build());
}

public Builder addAnnotation(Class<?> annotation) {
return addAnnotation(ClassName.get(annotation));
}

public Builder addModifiers(Modifier... modifiers) {
Collections.addAll(this.modifiers, modifiers);
return addModifiers(nonNullList(modifiers, "modifiers"));
}

public Builder addModifiers(Iterable<Modifier> modifiers) {
checkNotNull(modifiers, "modifiers == null");
for (Modifier modifier : modifiers) {
checkNotNull(modifier, "modifiers contain null");
this.modifiers.add(modifier);
}
return this;
}

Expand Down
13 changes: 8 additions & 5 deletions javapoet/src/main/java/com/palantir/javapoet/JavaFile.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package com.palantir.javapoet;

import static com.palantir.javapoet.Util.checkArgument;
import static com.palantir.javapoet.Util.checkNoNullElement;
import static com.palantir.javapoet.Util.checkNotNull;

import java.io.ByteArrayInputStream;
Expand All @@ -30,7 +31,6 @@
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
Expand Down Expand Up @@ -99,6 +99,7 @@ private void fillAlwaysQualifiedNames(TypeSpec spec, Set<String> alwaysQualified
}

public void writeTo(Appendable out) throws IOException {
checkNotNull(out, "out == null");
// First pass: emit the entire class, just to collect the types we'll need to import.
CodeWriter importsCollector = new CodeWriter(NULL_APPENDABLE, indent, staticImports, alwaysQualify);
emit(importsCollector);
Expand Down Expand Up @@ -129,6 +130,7 @@ public void writeTo(Path directory, Charset charset) throws IOException {

/** Writes this to {@code filer}. */
public void writeTo(Filer filer) throws IOException {
checkNotNull(filer, "filer == null");
String fileName = packageName.isEmpty() ? typeSpec.name() : packageName + "." + typeSpec.name();
List<Element> originatingElements = typeSpec.originatingElements();
JavaFileObject filerSourceFile = filer.createSourceFile(fileName, originatingElements.toArray(new Element[0]));
Expand Down Expand Up @@ -167,10 +169,12 @@ public Path writeToPath(Path directory) throws IOException {
* Returns the {@link Path} instance to which source is actually written.
*/
public Path writeToPath(Path directory, Charset charset) throws IOException {
checkNotNull(directory, "directory == null");
checkArgument(
Files.notExists(directory) || Files.isDirectory(directory),
"path %s exists but is not a directory.",
directory);
checkNotNull(charset, "charset == null");
Path outputDirectory = directory;
if (!packageName.isEmpty()) {
for (String packageComponent : packageName.split("\\.", -1)) {
Expand Down Expand Up @@ -323,11 +327,10 @@ public Builder addStaticImport(Class<?> clazz, String... names) {
}

public Builder addStaticImport(ClassName className, String... names) {
checkArgument(className != null, "className == null");
checkArgument(names != null, "names == null");
checkNotNull(className, "className == null");
checkNoNullElement(names, "names");
checkArgument(names.length > 0, "names array is empty");
for (String name : names) {
checkArgument(name != null, "null entry in names array: %s", Arrays.toString(names));
staticImports.add(className.canonicalName() + "." + name);
}
return this;
Expand All @@ -347,7 +350,7 @@ public Builder skipJavaLangImports(boolean skipJavaLangImports) {
}

public Builder indent(String indent) {
this.indent = indent;
this.indent = checkNotNull(indent, "indent == null");
return this;
}

Expand Down
Loading