Kapt: Support import directive with aliases in "correctErrorTypes" mode (KT-21358)

This commit is contained in:
Yan Zhulanow
2017-11-21 23:29:13 +09:00
parent c7645bcf03
commit 00bb38fbb1
5 changed files with 221 additions and 17 deletions
@@ -204,16 +204,12 @@ class ClassFileToSourceStubConverter(
for (importDirective in file.importDirectives) {
// Qualified name should be valid Java fq-name
val importedFqName = importDirective.importedFqName ?: continue
val importedFqName = importDirective.importedFqName?.takeIf { it.pathSegments().size > 1 } ?: continue
if (!isValidQualifiedName(importedFqName)) continue
val shortName = importedFqName.shortName()
if (shortName.asString() == classDeclaration.simpleName.toString()) continue
// If alias is specified, it also should be valid Java name
val aliasName = importDirective.aliasName
if (aliasName != null /*TODO support aliases */ /*&& getValidIdentifierName(aliasName) == null*/) continue
val importedReference = getReferenceExpression(importDirective.importedReference)
?.let { kaptContext.bindingContext[BindingContext.REFERENCE_TARGET, it] }
@@ -231,12 +227,6 @@ class ClassFileToSourceStubConverter(
return JavacList.from(imports)
}
private tailrec fun getReferenceExpression(expression: KtExpression?): KtReferenceExpression? = when (expression) {
is KtReferenceExpression -> expression
is KtQualifiedExpression -> getReferenceExpression(expression.selectorExpression)
else -> null
}
/**
* Returns false for the inner classes or if the origin for the class was not found.
*/
@@ -637,9 +627,10 @@ class ClassFileToSourceStubConverter(
if (type?.containsErrorTypes() == true) {
val typeFromSource = ktTypeProvider()?.typeElement
if (typeFromSource != null) {
val ktFile = typeFromSource?.containingKtFile
if (ktFile != null) {
@Suppress("UNCHECKED_CAST")
return ErrorTypeCorrector(this, kind).convert(typeFromSource, emptyMap()) as T
return ErrorTypeCorrector(this, kind, ktFile).convert(typeFromSource, emptyMap()) as T
}
}
@@ -917,6 +908,12 @@ private fun Any?.isOfPrimiviteType(): Boolean = when(this) {
private val ClassDescriptor.isNested: Boolean
get() = containingDeclaration is ClassDescriptor
internal tailrec fun getReferenceExpression(expression: KtExpression?): KtReferenceExpression? = when (expression) {
is KtReferenceExpression -> expression
is KtQualifiedExpression -> getReferenceExpression(expression.selectorExpression)
else -> null
}
internal fun getAnnotationValue(fqName: FqName, mods: JCTree.JCModifiers?): String? {
val annotations = mods?.annotations ?: return null
@@ -37,13 +37,30 @@ private typealias SubstitutionMap = Map<String, Pair<KtTypeParameter, KtTypeProj
class ErrorTypeCorrector(
private val converter: ClassFileToSourceStubConverter,
private val typeKind: TypeKind
private val typeKind: TypeKind,
file: KtFile
) {
private val defaultType = converter.treeMaker.FqName(Object::class.java.name)
private val bindingContext get() = converter.kaptContext.bindingContext
private val treeMaker get() = converter.treeMaker
private val aliasedImports = mutableMapOf<String, JCTree.JCExpression>().apply {
for (importDirective in file.importDirectives) {
if (importDirective.isAllUnder) continue
val aliasName = importDirective.aliasName ?: continue
val importedFqName = importDirective.importedFqName ?: continue
val importedReference = getReferenceExpression(importDirective.importedReference)
?.let { bindingContext[BindingContext.REFERENCE_TARGET, it] }
if (importedReference is CallableDescriptor) continue
this[aliasName] = treeMaker.FqName(importedFqName)
}
}
enum class TypeKind {
RETURN_TYPE, METHOD_PARAMETER_TYPE
}
@@ -85,9 +102,13 @@ class ErrorTypeCorrector(
val referencedName = type.referencedName ?: return defaultType
val qualifier = type.qualifier
if (qualifier == null && referencedName in substitutions) {
val (typeParameter, projection) = substitutions.getValue(referencedName)
return convertTypeProjection(projection, typeParameter.variance, emptyMap())
if (qualifier == null) {
if (referencedName in substitutions) {
val (typeParameter, projection) = substitutions.getValue(referencedName)
return convertTypeProjection(projection, typeParameter.variance, emptyMap())
}
aliasedImports[referencedName]?.let { return it }
}
baseExpression = when {
@@ -155,6 +176,10 @@ class ErrorTypeCorrector(
}
}
private fun convertTypeProjection() {
}
private fun convertFunctionType(type: KtFunctionType, substitutions: SubstitutionMap): JCTree.JCExpression {
val receiverType = type.receiverTypeReference
var parameterTypes = mapJList(type.parameters) { convert(it.typeReference, substitutions) }
@@ -44,6 +44,12 @@ public class ClassFileToSourceStubConverterTestGenerated extends AbstractClassFi
doTest(fileName);
}
@TestMetadata("aliasedImports.kt")
public void testAliasedImports() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("plugins/kapt3/kapt3-compiler/testData/converter/aliasedImports.kt");
doTest(fileName);
}
public void testAllFilesPresentInConverter() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("plugins/kapt3/kapt3-compiler/testData/converter"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
@@ -0,0 +1,26 @@
// CORRECT_ERROR_TYPES
// NO_VALIDATION
@file:Suppress("ENUM_ENTRY_AS_TYPE", "UNRESOLVED_REFERENCE")
import java.util.Date as MyDate
import java.util.concurrent.TimeUnit as MyTimeUnit
import java.util.concurrent.TimeUnit.MICROSECONDS as MyMicroseconds
import a.b.ABC as MyABC
import bcd as MyBCD
class Test {
lateinit var date: MyDate
lateinit var timeUnit: MyTimeUnit
lateinit var microseconds: MyMicroseconds
lateinit var abc: MyABC
lateinit var bcd: MyBCD
class MyDate {
lateinit var date2: MyDate
}
}
class Test2 {
lateinit var date: MyDate
}
@@ -0,0 +1,150 @@
import java.util.Date;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeUnit.MICROSECONDS;
import a.b.ABC;
@kotlin.Metadata()
@kapt.internal.KaptMetadata()
public final class Test {
@org.jetbrains.annotations.NotNull()
public Test.MyDate date;
@org.jetbrains.annotations.NotNull()
public java.util.concurrent.TimeUnit timeUnit;
@org.jetbrains.annotations.NotNull()
public java.util.concurrent.TimeUnit microseconds;
@org.jetbrains.annotations.NotNull()
public a.b.ABC abc;
@org.jetbrains.annotations.NotNull()
public bcd bcd;
@org.jetbrains.annotations.NotNull()
@kapt.internal.KaptSignature("getDate()LTest$MyDate;")
public final Test.MyDate getDate() {
return null;
}
@kapt.internal.KaptSignature("setDate(LTest$MyDate;)V")
public final void setDate(@org.jetbrains.annotations.NotNull()
Test.MyDate p0) {
}
@org.jetbrains.annotations.NotNull()
@kapt.internal.KaptSignature("getTimeUnit()Ljava/util/concurrent/TimeUnit;")
public final java.util.concurrent.TimeUnit getTimeUnit() {
return null;
}
@kapt.internal.KaptSignature("setTimeUnit(Ljava/util/concurrent/TimeUnit;)V")
public final void setTimeUnit(@org.jetbrains.annotations.NotNull()
java.util.concurrent.TimeUnit p0) {
}
@org.jetbrains.annotations.NotNull()
@kapt.internal.KaptSignature("getMicroseconds()Ljava/util/concurrent/TimeUnit;")
public final java.util.concurrent.TimeUnit getMicroseconds() {
return null;
}
@kapt.internal.KaptSignature("setMicroseconds(Ljava/util/concurrent/TimeUnit;)V")
public final void setMicroseconds(@org.jetbrains.annotations.NotNull()
java.util.concurrent.TimeUnit p0) {
}
@org.jetbrains.annotations.NotNull()
@kapt.internal.KaptSignature("getAbc()Lerror/NonExistentClass;")
public final a.b.ABC getAbc() {
return null;
}
@kapt.internal.KaptSignature("setAbc(Lerror/NonExistentClass;)V")
public final void setAbc(@org.jetbrains.annotations.NotNull()
a.b.ABC p0) {
}
@org.jetbrains.annotations.NotNull()
@kapt.internal.KaptSignature("getBcd()Lerror/NonExistentClass;")
public final bcd getBcd() {
return null;
}
@kapt.internal.KaptSignature("setBcd(Lerror/NonExistentClass;)V")
public final void setBcd(@org.jetbrains.annotations.NotNull()
bcd p0) {
}
@kapt.internal.KaptSignature("<init>()V")
public Test() {
super();
}
@kotlin.Metadata()
public static final class MyDate {
@org.jetbrains.annotations.NotNull()
public Test.MyDate date2;
@org.jetbrains.annotations.NotNull()
@kapt.internal.KaptSignature("getDate2()LTest$MyDate;")
public final Test.MyDate getDate2() {
return null;
}
@kapt.internal.KaptSignature("setDate2(LTest$MyDate;)V")
public final void setDate2(@org.jetbrains.annotations.NotNull()
Test.MyDate p0) {
}
@kapt.internal.KaptSignature("<init>()V")
public MyDate() {
super();
}
}
}
////////////////////
import java.util.Date;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeUnit.MICROSECONDS;
import a.b.ABC;
@kotlin.Metadata()
@kapt.internal.KaptMetadata()
public final class Test2 {
@org.jetbrains.annotations.NotNull()
public java.util.Date date;
@org.jetbrains.annotations.NotNull()
@kapt.internal.KaptSignature("getDate()Ljava/util/Date;")
public final java.util.Date getDate() {
return null;
}
@kapt.internal.KaptSignature("setDate(Ljava/util/Date;)V")
public final void setDate(@org.jetbrains.annotations.NotNull()
java.util.Date p0) {
}
@kapt.internal.KaptSignature("<init>()V")
public Test2() {
super();
}
}
////////////////////
package kapt.internal;
public @interface KaptMetadata {
public java.lang.String value();
}
////////////////////
package kapt.internal;
public @interface KaptSignature {
public java.lang.String value();
}