Skip to content

Commit

Permalink
Merge branch 'main' into psi-based-parser
Browse files Browse the repository at this point in the history
  • Loading branch information
kunli2 committed Sep 28, 2023
2 parents 7799ff1 + 93bd2eb commit 09a09c6
Show file tree
Hide file tree
Showing 12 changed files with 284 additions and 52 deletions.
4 changes: 3 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ dependencies {
testImplementation("org.openrewrite:rewrite-test")
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:latest.release")
testRuntimeOnly("org.openrewrite:rewrite-java-17")
testRuntimeOnly("com.squareup.misk:misk-prometheus:latest.release")
testRuntimeOnly("com.squareup.misk:misk-metrics:latest.release")

testImplementation("com.github.ajalt.clikt:clikt:3.5.0")
}
Expand All @@ -50,4 +52,4 @@ compileKotlin.kotlinOptions {
val compileTestKotlin: KotlinCompile by tasks
compileTestKotlin.kotlinOptions {
jvmTarget = "1.8"
}
}
34 changes: 33 additions & 1 deletion src/main/java/org/openrewrite/kotlin/AddImport.java
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,39 @@ private boolean hasReference(JavaSourceFile compilationUnit) {
if (member == null) {
//Non-static imports, we just look for field accesses.
for (NameTree t : FindTypes.find(compilationUnit, fullyQualifiedName)) {
if ((!(t instanceof J.FieldAccess) || !((J.FieldAccess) t).isFullyQualifiedClassReference(fullyQualifiedName)) &&
JavaType.Class classType = JavaType.ShallowClass.build(fullyQualifiedName);
boolean foundReference = false;
boolean usingAlias = false;
if (t instanceof J.ParameterizedType) {
J.ParameterizedType pt = (J.ParameterizedType) t;
if (pt.getClazz() instanceof J.Identifier) {
String nameInSource = ((J.Identifier) pt.getClazz()).getSimpleName();
if (alias != null) {
if ( nameInSource.equals(alias)) {
usingAlias = true;
}
} else if (nameInSource.equals(classType.getClassName())) {
foundReference = true;
}
}
} else if (t instanceof J.Identifier) {
String nameInSource = ((J.Identifier) t).getSimpleName();
if (alias != null) {
if ( nameInSource.equals(alias)) {
usingAlias = true;
}
} else if (nameInSource.equals(classType.getClassName())) {
foundReference = true;
}
} else {
foundReference = true;
}

if (usingAlias) {
return true;
}

if (foundReference && (!(t instanceof J.FieldAccess) || !((J.FieldAccess) t).isFullyQualifiedClassReference(fullyQualifiedName)) &&
isTypeReference(t)) {
return true;
}
Expand Down
36 changes: 0 additions & 36 deletions src/main/java/org/openrewrite/kotlin/KotlinVisitor.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import org.openrewrite.java.JavaVisitor;
import org.openrewrite.java.tree.*;
import org.openrewrite.kotlin.marker.*;
import org.openrewrite.kotlin.service.KotlinAutoFormatService;
import org.openrewrite.kotlin.tree.K;
import org.openrewrite.kotlin.tree.KContainer;
import org.openrewrite.kotlin.tree.KRightPadded;
Expand Down Expand Up @@ -66,41 +65,6 @@ public J visitCompilationUnit(J.CompilationUnit cu, P p) {
throw new UnsupportedOperationException("Kotlin has a different structure for its compilation unit. See K.CompilationUnit.");
}

@Override
public <J2 extends J> J2 autoFormat(J2 j, P p) {
return autoFormat(j, p, getCursor().getParentTreeCursor());
}

@SuppressWarnings({"ConstantConditions", "unchecked"})
@Override
public <J2 extends J> J2 autoFormat(J2 j, @Nullable J stopAfter, P p, Cursor cursor) {
KotlinAutoFormatService service = getCursor().firstEnclosingOrThrow(JavaSourceFile.class).service(KotlinAutoFormatService.class);
return (J2) service.autoFormatVisitor(stopAfter).visit(j, p, cursor);
}

@Override
public <J2 extends J> J2 autoFormat(J2 j, P p, Cursor cursor) {
return autoFormat(j, null, p, cursor);
}

@Override
public <J2 extends J> J2 maybeAutoFormat(J2 before, J2 after, P p) {
return maybeAutoFormat(before, after, p, getCursor().getParentTreeCursor());
}

@Override
public <J2 extends J> J2 maybeAutoFormat(J2 before, J2 after, P p, Cursor cursor) {
return maybeAutoFormat(before, after, null, p, cursor);
}

@Override
public <J2 extends J> J2 maybeAutoFormat(J2 before, J2 after, @Nullable J stopAfter, P p, Cursor cursor) {
if (before != after) {
return autoFormat(after, stopAfter, p, cursor);
}
return after;
}

public J visitAnnotatedExpression(K.AnnotatedExpression annotatedExpression, P p) {
K.AnnotatedExpression ae = annotatedExpression;
ae = ae.withMarkers(visitMarkers(ae.getMarkers(), p));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
import org.openrewrite.java.tree.JavaSourceFile;
import org.openrewrite.kotlin.KotlinIsoVisitor;
import org.openrewrite.kotlin.style.*;
import org.openrewrite.kotlin.tree.K;
import org.openrewrite.style.GeneralFormatStyle;

import java.util.Optional;
Expand All @@ -44,11 +43,6 @@ public AutoFormatVisitor(@Nullable Tree stopAfter) {
this.stopAfter = stopAfter;
}

@Override
public boolean isAcceptable(SourceFile sourceFile, P p) {
return sourceFile instanceof K.CompilationUnit;
}

@Override
public J visit(@Nullable Tree tree, P p, Cursor cursor) {
JavaSourceFile cu = (tree instanceof JavaSourceFile) ?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -945,7 +945,9 @@ public K.FunctionType visitFunctionType(K.FunctionType functionType, P p) {
K.FunctionType kf = super.visitFunctionType(functionType, p);

// handle space around arrow in function type
kf = kf.withArrow(updateSpace(kf.getArrow(), style.getOther().getAroundArrowInFunctionTypes()));
if (kf.getArrow() != null) {
kf = kf.withArrow(updateSpace(kf.getArrow(), style.getOther().getAroundArrowInFunctionTypes()));
}
kf = kf.withReturnType(spaceBefore(kf.getReturnType(), style.getOther().getAroundArrowInFunctionTypes()));
return kf;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ public J visitFunctionType(K.FunctionType functionType, PrintOutputCapture<P> p)
p.append(".");
}
delegate.visitContainer("(", functionType.getPadding().getParameters(), JContainer.Location.TYPE_PARAMETERS, ",", ")", p);
visitSpace(functionType.getArrow(), KSpace.Location.FUNCTION_TYPE_ARROW_PREFIX, p);
visitSpace(functionType.getArrow() != null ? functionType.getArrow() : Space.SINGLE_SPACE, KSpace.Location.FUNCTION_TYPE_ARROW_PREFIX, p);
p.append("->");
visit(functionType.getReturnType(), p);
if (nullable) {
Expand Down
9 changes: 8 additions & 1 deletion src/main/java/org/openrewrite/kotlin/style/Autodetect.java
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,14 @@ public Expression visitExpression(Expression expression, IndentStatistics stats)
if (statementExpressions.contains(expression)) {
return expression;
}
countIndents(expression.getPrefix().getWhitespace(), true, stats);
// (newline-separated) annotations on some common target are not continuations
// (newline-separated) annotations on some common target are not continuations
boolean isContinuation = !(expression instanceof J.Annotation && !(
// ...but annotations which are *arguments* to other annotations can be continuations
getCursor().getParentTreeCursor().getValue() instanceof J.Annotation
|| getCursor().getParentTreeCursor().getValue() instanceof J.NewArray
));
countIndents(expression.getPrefix().getWhitespace(), isContinuation, stats);

return expression;
}
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/org/openrewrite/kotlin/tree/K.java
Original file line number Diff line number Diff line change
Expand Up @@ -1011,7 +1011,7 @@ class FunctionType implements K, TypeTree, Expression {

public FunctionType(UUID id, Space prefix, Markers markers, List<Annotation> leadingAnnotations,
List<Modifier> modifiers, @Nullable JRightPadded<NameTree> receiver,
JContainer<TypeTree> parameters, Space arrow, TypedTree returnType) {
JContainer<TypeTree> parameters, @Nullable Space arrow, TypedTree returnType) {
this.id = id;
this.prefix = prefix;
this.markers = markers;
Expand Down Expand Up @@ -1071,6 +1071,7 @@ public FunctionType withParameters(List<TypeTree> parameters) {
return getPadding().withParameters(JContainer.withElementsNullable(this.parameters, parameters));
}

@Nullable // nullable for LST backwards compatibility reasons only
@With
@Getter
Space arrow;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1175,10 +1175,22 @@ class KotlinParserVisitor(
markers = markers.addIfAbsent(Extension(randomId()))
}

val implicitExtensionFunction = functionCall is FirImplicitInvokeCall
var hasExplicitReceiver = false
if (functionCall is FirImplicitInvokeCall) {
val explicitReceiver = functionCall.explicitReceiver
if (explicitReceiver is FirPropertyAccessExpression) {
if (explicitReceiver.explicitReceiver != null) {
hasExplicitReceiver = true
}
}
}

var implicitExtensionFunction = functionCall is FirImplicitInvokeCall
&& functionCall.arguments.isNotEmpty()
&& functionCall.source != null
&& functionCall.source!!.startOffset < functionCall.calleeReference.source!!.startOffset
&& !hasExplicitReceiver

if (functionCall !is FirImplicitInvokeCall || implicitExtensionFunction) {
val receiver = if (implicitExtensionFunction) functionCall.arguments[0] else getReceiver(functionCall.explicitReceiver)
if (receiver != null) {
Expand All @@ -1194,6 +1206,13 @@ class KotlinParserVisitor(
}
}

if (functionCall is FirImplicitInvokeCall) {
val receiver = functionCall.explicitReceiver
if (receiver is FirPropertyAccessExpression && receiver.explicitReceiver != null) {
select = padRight(convertToExpression(receiver.explicitReceiver as FirElement, data)!!, whitespace())
}
}

val name = visitElement(namedReference, data) as J.Identifier
var typeParams: JContainer<Expression>? = null
if (functionCall.typeArguments.isNotEmpty()) {
Expand Down Expand Up @@ -1413,6 +1432,18 @@ class KotlinParserVisitor(
var callPsi = getPsiElement(firCall)!!
callPsi = if (callPsi is KtDotQualifiedExpression || callPsi is KtSafeQualifiedExpression) callPsi.lastChild else callPsi
val firArguments = if (skipFirstArgument) firCall.argumentList.arguments.subList(1, firCall.argumentList.arguments.size) else firCall.argumentList.arguments

var hasParentheses = false
var lPAROffset = 0
if (firCall.argumentList.source is KtRealPsiSourceElement) {
val firArgumentsSource = firCall.argumentList.source.psi
val firstChild = firArgumentsSource?.firstChild
if (firstChild != null && firstChild.node.elementType == KtTokens.LPAR) {
hasParentheses = true
lPAROffset = firstChild.node.startOffset
}
}

val flattenedExpressions = firArguments.stream()
.map { e -> if (e is FirVarargArgumentsExpression) e.arguments else listOf(e) }
.flatMap { it.stream() }
Expand Down Expand Up @@ -1441,7 +1472,7 @@ class KotlinParserVisitor(
cursor++
saveCursor = cursor
parenOrBrace = source[cursor]
} else if ((parenOrBrace != '(' && parenOrBrace != '[') || isInfix) {
} else if (!hasParentheses && ((parenOrBrace != '(' && parenOrBrace != '[') || isInfix)) {
cursor(saveCursor)
containerPrefix = Space.EMPTY
markers = markers.addIfAbsent(OmitParentheses(randomId()))
Expand Down Expand Up @@ -1469,6 +1500,12 @@ class KotlinParserVisitor(
for (i in flattenedExpressions.indices) {
isTrailingLambda = hasTrailingLambda && i == argumentCount - 1
val expression = flattenedExpressions[i]

// Didn't find a way to proper reset the cursor, so have to do a hard reset here
if (firCall is FirImplicitInvokeCall && hasParentheses && i == 0) {
cursor = lPAROffset + 1
}

var expr = convertToExpression<Expression>(expression, data)!!
if (isTrailingLambda && expr !is J.Empty) {
expr = expr.withMarkers(expr.markers.addIfAbsent(TrailingLambdaArgument(randomId())))
Expand Down
Loading

0 comments on commit 09a09c6

Please sign in to comment.