Current package members to have less priority than explicit imports

This commit is contained in:
Valentin Kipyatkov
2015-01-15 20:54:35 +03:00
parent 59f24020b2
commit 929d6b885d
14 changed files with 188 additions and 93 deletions
@@ -193,7 +193,7 @@ public class LazyTopDownAnalyzer {
@Override
public void visitImportDirective(@NotNull JetImportDirective importDirective) {
LazyFileScope fileScope = resolveSession.getScopeProvider().getScopeForFile(
LazyFileScope fileScope = resolveSession.getScopeProvider().getFileScope(
importDirective.getContainingJetFile());
fileScope.forceResolveImport(importDirective);
}
@@ -364,7 +364,7 @@ public class LazyTopDownAnalyzer {
}
private static void resolveAndCheckImports(@NotNull JetFile file, @NotNull KotlinCodeAnalyzer resolveSession) {
LazyFileScope fileScope = resolveSession.getScopeProvider().getScopeForFile(file);
LazyFileScope fileScope = resolveSession.getScopeProvider().getFileScope(file);
fileScope.forceResolveAllImports();
}
@@ -22,15 +22,24 @@ import org.jetbrains.kotlin.psi.JetImportDirective
import org.jetbrains.kotlin.psi.JetFile
import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.psi.JetCodeFragment
import org.jetbrains.kotlin.resolve.JetModuleUtil
import org.jetbrains.kotlin.resolve.NoSubpackagesInPackageScope
import org.jetbrains.kotlin.resolve.scopes.JetScope
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
class LazyFileScope private(
private val aliasImportsScope: LazyImportScope,
private val allUnderImportsScope: LazyImportScope,
private val defaultAliasImportsScope: LazyImportScope,
private val defaultAllUnderImportsScope: LazyImportScope,
containingDeclaration: PackageViewDescriptor,
currentPackageMembersScope: JetScope,
rootPackagesScope: JetScope,
additionalScopes: List<JetScope>,
containingDeclaration: PackageFragmentDescriptor,
debugName: String
) : ChainedScope(containingDeclaration, debugName, aliasImportsScope, allUnderImportsScope, defaultAliasImportsScope, defaultAllUnderImportsScope) {
) : ChainedScope(containingDeclaration,
debugName,
*(listOf(aliasImportsScope, defaultAliasImportsScope, currentPackageMembersScope, rootPackagesScope, allUnderImportsScope, defaultAllUnderImportsScope) + additionalScopes).copyToArray()) {
public fun forceResolveAllImports() {
aliasImportsScope.forceResolveAllContents()
@@ -49,23 +58,36 @@ class LazyFileScope private(
class object {
public fun create(
resolveSession: ResolveSession,
packageDescriptor: PackageViewDescriptor,
jetFile: JetFile,
file: JetFile,
defaultImports: Collection<JetImportDirective>,
additionalScopes: List<JetScope>,
traceForImportResolve: BindingTrace,
traceForDefaultImportResolve: BindingTrace,
debugName: String
): LazyFileScope {
val imports = if (jetFile is JetCodeFragment)
jetFile.importsAsImportList()?.getImports() ?: listOf()
val imports = if (file is JetCodeFragment)
file.importsAsImportList()?.getImports() ?: listOf()
else
jetFile.getImportDirectives()
file.getImportDirectives()
val aliasImportsScope = LazyImportScope(resolveSession, packageDescriptor, AliasImportsIndexed(imports), traceForImportResolve, "Alias imports in $debugName")
val allUnderImportsScope = LazyImportScope(resolveSession, packageDescriptor, AllUnderImportsIndexed(imports), traceForImportResolve, "All under imports in $debugName")
val defaultAliasImportsScope = LazyImportScope(resolveSession, packageDescriptor, AliasImportsIndexed(defaultImports), traceForDefaultImportResolve, "Default alias imports in $debugName")
val defaultAllUnderImportsScope = LazyImportScope(resolveSession, packageDescriptor, AllUnderImportsIndexed(defaultImports), traceForDefaultImportResolve, "Default all under imports in $debugName")
return LazyFileScope(aliasImportsScope, allUnderImportsScope, defaultAliasImportsScope, defaultAllUnderImportsScope, packageDescriptor, debugName)
val packageView = getPackageViewDescriptor(file, resolveSession)
val currentPackageMembersScope = NoSubpackagesInPackageScope(packageView)
val rootPackagesScope = JetModuleUtil.getSubpackagesOfRootScope(resolveSession.getModuleDescriptor())
val aliasImportsScope = LazyImportScope(resolveSession, packageView, AliasImportsIndexed(imports), traceForImportResolve, "Alias imports in $debugName")
val allUnderImportsScope = LazyImportScope(resolveSession, packageView, AllUnderImportsIndexed(imports), traceForImportResolve, "All under imports in $debugName")
val defaultAliasImportsScope = LazyImportScope(resolveSession, packageView, AliasImportsIndexed(defaultImports), traceForDefaultImportResolve, "Default alias imports in $debugName")
val defaultAllUnderImportsScope = LazyImportScope(resolveSession, packageView, AllUnderImportsIndexed(defaultImports), traceForDefaultImportResolve, "Default all under imports in $debugName")
return LazyFileScope(aliasImportsScope, allUnderImportsScope, defaultAliasImportsScope, defaultAllUnderImportsScope,
currentPackageMembersScope, rootPackagesScope, additionalScopes,
resolveSession.getPackageFragment(file.getPackageFqName()), debugName)
}
private fun getPackageViewDescriptor(file: JetFile, resolveSession: ResolveSession): PackageViewDescriptor {
val fqName = file.getPackageFqName()
return resolveSession.getModuleDescriptor().getPackage(fqName)
?: throw IllegalStateException("Package not found: $fqName maybe the file is not in scope of this resolve session: ${file.getName()}")
}
}
}
@@ -267,14 +267,13 @@ public class ResolveSession implements KotlinCodeAnalyzer {
return getClassObjectDescriptor(classObjectElement);
}
}
JetScope resolutionScope = getScopeProvider().getResolutionScopeForDeclaration(classOrObject);
Name name = classOrObject.getNameAsSafeName();
JetScope resolutionScope = resolutionScopeToResolveDeclaration(classOrObject);
// Why not use the result here. Because it may be that there is a redeclaration:
// class A {} class A { fun foo(): A<completion here>}
// and if we find the class by name only, we may b-not get the right one.
// This call is only needed to make sure the classes are written to trace
ClassifierDescriptor scopeDescriptor = resolutionScope.getClassifier(name);
ClassifierDescriptor scopeDescriptor = resolutionScope.getClassifier(classOrObject.getNameAsSafeName());
DeclarationDescriptor descriptor = getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, classOrObject);
if (descriptor == null) {
@@ -291,7 +290,7 @@ public class ResolveSession implements KotlinCodeAnalyzer {
@NotNull
public ClassDescriptor getClassDescriptorForScript(@NotNull JetScript script) {
JetScope resolutionScope = getScopeProvider().getResolutionScopeForDeclaration(script);
JetScope resolutionScope = resolutionScopeToResolveDeclaration(script);
FqName fqName = ScriptNameUtil.classNameForScript(script);
ClassifierDescriptor classifier = resolutionScope.getClassifier(fqName.shortName());
assert classifier != null : "No descriptor for " + fqName + " in file " + script.getContainingFile();
@@ -399,7 +398,7 @@ public class ResolveSession implements KotlinCodeAnalyzer {
@Override
public DeclarationDescriptor visitNamedFunction(@NotNull JetNamedFunction function, Void data) {
JetScope scopeForDeclaration = getScopeProvider().getResolutionScopeForDeclaration(function);
JetScope scopeForDeclaration = resolutionScopeToResolveDeclaration(function);
scopeForDeclaration.getFunctions(function.getNameAsSafeName());
return getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, function);
}
@@ -435,7 +434,7 @@ public class ResolveSession implements KotlinCodeAnalyzer {
@Override
public DeclarationDescriptor visitProperty(@NotNull JetProperty property, Void data) {
JetScope scopeForDeclaration = getScopeProvider().getResolutionScopeForDeclaration(property);
JetScope scopeForDeclaration = resolutionScopeToResolveDeclaration(property);
scopeForDeclaration.getProperties(property.getNameAsSafeName());
return getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, property);
}
@@ -527,4 +526,18 @@ public class ResolveSession implements KotlinCodeAnalyzer {
public QualifiedExpressionResolver getQualifiedExpressionResolver() {
return qualifiedExpressionResolver;
}
@NotNull
private JetScope resolutionScopeToResolveDeclaration(@NotNull JetDeclaration declaration) {
boolean isTopLevel = JetStubbedPsiUtil.getContainingDeclaration(declaration) == null;
if (isTopLevel) { // for top level declarations we search directly in package because of possible conflicts with imports
FqName fqName = ((JetFile) declaration.getContainingFile()).getPackageFqName();
LazyPackageDescriptor packageDescriptor = getPackageFragment(fqName);
assert packageDescriptor != null;
return packageDescriptor.getMemberScope();
}
else {
return getScopeProvider().getResolutionScopeForDeclaration(declaration);
}
}
}
@@ -24,17 +24,13 @@ import org.jetbrains.kotlin.descriptors.PackageViewDescriptor;
import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.ImportPath;
import org.jetbrains.kotlin.resolve.JetModuleUtil;
import org.jetbrains.kotlin.resolve.NoSubpackagesInPackageScope;
import org.jetbrains.kotlin.resolve.TemporaryBindingTrace;
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyClassDescriptor;
import org.jetbrains.kotlin.resolve.scopes.ChainedScope;
import org.jetbrains.kotlin.resolve.scopes.JetScope;
import org.jetbrains.kotlin.storage.MemoizedFunctionToNotNull;
import org.jetbrains.kotlin.storage.NotNullLazyValue;
import javax.inject.Inject;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -51,9 +47,7 @@ public class ScopeProvider {
private final NotNullLazyValue<Collection<JetImportDirective>> defaultImports;
private final MemoizedFunctionToNotNull<JetFile, LazyFileScope> importScopes;
private final MemoizedFunctionToNotNull<JetFile, JetScope> fileScopes;
private final MemoizedFunctionToNotNull<JetFile, LazyFileScope> fileScopes;
@SuppressWarnings("ConstantConditions") @NotNull
private AdditionalFileScopeProvider additionalFileScopeProvider = null;
@@ -82,70 +76,29 @@ public class ScopeProvider {
});
this.importScopes = resolveSession.getStorageManager().createMemoizedFunction(new Function1<JetFile, LazyFileScope>() {
this.fileScopes = resolveSession.getStorageManager().createMemoizedFunction(new Function1<JetFile, LazyFileScope>() {
@Override
public LazyFileScope invoke(@NotNull JetFile file) {
return createImportScope(file, defaultImports.invoke());
}
});
this.fileScopes = resolveSession.getStorageManager().createMemoizedFunction(new Function1<JetFile, JetScope>() {
@Override
public JetScope invoke(JetFile file) {
public LazyFileScope invoke(JetFile file) {
return createFileScope(file);
}
});
}
private LazyFileScope createImportScope(@NotNull JetFile file, @NotNull Collection<JetImportDirective> defaultImports) {
TemporaryBindingTrace tempTrace = TemporaryBindingTrace.create(resolveSession.getTrace(), "Transient trace for default imports lazy resolve");
return LazyFileScope.OBJECT$.create(
resolveSession,
getFilePackageDescriptor(file),
file,
defaultImports,
resolveSession.getTrace(),
tempTrace,
"LazyFileScope for file " + file.getName());
}
@NotNull
public JetScope getFileScope(@NotNull JetFile file) {
public LazyFileScope getFileScope(@NotNull JetFile file) {
return fileScopes.invoke(file);
}
private JetScope createFileScope(@NotNull JetFile file) {
return new ChainedScope(resolveSession.getPackageFragment(file.getPackageFqName()),
"File scope: " + file.getName(),
collectFileScopes(file));
}
@NotNull
private JetScope[] collectFileScopes(@NotNull JetFile file) {
List<JetScope> list = new ArrayList<JetScope>();
list.add(new NoSubpackagesInPackageScope(getFilePackageDescriptor(file)));
list.add(JetModuleUtil.getSubpackagesOfRootScope(resolveSession.getModuleDescriptor()));
list.add(importScopes.invoke(file));
list.addAll(additionalFileScopeProvider.scopes(file));
return list.toArray(new JetScope[list.size()]);
}
@NotNull
public LazyFileScope getScopeForFile(@NotNull JetFile file) {
return importScopes.invoke(file);
}
@NotNull
private PackageViewDescriptor getFilePackageDescriptor(JetFile file) {
FqName fqName = file.getPackageFqName();
PackageViewDescriptor packageDescriptor = resolveSession.getModuleDescriptor().getPackage(fqName);
if (packageDescriptor == null) {
throw new IllegalStateException("Package not found: " + fqName + " maybe the file is not in scope of this resolve session: " + file.getName());
}
return packageDescriptor;
private LazyFileScope createFileScope(@NotNull JetFile file) {
TemporaryBindingTrace tempTrace = TemporaryBindingTrace.create(resolveSession.getTrace(), "Transient trace for default imports lazy resolve");
return LazyFileScope.OBJECT$.create(
resolveSession,
file,
defaultImports.invoke(),
additionalFileScopeProvider.scopes(file),
resolveSession.getTrace(),
tempTrace,
"LazyFileScope for file " + file.getName());
}
@NotNull
@@ -0,0 +1,16 @@
// FILE: a.kt
package a
class X
// FILE: b.kt
package b
open class X
// FILE: b1.kt
package b
import a.*
class Y : X() // class from the current package should take priority
@@ -0,0 +1,28 @@
package
package a {
internal final class X {
public constructor X()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
}
package b {
internal open class X {
public constructor X()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
internal final class Y : b.X {
public constructor Y()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
}
@@ -0,0 +1,16 @@
// FILE: a.kt
package a
open class Y
// FILE: b.kt
package b
class X
// FILE: b1.kt
package b
import a.Y as X
class Y : X() // class from explicit import should take priority
@@ -0,0 +1,28 @@
package
package a {
internal open class Y {
public constructor Y()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
}
package b {
internal final class X {
public constructor X()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
internal final class Y : a.Y {
public constructor Y()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
}
@@ -0,0 +1,8 @@
import kotlin.Double
import kotlin.List
import kotlin.arrayOfNulls
class List {}
fun arrayOfNulls(){}
val arrayOfNulls: Int = 0
@@ -1,5 +1,8 @@
package
internal val arrayOfNulls: kotlin.Int = 0
internal fun arrayOfNulls(): kotlin.Unit
internal final class List {
public constructor List()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
@@ -1,4 +0,0 @@
import kotlin.Double
import <!USELESS_HIDDEN_IMPORT!>kotlin.List<!>
class List {}
@@ -6,7 +6,7 @@ import testing.TestClass
class ~same-file~TestClass
val a1: `same-file`TestClass? = null
val a1: `testing`TestClass? = null
//FILE:testing.kt
@@ -4733,6 +4733,18 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("CurrentPackageAndAllUnderImport.kt")
public void testCurrentPackageAndAllUnderImport() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/imports/CurrentPackageAndAllUnderImport.kt");
doTest(fileName);
}
@TestMetadata("CurrentPackageAndExplicitImport.kt")
public void testCurrentPackageAndExplicitImport() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/imports/CurrentPackageAndExplicitImport.kt");
doTest(fileName);
}
@TestMetadata("DontImportRootScope.kt")
public void testDontImportRootScope() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/imports/DontImportRootScope.kt");
@@ -4775,6 +4787,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("ImportHidingDefinitionInTheSameFile.kt")
public void testImportHidingDefinitionInTheSameFile() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/imports/ImportHidingDefinitionInTheSameFile.kt");
doTest(fileName);
}
@TestMetadata("ImportObjectAndUseAsSupertype.kt")
public void testImportObjectAndUseAsSupertype() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/imports/ImportObjectAndUseAsSupertype.kt");
@@ -4817,12 +4835,6 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("ImportsHiddenByDefinitionInTheSameFile.kt")
public void testImportsHiddenByDefinitionInTheSameFile() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/imports/ImportsHiddenByDefinitionInTheSameFile.kt");
doTest(fileName);
}
@TestMetadata("ImportsUselessSimpleImport.kt")
public void testImportsUselessSimpleImport() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/imports/ImportsUselessSimpleImport.kt");
@@ -160,7 +160,7 @@ public abstract class ElementResolver {
}
else if (resolveElement instanceof JetImportDirective) {
JetImportDirective importDirective = (JetImportDirective) resolveElement;
LazyFileScope scope = resolveSession.getScopeProvider().getScopeForFile(importDirective.getContainingJetFile());
LazyFileScope scope = resolveSession.getScopeProvider().getFileScope(importDirective.getContainingJetFile());
scope.forceResolveAllImports();
}
else if (resolveElement instanceof JetAnnotationEntry) {