From 00bb38fbb1b06ff80ef0ea429b598f25d8d01f65 Mon Sep 17 00:00:00 2001 From: Yan Zhulanow Date: Tue, 21 Nov 2017 23:29:13 +0900 Subject: [PATCH] Kapt: Support import directive with aliases in "correctErrorTypes" mode (KT-21358) --- .../stubs/ClassFileToSourceStubConverter.kt | 23 ++- .../kotlin/kapt3/stubs/ErrorTypeCorrector.kt | 33 +++- ...ileToSourceStubConverterTestGenerated.java | 6 + .../testData/converter/aliasedImports.kt | 26 +++ .../testData/converter/aliasedImports.txt | 150 ++++++++++++++++++ 5 files changed, 221 insertions(+), 17 deletions(-) create mode 100644 plugins/kapt3/kapt3-compiler/testData/converter/aliasedImports.kt create mode 100644 plugins/kapt3/kapt3-compiler/testData/converter/aliasedImports.txt diff --git a/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/ClassFileToSourceStubConverter.kt b/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/ClassFileToSourceStubConverter.kt index 5df1d43970d..6bfba011076 100644 --- a/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/ClassFileToSourceStubConverter.kt +++ b/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/ClassFileToSourceStubConverter.kt @@ -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 diff --git a/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/ErrorTypeCorrector.kt b/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/ErrorTypeCorrector.kt index ef417b50baa..b34a07ce1c1 100644 --- a/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/ErrorTypeCorrector.kt +++ b/plugins/kapt3/kapt3-compiler/src/org/jetbrains/kotlin/kapt3/stubs/ErrorTypeCorrector.kt @@ -37,13 +37,30 @@ private typealias SubstitutionMap = Map().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) } diff --git a/plugins/kapt3/kapt3-compiler/test/org/jetbrains/kotlin/kapt3/test/ClassFileToSourceStubConverterTestGenerated.java b/plugins/kapt3/kapt3-compiler/test/org/jetbrains/kotlin/kapt3/test/ClassFileToSourceStubConverterTestGenerated.java index dafd5274abb..e681e452897 100644 --- a/plugins/kapt3/kapt3-compiler/test/org/jetbrains/kotlin/kapt3/test/ClassFileToSourceStubConverterTestGenerated.java +++ b/plugins/kapt3/kapt3-compiler/test/org/jetbrains/kotlin/kapt3/test/ClassFileToSourceStubConverterTestGenerated.java @@ -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); } diff --git a/plugins/kapt3/kapt3-compiler/testData/converter/aliasedImports.kt b/plugins/kapt3/kapt3-compiler/testData/converter/aliasedImports.kt new file mode 100644 index 00000000000..289773391f0 --- /dev/null +++ b/plugins/kapt3/kapt3-compiler/testData/converter/aliasedImports.kt @@ -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 +} \ No newline at end of file diff --git a/plugins/kapt3/kapt3-compiler/testData/converter/aliasedImports.txt b/plugins/kapt3/kapt3-compiler/testData/converter/aliasedImports.txt new file mode 100644 index 00000000000..62e3e5c528f --- /dev/null +++ b/plugins/kapt3/kapt3-compiler/testData/converter/aliasedImports.txt @@ -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("()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("()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("()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(); +}