Skip to content
This repository was archived by the owner on Aug 11, 2025. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all 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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
target
.vscode
10 changes: 10 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,16 @@
<build>
<pluginManagement>
<plugins>
<plugin>
Copy link
Owner

Choose a reason for hiding this comment

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

Why is this needed? If just personal preference please put in a separate commit with its own comment.

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 will make sure that every change apart from the lambdas will be in a separate commit

<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.6.3</version>
<configuration>
<show>private</show>
<nohelp>true</nohelp>
</configuration>
</plugin>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
Expand Down
123 changes: 123 additions & 0 deletions src/main/java/com/squareup/javapoet/CodeBlock.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,14 @@
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

import static com.squareup.javapoet.Util.checkArgument;
Expand Down Expand Up @@ -415,6 +418,126 @@ public Builder add(CodeBlock codeBlock) {
return this;
}

/**
* Structures a lambda function based on some inputs and a CodeBlock body.<br>
* Should be used with {@link #add(String, Object...) addCode},
* to provide specific behaviour such as
* <b>methodcall((int x, int y) -> x + y, 5)</b>.
* @param parameters the input parameters of the function.
* @param emitTypes true if the types of the inputs should
* be emitted on the result.
* @param body the body of the function.
*/
public Builder addLambda(Iterable<ParameterSpec> parameters, boolean emitTypes, CodeBlock body) {
int paramsLen = 0;
// check that the input types are valid
for (ParameterSpec parameter : parameters) {
checkArgument(!parameter.type.equals(TypeName.VOID),
"lambda input parameters cannot be of void type");
paramsLen++;
}

Stream<ParameterSpec> parameterStream = StreamSupport.stream(
parameters.spliterator(),
false
);

// the inputs of the lambda (left side)
String inputSide = parameterStream
.map(p -> emitTypes ? p.toString() : p.name)
.collect(Collectors.joining(", "));

// on 0 or more than 1 inputs, or in case of type emission,
// parentheses are mandatory
if (paramsLen == 0 || paramsLen > 1 || emitTypes) {
inputSide = "(" + inputSide + ")";
}

// the body of the lambda (right side)
String bodySide = body.toString().replaceAll("\n", "");

// in case of multiple statements, braces are mandatory
if (bodySide.contains(";")) {
bodySide = "{" + bodySide + "}";
}

// the full lambda structure
add(inputSide + " -> " + bodySide);
return this;
}

/**
* Structures a lambda function based on some inputs and a CodeBlock body.<br>
* Will not emit the input types.<br>
* Should be used with {@link #add(String, Object...) addCode},
* to provide specific behaviour such as
* <b>methodcall((x, y) -> x + y, 5)</b>.
* @param parameters the input parameters of the function.
* @param body the body of the function.
*/
public Builder addLambda(Iterable<ParameterSpec> parameters, CodeBlock body) {
return addLambda(parameters, false, body);
}

/**
* Structures a lambda function based on some inputs and an expression body.<br>
* Should be used with {@link #add(String, Object...) addCode},
* to provide specific behaviour such as
* <b>methodcall((int x, int y) -> x + y, 5)</b>.
* @param parameters the input parameters of the function.
* @param emitTypes true if the types of the inputs should
* be emitted on the result.
* @param expressionFormat the format that should be used
* for the expression.
* @param args the values that should be placed in the holders
* of the format.
*/
public Builder addLambda(Iterable<ParameterSpec> parameters, boolean emitTypes,
String expressionFormat, Object... args) {
return addLambda(parameters, emitTypes, CodeBlock.of(expressionFormat, args));
}

/**
* Structures a lambda function based on some inputs and an expression body.<br>
* Will not emit the input types.<br>
* Should be used with {@link #add(String, Object...) addCode},
* to provide specific behaviour such as
* <b>methodcall((x, y) -> x + y, 5)</b>.
* @param parameters the input parameters of the function.
* @param expressionFormat the format that should be used
* for the expression.
* @param args the values that should be placed in the holders
* of the format.
*/
public Builder addLambda(Iterable<ParameterSpec> parameters, String expressionFormat, Object... args) {
return addLambda(parameters, false, CodeBlock.of(expressionFormat, args));
}

/**
* Structures a producer lambda function based on a CodeBlock body.<br>
* Should be used with {@link #add(String, Object...) addCode},
* to provide specific behaviour such as
* <b>methodcall(() -> 3 + 2, 5)</b>.
* @param body the body of the lambda.
*/
public Builder addLambda(CodeBlock body) {
return addLambda(Collections.emptyList(), false, body);
}

/**
* Structures a producer lambda function based on an expression body.<br>
* Should be used with {@link #add(String, Object...) addCode},
* to provide specific behaviour such as
* <b>methodcall(() -> 3 + 2, 5)</b>.
* @param expressionFormat the format that should be used
* for the expression.
* @param args the values that should be placed in the holders
* of the format.
*/
public Builder addLambda(String expressionFormat, Object... args) {
return addLambda(Collections.emptyList(), false, expressionFormat, args);
}

