diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirImportOptimizer.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirImportOptimizer.kt index fc082bcb707..84bbd895618 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirImportOptimizer.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirImportOptimizer.kt @@ -21,7 +21,12 @@ import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.psi import org.jetbrains.kotlin.fir.realPsi -import org.jetbrains.kotlin.fir.references.FirNamedReference +import org.jetbrains.kotlin.fir.references.FirErrorNamedReference +import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnresolvedError +import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnresolvedNameError +import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnresolvedReferenceError +import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnresolvedSymbolError +import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnresolvedTypeQualifierError import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol @@ -62,7 +67,9 @@ internal class KtFirImportOptimizer( .map { it.fqName } .toSet() - val referencesEntities = collectReferencedEntities(firFile) + val (usedImports, unresolvedNames) = collectReferencedEntities(firFile) + + val referencesEntities = usedImports .filterNot { (fqName, referencedByNames) -> // when referenced by more than one name, we need to keep the imports with same package fqName.parentOrNull() == file.packageFqName && referencedByNames.size == 1 @@ -82,8 +89,9 @@ internal class KtFirImportOptimizer( val importPath = import.importPath ?: continue val isUsed = when { + importPath.importedName in unresolvedNames -> true !alreadySeenImports.add(importPath) -> false - importPath.isAllUnder -> importPath.fqName in requiredStarImports + importPath.isAllUnder -> unresolvedNames.isNotEmpty() || importPath.fqName in requiredStarImports importPath.fqName in referencesEntities -> importPath.importedName in referencesEntities.getValue(importPath.fqName) else -> false } @@ -96,8 +104,14 @@ internal class KtFirImportOptimizer( return KtImportOptimizerResult(unusedImports) } - private fun collectReferencedEntities(firFile: FirFile): Map> { + private data class ReferencedEntitiesResult( + val usedImports: Map>, + val unresolvedNames: Set, + ) + + private fun collectReferencedEntities(firFile: FirFile): ReferencedEntitiesResult { val usedImports = mutableMapOf>() + val unresolvedNames = mutableSetOf() firFile.accept(object : FirVisitorVoid() { override fun visitElement(element: FirElement) { @@ -128,6 +142,7 @@ internal class KtFirImportOptimizer( override fun visitErrorTypeRef(errorTypeRef: FirErrorTypeRef) { processTypeRef(errorTypeRef) + processErrorTypeRef(errorTypeRef) errorTypeRef.delegatedTypeRef?.accept(this) super.visitErrorTypeRef(errorTypeRef) @@ -148,8 +163,21 @@ internal class KtFirImportOptimizer( super.visitErrorResolvedQualifier(errorResolvedQualifier) } + private fun processErrorNameReference(resolvable: FirResolvable) { + val nameReference = resolvable.calleeReference as? FirErrorNamedReference ?: return + val name = nameReference.unresolvedName ?: return + unresolvedNames += name + } + + private fun processErrorTypeRef(typeRef: FirErrorTypeRef) { + val diagnostic = typeRef.diagnostic as? ConeUnresolvedError ?: return + val name = diagnostic.unresolvedName ?: return + unresolvedNames += name + } + private fun processFunctionCall(functionCall: FirFunctionCall) { if (functionCall.isFullyQualified) return + processErrorNameReference(functionCall) val referencesByName = functionCall.functionReferenceName ?: return val functionSymbol = functionCall.referencedCallableSymbol ?: return @@ -158,6 +186,8 @@ internal class KtFirImportOptimizer( } private fun processImplicitFunctionCall(implicitInvokeCall: FirImplicitInvokeCall) { + processErrorNameReference(implicitInvokeCall) + val functionSymbol = implicitInvokeCall.referencedCallableSymbol ?: return saveCallable(functionSymbol, OperatorNameConventions.INVOKE) @@ -165,6 +195,7 @@ internal class KtFirImportOptimizer( private fun processPropertyAccessExpression(propertyAccessExpression: FirPropertyAccessExpression) { if (propertyAccessExpression.isFullyQualified) return + processErrorNameReference(propertyAccessExpression) val referencedByName = propertyAccessExpression.propertyReferenceName ?: return val propertySymbol = propertyAccessExpression.referencedCallableSymbol ?: return @@ -180,6 +211,7 @@ internal class KtFirImportOptimizer( private fun processCallableReferenceAccess(callableReferenceAccess: FirCallableReferenceAccess) { if (callableReferenceAccess.isFullyQualified) return + processErrorNameReference(callableReferenceAccess) val referencedByName = callableReferenceAccess.callableReferenceName ?: return val resolvedSymbol = callableReferenceAccess.referencedCallableSymbol ?: return @@ -218,10 +250,28 @@ internal class KtFirImportOptimizer( } }) - return usedImports + return ReferencedEntitiesResult(usedImports, unresolvedNames) } } +private val FirErrorNamedReference.unresolvedName: Name? + get() { + val diagnostic = diagnostic as? ConeUnresolvedError ?: return null + return diagnostic.unresolvedName + } + +private val ConeUnresolvedError.unresolvedName: Name? + get() = when (this) { + is ConeUnresolvedNameError -> name + is ConeUnresolvedReferenceError -> name + is ConeUnresolvedSymbolError -> classId.shortClassName + is ConeUnresolvedTypeQualifierError -> { + // we take the first qualifier part because only the first one can be imported + qualifiers.firstOrNull()?.name + } + } + + /** * An actual name by which this callable reference were used. */ diff --git a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/importOptimizer/FirIdeNormalAnalysisSourceModuleAnalysisApiImportOptimizerTestGenerated.java b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/importOptimizer/FirIdeNormalAnalysisSourceModuleAnalysisApiImportOptimizerTestGenerated.java index d5cdf9e4bca..8929458b852 100644 --- a/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/importOptimizer/FirIdeNormalAnalysisSourceModuleAnalysisApiImportOptimizerTestGenerated.java +++ b/analysis/analysis-api-fir/tests-gen/org/jetbrains/kotlin/analysis/api/fir/test/cases/generated/cases/components/importOptimizer/FirIdeNormalAnalysisSourceModuleAnalysisApiImportOptimizerTestGenerated.java @@ -133,12 +133,66 @@ public class FirIdeNormalAnalysisSourceModuleAnalysisApiImportOptimizerTestGener KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors"), Pattern.compile("^([^.]+)\\.kt$"), null, true); } + @Test + @TestMetadata("unresolvedFunction.kt") + public void testUnresolvedFunction() throws Exception { + runTest("analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedFunction.kt"); + } + + @Test + @TestMetadata("unresolvedFunctionStarImport.kt") + public void testUnresolvedFunctionStarImport() throws Exception { + runTest("analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedFunctionStarImport.kt"); + } + + @Test + @TestMetadata("unresolvedProperty.kt") + public void testUnresolvedProperty() throws Exception { + runTest("analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedProperty.kt"); + } + + @Test + @TestMetadata("unresolvedType.kt") + public void testUnresolvedType() throws Exception { + runTest("analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedType.kt"); + } + + @Test + @TestMetadata("unresolvedTypeArgument.kt") + public void testUnresolvedTypeArgument() throws Exception { + runTest("analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedTypeArgument.kt"); + } + + @Test + @TestMetadata("unresolvedTypeQualifier.kt") + public void testUnresolvedTypeQualifier() throws Exception { + runTest("analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedTypeQualifier.kt"); + } + + @Test + @TestMetadata("unresolvedTypeQualifierConstructor.kt") + public void testUnresolvedTypeQualifierConstructor() throws Exception { + runTest("analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedTypeQualifierConstructor.kt"); + } + + @Test + @TestMetadata("unresolvedViaImportAlias.kt") + public void testUnresolvedViaImportAlias() throws Exception { + runTest("analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedViaImportAlias.kt"); + } + @Test @TestMetadata("unusedTypeHiddenByTypeParameter_invalidAsArgument.kt") public void testUnusedTypeHiddenByTypeParameter_invalidAsArgument() throws Exception { runTest("analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unusedTypeHiddenByTypeParameter_invalidAsArgument.kt"); } + @Test + @TestMetadata("unusedUnresolvedImport.kt") + public void testUnusedUnresolvedImport() throws Exception { + runTest("analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unusedUnresolvedImport.kt"); + } + @Test @TestMetadata("usedConstructor_invalidArguments.kt") public void testUsedConstructor_invalidArguments() throws Exception { diff --git a/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/components/importOptimizer/FirStandaloneNormalAnalysisSourceModuleAnalysisApiImportOptimizerTestGenerated.java b/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/components/importOptimizer/FirStandaloneNormalAnalysisSourceModuleAnalysisApiImportOptimizerTestGenerated.java index 157f3bf8fbc..db03c56793c 100644 --- a/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/components/importOptimizer/FirStandaloneNormalAnalysisSourceModuleAnalysisApiImportOptimizerTestGenerated.java +++ b/analysis/analysis-api-standalone/tests-gen/org/jetbrains/kotlin/analysis/api/standalone/fir/test/cases/generated/cases/components/importOptimizer/FirStandaloneNormalAnalysisSourceModuleAnalysisApiImportOptimizerTestGenerated.java @@ -133,12 +133,66 @@ public class FirStandaloneNormalAnalysisSourceModuleAnalysisApiImportOptimizerTe KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors"), Pattern.compile("^([^.]+)\\.kt$"), null, true); } + @Test + @TestMetadata("unresolvedFunction.kt") + public void testUnresolvedFunction() throws Exception { + runTest("analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedFunction.kt"); + } + + @Test + @TestMetadata("unresolvedFunctionStarImport.kt") + public void testUnresolvedFunctionStarImport() throws Exception { + runTest("analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedFunctionStarImport.kt"); + } + + @Test + @TestMetadata("unresolvedProperty.kt") + public void testUnresolvedProperty() throws Exception { + runTest("analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedProperty.kt"); + } + + @Test + @TestMetadata("unresolvedType.kt") + public void testUnresolvedType() throws Exception { + runTest("analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedType.kt"); + } + + @Test + @TestMetadata("unresolvedTypeArgument.kt") + public void testUnresolvedTypeArgument() throws Exception { + runTest("analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedTypeArgument.kt"); + } + + @Test + @TestMetadata("unresolvedTypeQualifier.kt") + public void testUnresolvedTypeQualifier() throws Exception { + runTest("analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedTypeQualifier.kt"); + } + + @Test + @TestMetadata("unresolvedTypeQualifierConstructor.kt") + public void testUnresolvedTypeQualifierConstructor() throws Exception { + runTest("analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedTypeQualifierConstructor.kt"); + } + + @Test + @TestMetadata("unresolvedViaImportAlias.kt") + public void testUnresolvedViaImportAlias() throws Exception { + runTest("analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedViaImportAlias.kt"); + } + @Test @TestMetadata("unusedTypeHiddenByTypeParameter_invalidAsArgument.kt") public void testUnusedTypeHiddenByTypeParameter_invalidAsArgument() throws Exception { runTest("analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unusedTypeHiddenByTypeParameter_invalidAsArgument.kt"); } + @Test + @TestMetadata("unusedUnresolvedImport.kt") + public void testUnusedUnresolvedImport() throws Exception { + runTest("analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unusedUnresolvedImport.kt"); + } + @Test @TestMetadata("usedConstructor_invalidArguments.kt") public void testUsedConstructor_invalidArguments() throws Exception { diff --git a/analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedFunction.imports b/analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedFunction.imports new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedFunction.imports @@ -0,0 +1 @@ + diff --git a/analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedFunction.kt b/analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedFunction.kt new file mode 100644 index 00000000000..3460d1b49a4 --- /dev/null +++ b/analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedFunction.kt @@ -0,0 +1,7 @@ +package m2.second + +import a.b.c.readText + +fun t() { + readText() +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedFunctionStarImport.imports b/analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedFunctionStarImport.imports new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedFunctionStarImport.imports @@ -0,0 +1 @@ + diff --git a/analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedFunctionStarImport.kt b/analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedFunctionStarImport.kt new file mode 100644 index 00000000000..c0212e266f1 --- /dev/null +++ b/analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedFunctionStarImport.kt @@ -0,0 +1,7 @@ +package m2.second + +import a.b.c.* + +fun t() { + readText() +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedProperty.imports b/analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedProperty.imports new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedProperty.imports @@ -0,0 +1 @@ + diff --git a/analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedProperty.kt b/analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedProperty.kt new file mode 100644 index 00000000000..e7778ea04b1 --- /dev/null +++ b/analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedProperty.kt @@ -0,0 +1,7 @@ +package m2.second + +import a.b.c.prop + +fun t() { + prop +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedType.imports b/analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedType.imports new file mode 100644 index 00000000000..e69de29bb2d diff --git a/analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedType.kt b/analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedType.kt new file mode 100644 index 00000000000..2649ee2a1df --- /dev/null +++ b/analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedType.kt @@ -0,0 +1,7 @@ +package m2.second + +import a.b.c.X + +fun t(): X { + +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedTypeArgument.imports b/analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedTypeArgument.imports new file mode 100644 index 00000000000..e69de29bb2d diff --git a/analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedTypeArgument.kt b/analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedTypeArgument.kt new file mode 100644 index 00000000000..15ebe90eb09 --- /dev/null +++ b/analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedTypeArgument.kt @@ -0,0 +1,7 @@ +package m2.second + +import a.b.c.X + +fun t(): List { + +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedTypeQualifier.imports b/analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedTypeQualifier.imports new file mode 100644 index 00000000000..e69de29bb2d diff --git a/analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedTypeQualifier.kt b/analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedTypeQualifier.kt new file mode 100644 index 00000000000..1d30e9173e1 --- /dev/null +++ b/analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedTypeQualifier.kt @@ -0,0 +1,8 @@ +package m2.second + +import a.b.c.X +import a.b.c.C + +fun t() { + X.C +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedTypeQualifierConstructor.imports b/analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedTypeQualifierConstructor.imports new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedTypeQualifierConstructor.imports @@ -0,0 +1 @@ + diff --git a/analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedTypeQualifierConstructor.kt b/analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedTypeQualifierConstructor.kt new file mode 100644 index 00000000000..c86dba9af4c --- /dev/null +++ b/analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedTypeQualifierConstructor.kt @@ -0,0 +1,8 @@ +package m2.second + +import a.b.c.X +import a.b.c.C + +fun t() { + X.C() +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedViaImportAlias.imports b/analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedViaImportAlias.imports new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedViaImportAlias.imports @@ -0,0 +1 @@ + diff --git a/analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedViaImportAlias.kt b/analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedViaImportAlias.kt new file mode 100644 index 00000000000..a2b18ab3db9 --- /dev/null +++ b/analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unresolvedViaImportAlias.kt @@ -0,0 +1,7 @@ +package m2.second + +import a.b.c.prop as prp + +fun t() { + prp +} \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unusedUnresolvedImport.imports b/analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unusedUnresolvedImport.imports new file mode 100644 index 00000000000..ae5c3fa7839 --- /dev/null +++ b/analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unusedUnresolvedImport.imports @@ -0,0 +1 @@ +a.a.Foo \ No newline at end of file diff --git a/analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unusedUnresolvedImport.kt b/analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unusedUnresolvedImport.kt new file mode 100644 index 00000000000..21b722fd81a --- /dev/null +++ b/analysis/analysis-api/testData/components/importOptimizer/analyseImports/referencesWithErrors/unusedUnresolvedImport.kt @@ -0,0 +1,9 @@ +package one + +import a.c.c.D +import a.a.Foo +import a.star.* + +fun t() { + D() +} \ No newline at end of file