Kapt3: As javac now reads stubs from Java files, not from AST, we should provide the valid names for all identifiers (at least names should not clash with Java keywords).
Rename identifiers if it clashes with Java keywords. (KT-15838)
This commit is contained in:
+18
-4
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.kapt3.stubs
|
|||||||
import com.sun.tools.javac.code.Flags
|
import com.sun.tools.javac.code.Flags
|
||||||
import com.sun.tools.javac.code.TypeTag
|
import com.sun.tools.javac.code.TypeTag
|
||||||
import com.sun.tools.javac.file.JavacFileManager
|
import com.sun.tools.javac.file.JavacFileManager
|
||||||
|
import com.sun.tools.javac.parser.Tokens
|
||||||
import com.sun.tools.javac.tree.JCTree
|
import com.sun.tools.javac.tree.JCTree
|
||||||
import com.sun.tools.javac.tree.JCTree.*
|
import com.sun.tools.javac.tree.JCTree.*
|
||||||
import com.sun.tools.javac.tree.TreeMaker
|
import com.sun.tools.javac.tree.TreeMaker
|
||||||
@@ -27,6 +28,7 @@ import org.jetbrains.kotlin.descriptors.*
|
|||||||
import org.jetbrains.kotlin.kapt3.*
|
import org.jetbrains.kotlin.kapt3.*
|
||||||
import org.jetbrains.kotlin.kapt3.javac.KaptTreeMaker
|
import org.jetbrains.kotlin.kapt3.javac.KaptTreeMaker
|
||||||
import org.jetbrains.kotlin.kapt3.javac.KaptJavaFileObject
|
import org.jetbrains.kotlin.kapt3.javac.KaptJavaFileObject
|
||||||
|
import org.jetbrains.kotlin.kapt3.stubs.Kapt3StubUtils.*
|
||||||
import org.jetbrains.kotlin.kapt3.util.*
|
import org.jetbrains.kotlin.kapt3.util.*
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
@@ -69,6 +71,12 @@ class ClassFileToSourceStubConverter(
|
|||||||
"org.jetbrains.annotations.", // Nullable/NotNull, ReadOnly, Mutable
|
"org.jetbrains.annotations.", // Nullable/NotNull, ReadOnly, Mutable
|
||||||
"kotlin.jvm.", "kotlin.Metadata" // Kotlin annotations from runtime
|
"kotlin.jvm.", "kotlin.Metadata" // Kotlin annotations from runtime
|
||||||
)
|
)
|
||||||
|
|
||||||
|
private val JAVA_KEYWORD_FILTER_REGEX = "[a-z]+".toRegex()
|
||||||
|
|
||||||
|
private val JAVA_KEYWORDS = Tokens.TokenKind.values()
|
||||||
|
.filter { JAVA_KEYWORD_FILTER_REGEX.matches(getTokenName(it)) }
|
||||||
|
.mapTo(hashSetOf(), ::getTokenName)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val _bindings = mutableMapOf<String, KaptJavaFileObject>()
|
private val _bindings = mutableMapOf<String, KaptJavaFileObject>()
|
||||||
@@ -210,7 +218,7 @@ class ClassFileToSourceStubConverter(
|
|||||||
|
|
||||||
return treeMaker.ClassDef(
|
return treeMaker.ClassDef(
|
||||||
modifiers,
|
modifiers,
|
||||||
treeMaker.name(simpleName),
|
treeMaker.name(getNonKeywordName(simpleName)),
|
||||||
genericType.typeParameters,
|
genericType.typeParameters,
|
||||||
if (hasSuperClass) genericType.superClass else null,
|
if (hasSuperClass) genericType.superClass else null,
|
||||||
genericType.interfaces,
|
genericType.interfaces,
|
||||||
@@ -222,7 +230,7 @@ class ClassFileToSourceStubConverter(
|
|||||||
val descriptor = kaptContext.origins[field]?.descriptor
|
val descriptor = kaptContext.origins[field]?.descriptor
|
||||||
|
|
||||||
val modifiers = convertModifiers(field.access, ElementKind.FIELD, packageFqName, field.visibleAnnotations, field.invisibleAnnotations)
|
val modifiers = convertModifiers(field.access, ElementKind.FIELD, packageFqName, field.visibleAnnotations, field.invisibleAnnotations)
|
||||||
val name = treeMaker.name(field.name)
|
val name = treeMaker.name(getNonKeywordName(field.name))
|
||||||
val type = Type.getType(field.desc)
|
val type = Type.getType(field.desc)
|
||||||
|
|
||||||
// Enum type must be an identifier (Javac requirement)
|
// Enum type must be an identifier (Javac requirement)
|
||||||
@@ -260,7 +268,7 @@ class ClassFileToSourceStubConverter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val isConstructor = method.name == "<init>"
|
val isConstructor = method.name == "<init>"
|
||||||
val name = treeMaker.name(method.name)
|
val name = treeMaker.name(getNonKeywordName(method.name))
|
||||||
|
|
||||||
val modifiers = convertModifiers(
|
val modifiers = convertModifiers(
|
||||||
if (containingClass.isEnum() && isConstructor)
|
if (containingClass.isEnum() && isConstructor)
|
||||||
@@ -286,7 +294,7 @@ class ClassFileToSourceStubConverter(
|
|||||||
info.visibleAnnotations,
|
info.visibleAnnotations,
|
||||||
info.invisibleAnnotations)
|
info.invisibleAnnotations)
|
||||||
|
|
||||||
val name = treeMaker.name(info.name)
|
val name = treeMaker.name(getNonKeywordName(info.name))
|
||||||
val type = treeMaker.Type(info.type)
|
val type = treeMaker.Type(info.type)
|
||||||
treeMaker.VarDef(modifiers, name, type, null)
|
treeMaker.VarDef(modifiers, name, type, null)
|
||||||
}
|
}
|
||||||
@@ -394,6 +402,12 @@ class ClassFileToSourceStubConverter(
|
|||||||
return ifNonError()
|
return ifNonError()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getNonKeywordName(name: String): String {
|
||||||
|
// In theory, this could lead to member/parameter name clashes, though it's supposed to be extremely rare.
|
||||||
|
if (name in JAVA_KEYWORDS) return '_' + name + '_'
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
|
||||||
private inline fun <T : JCExpression?> getNotAnonymousType(descriptor: DeclarationDescriptor?, f: () -> T): T {
|
private inline fun <T : JCExpression?> getNotAnonymousType(descriptor: DeclarationDescriptor?, f: () -> T): T {
|
||||||
if (descriptor is CallableDescriptor) {
|
if (descriptor is CallableDescriptor) {
|
||||||
val returnTypeDescriptor = descriptor.returnType?.constructor?.declarationDescriptor
|
val returnTypeDescriptor = descriptor.returnType?.constructor?.declarationDescriptor
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2017 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* 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 org.jetbrains.kotlin.kapt3.stubs;
|
||||||
|
|
||||||
|
import com.sun.tools.javac.parser.Tokens;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public class Kapt3StubUtils {
|
||||||
|
@NotNull
|
||||||
|
public static String getTokenName(@NotNull Tokens.TokenKind kind) {
|
||||||
|
// This is a work-around. `name` can't be called from Kotlin, as it clashes with the `name` enum property.
|
||||||
|
String name = kind.name;
|
||||||
|
return (name == null) ? "" : name;
|
||||||
|
}
|
||||||
|
}
|
||||||
+6
@@ -108,6 +108,12 @@ public class ClassFileToSourceStubConverterTestGenerated extends AbstractClassFi
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("javaKeywords.kt")
|
||||||
|
public void testJavaKeywords() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("plugins/kapt3/testData/converter/javaKeywords.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("jvmOverloads.kt")
|
@TestMetadata("jvmOverloads.kt")
|
||||||
public void testJvmOverloads() throws Exception {
|
public void testJvmOverloads() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("plugins/kapt3/testData/converter/jvmOverloads.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("plugins/kapt3/testData/converter/jvmOverloads.kt");
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
class default {
|
||||||
|
lateinit val extends: String
|
||||||
|
fun implements(instanceof: Int) {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
public final class _default_ {
|
||||||
|
public java.lang.String _extends_;
|
||||||
|
|
||||||
|
public final java.lang.String getExtends() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void _implements_(int _instanceof_) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public _default_() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -3,7 +3,7 @@ public final class Outer {
|
|||||||
public final void nonAbstract(java.lang.String s, int i) {
|
public final void nonAbstract(java.lang.String s, int i) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void abstract(java.lang.String p0, int p1);
|
public abstract void _abstract_(java.lang.String p0, int p1);
|
||||||
|
|
||||||
public Outer() {
|
public Outer() {
|
||||||
super();
|
super();
|
||||||
|
|||||||
Reference in New Issue
Block a user