Skip to content

Commit

Permalink
java21:reworks all the packaging
Browse files Browse the repository at this point in the history
  • Loading branch information
npeters committed Nov 2, 2024
1 parent 1ed1148 commit 56b6eab
Show file tree
Hide file tree
Showing 13 changed files with 969 additions and 6 deletions.
117 changes: 112 additions & 5 deletions palantir-java-format/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ tasks.withType(JavaCompile).configureEach {
options.compilerArgs += jvmArgList

if (JavaVersion.current() < JavaVersion.VERSION_14) {
excludes = ['**/Java14InputAstVisitor.java']
excludes = ['**/Java14InputAstVisitor.java', '**/Java21InputAstVisitor.java']
}
}

Expand All @@ -62,7 +62,7 @@ tasks.withType(Javadoc).configureEach {
options.optionFiles << file('../gradle/javadoc.options')

if (JavaVersion.current() < JavaVersion.VERSION_14) {
exclude '**/Java14InputAstVisitor.java'
excludes = ['**/Java14InputAstVisitor.java', '**/Java21InputAstVisitor.java']
}
}

Expand All @@ -77,15 +77,122 @@ tasks.named("test") {
systemProperty 'junit.jupiter.execution.parallel.mode.default', 'concurrent'
}

// necessary to compile Java14InputAstVisitor
idea {
module.languageLevel = new org.gradle.plugins.ide.idea.model.IdeaLanguageLevel(14)

def target21Compiler = javaToolchains.compilerFor {
it.languageVersion = JavaLanguageVersion.of(21)
}

def target21Launcher = javaToolchains.launcherFor {
it.languageVersion = JavaLanguageVersion.of(21)
}


sourceSets.create("java21") {
}

sourceSets.create("test21") {
}

tasks.named("compileJava21Java", JavaCompile) {
it.javaCompiler = target21Compiler
it.sourceCompatibility = 21
it.targetCompatibility = 21
it.source = sourceSets.named("java21").get().java
it.classpath = project.objects.fileCollection().from(
sourceSets.named("main").get().output,
sourceSets.named("main").get().compileClasspath,
sourceSets.named("java21").get().compileClasspath
)
}

tasks.named("compileTest21Java", JavaCompile) {
it.javaCompiler = target21Compiler
it.sourceCompatibility = 21
it.targetCompatibility = 21
it.source = sourceSets.named("test21").get().java
it.classpath = sourceSets.named("test").get().runtimeClasspath
}

tasks.register("testJava21", Test) {

it.group = "verification"
it.javaLauncher.set(target21Launcher.get())

useJUnitPlatform()

it.testClassesDirs = project.objects.fileCollection().from(
sourceSets.named("test21").get().output.classesDirs
)
it.classpath = project.objects.fileCollection().from(
sourceSets.named("test21").get().output,
sourceSets.named("java21").get().output,
sourceSets.named("test").get().runtimeClasspath
)
}


sourceSets.create("java21Preview") {
java.srcDirs(project.layout.projectDirectory.dir("src/java21Preview/java"))
}

sourceSets.create("test21Preview") {
java.srcDirs(project.layout.projectDirectory.dir("src/test21Preview/java"))
}

tasks.named("compileJava21PreviewJava", JavaCompile) {
it.javaCompiler = target21Compiler
it.sourceCompatibility = 21
it.targetCompatibility = 21
options.compilerArgs += '--enable-preview'
it.source = sourceSets.named("java21Preview").get().java
it.classpath = objects.fileCollection().from(
sourceSets.named("main").get().output,
sourceSets.named("java21").get().output,
sourceSets.named("main").get().compileClasspath,
sourceSets.named("java21Preview").get().compileClasspath

)
}

tasks.named("compileTest21PreviewJava", JavaCompile) {
it.javaCompiler = target21Compiler
it.sourceCompatibility = 21
it.targetCompatibility = 21
options.compilerArgs += '--enable-preview'
it.source = sourceSets.named("test21Preview").get().java
it.classpath = sourceSets.named("test").get().runtimeClasspath
}

tasks.register("testJava21Preview", Test) {

it.group = "verification"
it.javaLauncher.set(target21Launcher.get())
jvmArgs += '--enable-preview'
useJUnitPlatform()

it.testClassesDirs = project.objects.fileCollection().from(
sourceSets.named("test21Preview").get().output.classesDirs
)
it.classpath = project.objects.fileCollection().from(
sourceSets.named("test21Preview").get().output,
sourceSets.named("java21Preview").get().output,
sourceSets.named("java21").get().output,
sourceSets.named("test").get().runtimeClasspath
)
}

tasks.check { dependsOn(test,testJava21,testJava21Preview) }

// This block may be replaced by BaselineExportsExtension exports
// once https://github.com/gradle/gradle/issues/18824 is resolved.
tasks.named("jar", Jar) {
manifest {
attributes('Add-Exports': exports.join(' '))
}
it.from(
sourceSets.named("main").get().output,
sourceSets.named("java21").get().output,
sourceSets.named("java21Preview").get().output
)

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
/*
* (c) Copyright 2024 Palantir Technologies Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.palantir.javaformat.java.java21;

import com.google.common.collect.Iterables;
import com.palantir.javaformat.OpsBuilder;
import com.palantir.javaformat.java.JavaInputAstVisitor;
import com.palantir.javaformat.java.java14.Java14InputAstVisitor;
import com.sun.source.tree.BlockTree;
import com.sun.source.tree.CaseTree;
import com.sun.source.tree.ConstantCaseLabelTree;
import com.sun.source.tree.DeconstructionPatternTree;
import com.sun.source.tree.ParenthesizedTree;
import com.sun.source.tree.PatternCaseLabelTree;
import com.sun.source.tree.PatternTree;
import com.sun.source.tree.Tree;
import com.sun.source.tree.Tree.Kind;
import java.lang.reflect.Method;
import java.util.List;

/**
* Extends {@link Java14InputAstVisitor} with support for AST nodes that were added or modified for Java 14.
*/
public class Java21InputAstVisitor extends Java14InputAstVisitor {
private static final Method CASE_TREE_GET_LABELS2 = maybeGetMethodPrivate(CaseTree.class, "getLabels");

private static Method maybeGetMethodPrivate(Class<?> c, String name) {
try {
return c.getMethod(name);
} catch (ReflectiveOperationException e) {
return null;
}
}

private static Object invokePrivate(Method m, Object target) {
try {
return m.invoke(target);
} catch (ReflectiveOperationException e) {
throw new RuntimeException(e.getMessage(), e);
}
}

public Java21InputAstVisitor(OpsBuilder builder, int indentMultiplier) {
super(builder, indentMultiplier);
}

@Override
public Void visitParenthesized(ParenthesizedTree node, Void unused) {
token("(");
Void v = scan(node.getExpression(), unused);
token(")");
return v;
}

@Override
public Void visitDeconstructionPattern(DeconstructionPatternTree node, Void unused) {

Void r = scan(node.getDeconstructor(), unused);
token("(");
boolean firstInRow = true;
for (PatternTree item : node.getNestedPatterns()) {
if (!firstInRow) {
token(",");
builder.breakToFill(" ");
}
scan(item, null);
firstInRow = false;
}
token(")");
return r;
}

@Override
public Void visitConstantCaseLabel(ConstantCaseLabelTree node, Void unused) {
return scan(node.getConstantExpression(), unused);
}

@Override
public Void visitCase(CaseTree node, Void unused) {
sync(node);
markForPartialFormat();
builder.forcedBreak();
List<? extends Tree> labels;
boolean isDefault;
if (CASE_TREE_GET_LABELS2 != null) {
labels = (List<? extends Tree>) invokePrivate(CASE_TREE_GET_LABELS2, node);
isDefault = labels.size() == 1
&& Iterables.getOnlyElement(labels).getKind().name().equals("DEFAULT_CASE_LABEL");
} else {
labels = node.getExpressions();
isDefault = labels.isEmpty();
}
if (isDefault) {
token("default", plusTwo);
} else {
token("case", plusTwo);
builder.space();
builder.open(labels.size() > 1 ? plusFour : JavaInputAstVisitor.ZERO);
boolean first = true;
for (Tree expression : labels) {
if (!first) {
token(",");
builder.breakOp(" ");
}
scan(expression, null);
first = false;
}
builder.close();
}
switch (node.getCaseKind()) {
case STATEMENT:
token(":");
boolean isBlock = node.getStatements().size() == 1
&& node.getStatements().get(0).getKind() == Kind.BLOCK;
builder.open(isBlock ? JavaInputAstVisitor.ZERO : plusTwo);
if (isBlock) {
builder.space();
}
visitStatements(node.getStatements(), isBlock);
builder.close();
break;
case RULE:
if (node.getGuard() != null) {
builder.space();
token("when");
builder.space();
scan(node.getGuard(), null);
}

builder.space();
token("-");
token(">");

builder.space();
if (node.getBody().getKind() == Kind.BLOCK) {
// Explicit call with {@link CollapseEmptyOrNot.YES} to handle empty case blocks.
visitBlock(
(BlockTree) node.getBody(),
CollapseEmptyOrNot.YES,
AllowLeadingBlankLine.NO,
AllowTrailingBlankLine.NO);
} else {
scan(node.getBody(), null);
}
builder.guessToken(";");
break;
default:
throw new IllegalArgumentException(node.getCaseKind().name());
}
return null;
}

public Void visitPatternCaseLabel(PatternCaseLabelTree node, Void p) {
return scan(node.getPattern(), p);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* (c) Copyright 2024 Palantir Technologies Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.palantir.javaformat.java.java21;

import com.palantir.javaformat.OpsBuilder;
import com.sun.source.tree.AnyPatternTree;

public class Java21PreviewInputAstVisitor extends Java21InputAstVisitor {

public Java21PreviewInputAstVisitor(OpsBuilder builder, int indentMultiplier) {
super(builder, indentMultiplier);
}

public Void visitAnyPattern(AnyPatternTree node, Void p) {
token("_");
return p;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import com.sun.tools.javac.util.Log;
import com.sun.tools.javac.util.Options;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.net.URI;
import java.util.Collection;
import javax.tools.Diagnostic;
Expand Down Expand Up @@ -131,7 +132,26 @@ static JavaOutput format(
OpsBuilder opsBuilder = new OpsBuilder(javaInput);

JavaInputAstVisitor visitor;
if (getRuntimeVersion() >= 14) {

if (getRuntimeVersion() >= 21 && isEnabledPriew()) {
try {
visitor = Class.forName("com.palantir.javaformat.java.java21.Java21PreviewInputAstVisitor")
.asSubclass(JavaInputAstVisitor.class)
.getConstructor(OpsBuilder.class, int.class)
.newInstance(opsBuilder, options.indentationMultiplier());
} catch (ReflectiveOperationException e) {
throw new RuntimeException(e.getMessage(), e);
}
} else if (getRuntimeVersion() >= 21) {
try {
visitor = Class.forName("com.palantir.javaformat.java.java21.Java21InputAstVisitor")
.asSubclass(JavaInputAstVisitor.class)
.getConstructor(OpsBuilder.class, int.class)
.newInstance(opsBuilder, options.indentationMultiplier());
} catch (ReflectiveOperationException e) {
throw new RuntimeException(e.getMessage(), e);
}
} else if (getRuntimeVersion() >= 14) {
try {
visitor = Class.forName("com.palantir.javaformat.java.java14.Java14InputAstVisitor")
.asSubclass(JavaInputAstVisitor.class)
Expand Down Expand Up @@ -206,6 +226,11 @@ static int getRuntimeVersion() {
return Runtime.version().feature();
}

@VisibleForTesting
static boolean isEnabledPriew() {
return ManagementFactory.getRuntimeMXBean().getInputArguments().contains("--enable-preview");
}

static boolean errorDiagnostic(Diagnostic<?> input) {
if (input.getKind() != Diagnostic.Kind.ERROR) {
return false;
Expand Down
Loading

0 comments on commit 56b6eab

Please sign in to comment.