Changed priority for default imports + default imports include all built-ins explicitly for java module

#KT-4374 Fixed
This commit is contained in:
Valentin Kipyatkov
2015-01-19 19:17:23 +03:00
parent ae9ebbec7d
commit b9d47ffe7a
14 changed files with 76 additions and 86 deletions
@@ -17,7 +17,6 @@
package org.jetbrains.kotlin.resolve.jvm; package org.jetbrains.kotlin.resolve.jvm;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableList;
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiFile; import com.intellij.psi.PsiFile;
import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.GlobalSearchScope;
@@ -26,16 +25,19 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.analyzer.AnalysisResult; import org.jetbrains.kotlin.analyzer.AnalysisResult;
import org.jetbrains.kotlin.builtins.KotlinBuiltIns; import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
import org.jetbrains.kotlin.context.GlobalContext; import org.jetbrains.kotlin.context.GlobalContext;
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
import org.jetbrains.kotlin.descriptors.PackageFragmentProvider; import org.jetbrains.kotlin.descriptors.PackageFragmentProvider;
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl; import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl;
import org.jetbrains.kotlin.di.InjectorForTopDownAnalyzerForJvm; import org.jetbrains.kotlin.di.InjectorForTopDownAnalyzerForJvm;
import org.jetbrains.kotlin.load.kotlin.incremental.IncrementalPackageFragmentProvider; import org.jetbrains.kotlin.load.kotlin.incremental.IncrementalPackageFragmentProvider;
import org.jetbrains.kotlin.load.kotlin.incremental.cache.IncrementalCache; import org.jetbrains.kotlin.load.kotlin.incremental.cache.IncrementalCache;
import org.jetbrains.kotlin.load.kotlin.incremental.cache.IncrementalCacheProvider; import org.jetbrains.kotlin.load.kotlin.incremental.cache.IncrementalCacheProvider;
import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.name.Name;
import org.jetbrains.kotlin.platform.JavaToKotlinClassMap; import org.jetbrains.kotlin.platform.JavaToKotlinClassMap;
import org.jetbrains.kotlin.psi.JetFile; import org.jetbrains.kotlin.psi.JetFile;
import org.jetbrains.kotlin.resolve.BindingTrace; import org.jetbrains.kotlin.resolve.BindingTrace;
import org.jetbrains.kotlin.resolve.DescriptorUtils;
import org.jetbrains.kotlin.resolve.ImportPath; import org.jetbrains.kotlin.resolve.ImportPath;
import org.jetbrains.kotlin.resolve.TopDownAnalysisParameters; import org.jetbrains.kotlin.resolve.TopDownAnalysisParameters;
import org.jetbrains.kotlin.resolve.lazy.declarations.FileBasedDeclarationProviderFactory; import org.jetbrains.kotlin.resolve.lazy.declarations.FileBasedDeclarationProviderFactory;
@@ -48,12 +50,23 @@ public enum TopDownAnalyzerFacadeForJVM {
INSTANCE; INSTANCE;
public static final List<ImportPath> DEFAULT_IMPORTS = ImmutableList.of( public static final List<ImportPath> DEFAULT_IMPORTS = buildDefaultImports();
new ImportPath("java.lang.*"),
new ImportPath("kotlin.*"), private static List<ImportPath> buildDefaultImports() {
new ImportPath("kotlin.jvm.*"), List<ImportPath> list = new ArrayList<ImportPath>();
new ImportPath("kotlin.io.*") list.add(new ImportPath("java.lang.*"));
); list.add(new ImportPath("kotlin.*"));
list.add(new ImportPath("kotlin.jvm.*"));
list.add(new ImportPath("kotlin.io.*"));
// all classes from package "kotlin" mapped to java classes are imported explicitly so that they take priority over classes from java.lang
for (ClassDescriptor descriptor : JavaToKotlinClassMap.INSTANCE.allKotlinClasses()) {
FqName fqName = DescriptorUtils.getFqNameSafe(descriptor);
if (fqName.parent().equals(new FqName("kotlin"))) {
list.add(new ImportPath(fqName, false));
}
}
return list;
}
private TopDownAnalyzerFacadeForJVM() { private TopDownAnalyzerFacadeForJVM() {
} }
@@ -26,14 +26,13 @@ import java.util.ArrayList
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.utils.Printer import org.jetbrains.kotlin.utils.Printer
public class Importer(private val platformToKotlinClassMap: PlatformToKotlinClassMap) { public class Importer {
private val allUnderImportScopes = ArrayList<JetScope>() private val allUnderImportScopes = ArrayList<JetScope>()
private val explicitImports = ArrayList<Pair<DeclarationDescriptor, Name>>() private val explicitImports = ArrayList<Pair<DeclarationDescriptor, Name>>()
public fun addAllUnderImport(descriptor: DeclarationDescriptor) { public fun addAllUnderImport(descriptor: DeclarationDescriptor) {
if (descriptor is PackageViewDescriptor) { if (descriptor is PackageViewDescriptor) {
val scope = NoSubpackagesInPackageScope(descriptor) allUnderImportScopes.add(NoSubpackagesInPackageScope(descriptor))
allUnderImportScopes.add(createFilteringScope(scope, descriptor, platformToKotlinClassMap))
} }
else if (descriptor is ClassDescriptor && descriptor.getKind() != ClassKind.OBJECT) { else if (descriptor is ClassDescriptor && descriptor.getKind() != ClassKind.OBJECT) {
allUnderImportScopes.add(descriptor.getStaticScope()) allUnderImportScopes.add(descriptor.getStaticScope())
@@ -45,12 +44,6 @@ public class Importer(private val platformToKotlinClassMap: PlatformToKotlinClas
} }
} }
private fun createFilteringScope(scope: JetScope, descriptor: PackageViewDescriptor, platformToKotlinClassMap: PlatformToKotlinClassMap): JetScope {
val kotlinAnalogsForClassesInside = platformToKotlinClassMap.mapPlatformClassesInside(descriptor)
if (kotlinAnalogsForClassesInside.isEmpty()) return scope
return FilteringScope(scope) { descriptor -> kotlinAnalogsForClassesInside.all { it.getName() != descriptor.getName() } }
}
public fun addAliasImport(descriptor: DeclarationDescriptor, aliasName: Name) { public fun addAliasImport(descriptor: DeclarationDescriptor, aliasName: Name) {
explicitImports.add(descriptor to aliasName) explicitImports.add(descriptor to aliasName)
} }
@@ -99,7 +99,7 @@ public class ImportsResolver {
) { ) {
@NotNull JetScope rootScope = JetModuleUtil.getSubpackagesOfRootScope(module); @NotNull JetScope rootScope = JetModuleUtil.getSubpackagesOfRootScope(module);
Importer importer = new Importer(module.getPlatformToKotlinClassMap()); Importer importer = new Importer();
if (lookupMode == LookupMode.EVERYTHING) { if (lookupMode == LookupMode.EVERYTHING) {
fileScope.clearImports(); fileScope.clearImports();
} }
@@ -40,7 +40,7 @@ class LazyFileScope private(
debugName: String debugName: String
) : ChainedScope(containingDeclaration, ) : ChainedScope(containingDeclaration,
debugName, debugName,
*(listOf(aliasImportsScope, defaultAliasImportsScope, currentPackageMembersScope, rootPackagesScope, allUnderImportsScope, defaultAllUnderImportsScope) + additionalScopes).copyToArray()) { *(listOf(aliasImportsScope, currentPackageMembersScope, rootPackagesScope, defaultAliasImportsScope, defaultAllUnderImportsScope, allUnderImportsScope) + additionalScopes).copyToArray()) {
public fun forceResolveAllImports() { public fun forceResolveAllImports() {
aliasImportsScope.forceResolveAllContents() aliasImportsScope.forceResolveAllContents()
@@ -98,7 +98,7 @@ class LazyImportScope(
val directiveImportScope = WritableScopeImpl(JetScope.Empty, containingDeclaration, RedeclarationHandler.DO_NOTHING, "Scope for import '" + directive.getDebugText() + "' resolve in " + toString()) val directiveImportScope = WritableScopeImpl(JetScope.Empty, containingDeclaration, RedeclarationHandler.DO_NOTHING, "Scope for import '" + directive.getDebugText() + "' resolve in " + toString())
directiveImportScope.changeLockLevel(WritableScope.LockLevel.BOTH) directiveImportScope.changeLockLevel(WritableScope.LockLevel.BOTH)
val importer = Importer(resolveSession.getModuleDescriptor().platformToKotlinClassMap) val importer = Importer()
directiveUnderResolve = directive directiveUnderResolve = directive
val descriptors: Collection<DeclarationDescriptor> val descriptors: Collection<DeclarationDescriptor>
@@ -0,0 +1,6 @@
import java.lang.reflect.*
import <!PLATFORM_CLASS_MAPPED_TO_KOTLIN!>java.util.List<!>
fun foo(
<!UNUSED_PARAMETER!>p1<!>: Array<String> /* should be resolved to kotlin.Array */,
<!UNUSED_PARAMETER!>p2<!>: <!PLATFORM_CLASS_MAPPED_TO_KOTLIN!>List<String><!> /* should be resolved to java.util.List */) { }
@@ -0,0 +1,3 @@
package
internal fun foo(/*0*/ p1: kotlin.Array<kotlin.String>, /*1*/ p2: java.util.List<kotlin.String>): kotlin.Unit
@@ -4,8 +4,8 @@ package test
import testing.custom.* import testing.custom.*
// Non default import has priority over default one. No conflicts are expected. // Default import has priority over on-demand ones. No conflicts are expected.
val a1: `custom`List<Int>? = null val a1: `kotlin::List`List<Int>? = null
//FILE:javaUtilImport.kt //FILE:javaUtilImport.kt
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
@@ -13,7 +13,7 @@ package test
import java.util.* import java.util.*
// Mapped declarations are dropped from on-demand imports. // Default imports take over import-on-demand
// TODO: Fix for lazy resolve test // TODO: Fix for lazy resolve test
// val a2: 'kotlin::List'List<Int>? = null // val a2: 'kotlin::List'List<Int>? = null
@@ -24,8 +24,8 @@ package test
import testing.custom.* import testing.custom.*
import java.util.* import java.util.*
// Mapped declarations are dropped from on-demand "java.util" import. So no conflicts are expected. // Default import has priority over on-demand ones. No conflicts are expected.
val a3: `custom`List<Int>? = null val a3: `kotlin::List`List<Int>? = null
//FILE:singleClassImportFromJavaUtil.kt //FILE:singleClassImportFromJavaUtil.kt
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
+3 -3
View File
@@ -29,9 +29,9 @@ class WithPredicate() {
val p : Boolean val p : Boolean
} }
open class List<E>() open class InvList<E>()
open class AbstractList<E> : List<E?> open class AbstractList<E> : InvList<E?>
open class ArrayList<E>() : Any, AbstractList<E?>, List<E?> open class ArrayList<E>() : Any, AbstractList<E?>, InvList<E?>
fun f() : Unit {} fun f() : Unit {}
fun f(a : Int) : Int {a} fun f(a : Int) : Int {a}
@@ -4745,6 +4745,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
doTest(fileName); doTest(fileName);
} }
@TestMetadata("DefaultImportsPriority.kt")
public void testDefaultImportsPriority() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/imports/DefaultImportsPriority.kt");
doTest(fileName);
}
@TestMetadata("DontImportRootScope.kt") @TestMetadata("DontImportRootScope.kt")
public void testDontImportRootScope() throws Exception { public void testDontImportRootScope() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/imports/DontImportRootScope.kt"); String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/imports/DontImportRootScope.kt");
@@ -304,7 +304,7 @@ public class JetTypeCheckerTest extends JetLiteFixture {
assertSubtype("Derived_T<Int>", "Base_T<in Int>"); assertSubtype("Derived_T<Int>", "Base_T<in Int>");
assertSubtype("MDerived_T<Int>", "Base_T<in Int>"); assertSubtype("MDerived_T<Int>", "Base_T<in Int>");
assertSubtype("ArrayList<Int>", "List<in Int>"); assertSubtype("ArrayList<Int>", "InvList<in Int>");
// assertSubtype("java.lang.Integer", "java.lang.Comparable<java.lang.Integer>?"); // assertSubtype("java.lang.Integer", "java.lang.Comparable<java.lang.Integer>?");
} }
@@ -596,7 +596,14 @@ public class JetTypeCheckerTest extends JetLiteFixture {
InjectorForJavaDescriptorResolver injector = InjectorForJavaDescriptorResolverUtil.create(getProject(), trace, true); InjectorForJavaDescriptorResolver injector = InjectorForJavaDescriptorResolverUtil.create(getProject(), trace, true);
ModuleDescriptor module = injector.getModule(); ModuleDescriptor module = injector.getModule();
for (ImportPath defaultImport : module.getDefaultImports()) { for (ImportPath defaultImport : module.getDefaultImports()) {
writableScope.importScope(module.getPackage(defaultImport.fqnPart()).getMemberScope()); FqName fqName = defaultImport.fqnPart();
if (defaultImport.isAllUnder()) {
writableScope.importScope(module.getPackage(fqName).getMemberScope());
}
else {
writableScope.addClassifierAlias(defaultImport.getImportedName(),
module.getPackage(fqName.parent()).getMemberScope().getClassifier(fqName.shortName()));
}
} }
writableScope.importScope(module.getPackage(FqName.ROOT).getMemberScope()); writableScope.importScope(module.getPackage(FqName.ROOT).getMemberScope());
writableScope.changeLockLevel(WritableScope.LockLevel.BOTH); writableScope.changeLockLevel(WritableScope.LockLevel.BOTH);
@@ -36,8 +36,9 @@ public class JavaToKotlinClassMap extends JavaToKotlinClassMapBuilder implements
private final Map<FqName, ClassDescriptor> classDescriptorMap = new HashMap<FqName, ClassDescriptor>(); private final Map<FqName, ClassDescriptor> classDescriptorMap = new HashMap<FqName, ClassDescriptor>();
private final Map<FqName, ClassDescriptor> classDescriptorMapForCovariantPositions = new HashMap<FqName, ClassDescriptor>(); private final Map<FqName, ClassDescriptor> classDescriptorMapForCovariantPositions = new HashMap<FqName, ClassDescriptor>();
private final Map<String, JetType> primitiveTypesMap = new HashMap<String, JetType>(); private final Map<String, JetType> primitiveTypesMap = new LinkedHashMap<String, JetType>();
private final Map<FqName, Collection<ClassDescriptor>> packagesWithMappedClasses = new HashMap<FqName, Collection<ClassDescriptor>>(); private final Map<FqName, Collection<ClassDescriptor>> packagesWithMappedClasses = new HashMap<FqName, Collection<ClassDescriptor>>();
private final Set<ClassDescriptor> allKotlinClasses = new LinkedHashSet<ClassDescriptor>();
private JavaToKotlinClassMap() { private JavaToKotlinClassMap() {
init(); init();
@@ -57,6 +58,10 @@ public class JavaToKotlinClassMap extends JavaToKotlinClassMapBuilder implements
primitiveTypesMap.put(wrapperFqName.asString(), builtIns.getNullablePrimitiveJetType(primitiveType)); primitiveTypesMap.put(wrapperFqName.asString(), builtIns.getNullablePrimitiveJetType(primitiveType));
} }
primitiveTypesMap.put("void", KotlinBuiltIns.getInstance().getUnitType()); primitiveTypesMap.put("void", KotlinBuiltIns.getInstance().getUnitType());
for (JetType type : primitiveTypesMap.values()) {
allKotlinClasses.add((ClassDescriptor)type.getConstructor().getDeclarationDescriptor());
}
} }
@Nullable @Nullable
@@ -119,6 +124,8 @@ public class JavaToKotlinClassMap extends JavaToKotlinClassMapBuilder implements
packagesWithMappedClasses.put(packageFqName, classesInPackage); packagesWithMappedClasses.put(packageFqName, classesInPackage);
} }
classesInPackage.add(kotlinDescriptor); classesInPackage.add(kotlinDescriptor);
allKotlinClasses.add(kotlinDescriptor);
} }
@NotNull @NotNull
@@ -155,4 +162,9 @@ public class JavaToKotlinClassMap extends JavaToKotlinClassMapBuilder implements
Collection<ClassDescriptor> result = packagesWithMappedClasses.get(fqName.toSafe()); Collection<ClassDescriptor> result = packagesWithMappedClasses.get(fqName.toSafe());
return result == null ? Collections.<ClassDescriptor>emptySet() : Collections.unmodifiableCollection(result); return result == null ? Collections.<ClassDescriptor>emptySet() : Collections.unmodifiableCollection(result);
} }
@NotNull
public Set<ClassDescriptor> allKotlinClasses() {
return allKotlinClasses;
}
} }
@@ -135,8 +135,6 @@ public class KotlinBuiltIns {
for (PrimitiveType primitive : PrimitiveType.values()) { for (PrimitiveType primitive : PrimitiveType.values()) {
makePrimitive(primitive); makePrimitive(primitive);
} }
computeNonPhysicalClasses();
} }
private void makePrimitive(@NotNull PrimitiveType primitiveType) { private void makePrimitive(@NotNull PrimitiveType primitiveType) {
@@ -476,57 +474,6 @@ public class KotlinBuiltIns {
return getBuiltInClassByName("MutableListIterator"); return getBuiltInClassByName("MutableListIterator");
} }
/**
* Classes that only exist for the Kotlin compiler: they are erased at runtime.
* As a consequence they, for example, shouldn't be referred to by other languages
* (e.g. Java).
*/
@NotNull
public Set<ClassDescriptor> getNonPhysicalClasses() {
return Collections.unmodifiableSet(nonPhysicalClasses);
}
private void computeNonPhysicalClasses() {
nonPhysicalClasses.addAll(Arrays.asList(
getAny(),
getNothing(),
getNumber(),
getString(),
getCharSequence(),
getThrowable(),
getIterator(),
getIterable(),
getCollection(),
getList(),
getListIterator(),
getSet(),
getMap(),
getMapEntry(),
getMutableIterator(),
getMutableIterable(),
getMutableCollection(),
getMutableList(),
getMutableListIterator(),
getMutableSet(),
getMutableMap(),
getMutableMapEntry(),
getDataClassAnnotation(),
getAnnotation(),
getComparable(),
getEnum(),
getArray()
));
for (PrimitiveType primitiveType : values()) {
nonPhysicalClasses.add(getPrimitiveClassDescriptor(primitiveType));
nonPhysicalClasses.add(getPrimitiveArrayClassDescriptor(primitiveType));
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// GET TYPE // GET TYPE
@@ -20,7 +20,6 @@ import com.intellij.codeInsight.completion.*
import org.jetbrains.kotlin.asJava.KotlinLightClass import org.jetbrains.kotlin.asJava.KotlinLightClass
import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.psi.JetFile import org.jetbrains.kotlin.psi.JetFile
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.idea.project.ProjectStructureUtil import org.jetbrains.kotlin.idea.project.ProjectStructureUtil
import org.jetbrains.kotlin.idea.caches.KotlinIndicesHelper import org.jetbrains.kotlin.idea.caches.KotlinIndicesHelper
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
@@ -28,6 +27,8 @@ import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.idea.caches.resolve.ResolutionFacade import org.jetbrains.kotlin.idea.caches.resolve.ResolutionFacade
import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.platform.JavaToKotlinClassMap
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
class AllClassesCompletion(val parameters: CompletionParameters, class AllClassesCompletion(val parameters: CompletionParameters,
val lookupElementFactory: LookupElementFactory, val lookupElementFactory: LookupElementFactory,
@@ -39,8 +40,10 @@ class AllClassesCompletion(val parameters: CompletionParameters,
val kindFilter: (ClassKind) -> Boolean, val kindFilter: (ClassKind) -> Boolean,
val visibilityFilter: (DeclarationDescriptor) -> Boolean) { val visibilityFilter: (DeclarationDescriptor) -> Boolean) {
fun collect(result: LookupElementsCollector) { fun collect(result: LookupElementsCollector) {
val builtIns = KotlinBuiltIns.getInstance().getNonPhysicalClasses().filter { kindFilter(it.getKind()) && prefixMatcher.prefixMatches(it.getName().asString()) } //TODO: this is a temporary hack until we have built-ins in indices
result.addDescriptorElements(builtIns, suppressAutoInsertion = true) val builtIns = JavaToKotlinClassMap.INSTANCE.allKotlinClasses() + listOf(KotlinBuiltIns.getInstance().getNothing())
val filteredBuiltIns = builtIns.filter { kindFilter(it.getKind()) && prefixMatcher.prefixMatches(it.getName().asString()) }
result.addDescriptorElements(filteredBuiltIns, suppressAutoInsertion = true)
val helper = KotlinIndicesHelper(scope.getProject(), resolutionFacade, bindingContext, scope, moduleDescriptor, visibilityFilter) val helper = KotlinIndicesHelper(scope.getProject(), resolutionFacade, bindingContext, scope, moduleDescriptor, visibilityFilter)
result.addDescriptorElements(helper.getClassDescriptors({ prefixMatcher.prefixMatches(it) }, kindFilter), result.addDescriptorElements(helper.getClassDescriptors({ prefixMatcher.prefixMatches(it) }, kindFilter),