public Builder indent() {
this.formatParts.add("$>");
return this;
Expand Down
110 changes: 105 additions & 5 deletions src/main/java/com/squareup/javapoet/MethodSpec.java
Original file line number Diff line number Diff line change
Expand Up @@ -296,21 +296,25 @@ public static final class Builder {
private String name;

private final CodeBlock.Builder javadoc = CodeBlock.builder();
public final List<AnnotationSpec> annotations = new ArrayList<>();
public final List<Modifier> modifiers = new ArrayList<>();
public final List<TypeVariableName> typeVariables = new ArrayList<>();
private TypeName returnType;
public final List<ParameterSpec> parameters = new ArrayList<>();
private boolean varargs;
private final Set<TypeName> exceptions = new LinkedHashSet<>();
private final CodeBlock.Builder code = CodeBlock.builder();
private boolean varargs;
private CodeBlock defaultValue;

public final List<TypeVariableName> typeVariables = new ArrayList<>();
public final List<AnnotationSpec> annotations = new ArrayList<>();
public final List<Modifier> modifiers = new ArrayList<>();
public final List<ParameterSpec> parameters = new ArrayList<>();

private Builder(String name) {
setName(name);
}

/**
* Sets a name for this builder.
* @param name the name to be set for the method.
*/
public Builder setName(String name) {
checkNotNull(name, "name == null");
checkArgument(name.equals(CONSTRUCTOR) || SourceVersion.isName(name),
Expand Down Expand Up @@ -500,6 +504,10 @@ public Builder nextControlFlow(CodeBlock codeBlock) {
return nextControlFlow("$L", codeBlock);
}

/**
* Ends the last open control flow.
* Should be used once for every control flow.
*/
public Builder endControlFlow() {
code.endControlFlow();
return this;
Expand Down Expand Up @@ -532,6 +540,98 @@ public Builder addStatement(CodeBlock codeBlock) {
return this;
}

/**
* Structures a lambda function based on some inputs and a CodeBlock body.<br>
* Should be used with {@link #addCode(String, Object...) addCode},
* to provide specific behaviour such as
* <b>methodcall((int x, int y) -> x + y, 5)</b>.
* @param parameters the input parameters of the function.
* @param emitTypes true if the types of the inputs should
* be emitted on the result.
* @param body the body of the function.
*/
public Builder addLambda(Iterable<ParameterSpec> parameters, boolean emitTypes, CodeBlock body) {
code.addLambda(parameters, emitTypes, body);
return this;
}

/**
* Structures a lambda function based on some inputs and a CodeBlock body.<br>
* Will not emit the input types.<br>
* Should be used with {@link #addCode(String, Object...) addCode},
* to provide specific behaviour such as
* <b>methodcall((x, y) -> x + y, 5)</b>.
* @param parameters the input parameters of the function.
* @param body the body of the function.
*/
public Builder addLambda(Iterable<ParameterSpec> parameters, CodeBlock body) {
code.addLambda(parameters, false, body);
return this;
}

/**
* Structures a lambda function based on some inputs and an expression body.<br>
* Should be used with {@link #addCode(String, Object...) addCode},
* to provide specific behaviour such as
* <b>methodcall((int x, int y) -> x + y, 5)</b>.
* @param parameters the input parameters of the function.
* @param emitTypes true if the types of the inputs should
* be emitted on the result.
* @param expressionFormat the format that should be used
* for the expression.
* @param args the values that should be placed in the holders
* of the format.
*/
public Builder addLambda(Iterable<ParameterSpec> parameters, boolean emitTypes,
String expressionFormat, Object... args) {
code.addLambda(parameters, emitTypes, CodeBlock.of(expressionFormat, args));
return this;
}

/**
* Structures a lambda function based on some inputs and an expression body.<br>
* Will not emit the input types.<br>
* Should be used with {@link #addCode(String, Object...) addCode},
* to provide specific behaviour such as
* <b>methodcall((x, y) -> x + y, 5)</b>.
* @param parameters the input parameters of the function.
* @param expressionFormat the format that should be used
* for the expression.
* @param args the values that should be placed in the holders
* of the format.
*/
public Builder addLambda(Iterable<ParameterSpec> parameters, String expressionFormat, Object... args) {
code.addLambda(parameters, false, CodeBlock.of(expressionFormat, args));
return this;
}

/**
* Structures a producer lambda function based on a CodeBlock body.<br>
* Should be used with {@link #addCode(String, Object...) addCode},
* to provide specific behaviour such as
* <b>methodcall(() -> 3 + 2, 5)</b>.
* @param body the body of the lambda.
*/
public Builder addLambda(CodeBlock body) {
code.addLambda(Collections.emptyList(), false, body);
return this;
}

/**
* Structures a producer lambda function based on an expression body.<br>
* Should be used with {@link #addCode(String, Object...) addCode},
* to provide specific behaviour such as
* <b>methodcall(() -> 3 + 2, 5)</b>.
* @param expressionFormat the format that should be used
* for the expression.
* @param args the values that should be placed in the holders
* of the format.
*/
public Builder addLambda(String expressionFormat, Object... args) {
code.addLambda(Collections.emptyList(), false, expressionFormat, args);
return this;
}

public MethodSpec build() {
return new MethodSpec(this);
}
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/squareup/javapoet/TypeSpec.java
Original file line number Diff line number Diff line change
Expand Up @@ -610,7 +610,7 @@ public Builder addSuperinterface(Type superinterface, boolean avoidNestedTypeNam
public Builder addPermits(Iterable<? extends TypeName> permits) {
checkArgument(permits != null, "permits == null");
for (TypeName permit : permits) {
addPermits(permits);
addPermits(permit);
Copy link
Owner

Choose a reason for hiding this comment

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

nit: I'd put this in a separate commit as it's not related to this commit

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Must have missed it while squashing my commits, sorry for the inconvenience. Thanks!

Copy link
Owner

Choose a reason for hiding this comment

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

Have you pushed latest? I'm still seeing this in the 1 commit.

}
return this;
}
Expand Down
Loading