diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java index 8e450cce0f8..e90a6889c11 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java @@ -84,6 +84,8 @@ public interface Errors { SimpleDiagnosticFactory EXPRESSION_EXPECTED_NAMESPACE_FOUND = SimpleDiagnosticFactory.create(ERROR, "Expression expected, but a namespace name found"); ParameterizedDiagnosticFactory1 CANNOT_IMPORT_FROM_ELEMENT = ParameterizedDiagnosticFactory1.create(ERROR, "Cannot import from ''{0}''", NAME); + ParameterizedDiagnosticFactory1 CANNOT_BE_IMPORTED = ParameterizedDiagnosticFactory1.create(ERROR, "Cannot import ''{0}'', functions and properties can be imported only from packages", NAME); + SimpleDiagnosticFactory USELESS_IMPORT = SimpleDiagnosticFactory.create(ERROR, "Useless import"); SimpleDiagnosticFactory CANNOT_INFER_PARAMETER_TYPE = SimpleDiagnosticFactory.create(ERROR, "Cannot infer a type for this parameter. To specify it explicitly use the {(p : Type) => ...} notation"); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ImportsResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ImportsResolver.java index 202d5b942e4..806cf734515 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ImportsResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ImportsResolver.java @@ -1,5 +1,7 @@ package org.jetbrains.jet.lang.resolve; +import com.google.common.base.Predicate; +import com.google.common.collect.Collections2; import com.google.common.collect.Lists; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -75,13 +77,8 @@ public class ImportsResolver { } else { assert importedReference instanceof JetSimpleNameExpression; - - // for "import java.*" there's should be a correct resolving - // but for "import SomeClass" we want to get unresolved error, even if SomeClass descriptor exist in outer scope - JetScope resolveScope = importDirective.isAllUnder() ? namespaceScope : JetScope.EMPTY; - descriptors = lookupDescriptorsForSimpleNameReference((JetSimpleNameExpression) importedReference, - resolveScope, namespaceScope, !importDirective.isAllUnder()); + namespaceScope, true, !importDirective.isAllUnder()); } JetSimpleNameExpression referenceExpression = getLastReference(importedReference); @@ -174,7 +171,7 @@ public class ImportsResolver { } else { assert receiverExpression instanceof JetSimpleNameExpression; - declarationDescriptors = lookupDescriptorsForSimpleNameReference((JetSimpleNameExpression) receiverExpression, outerScope, false); + declarationDescriptors = lookupDescriptorsForSimpleNameReference((JetSimpleNameExpression) receiverExpression, outerScope, true, false); } JetExpression selectorExpression = importedReference.getSelectorExpression(); @@ -187,7 +184,7 @@ public class ImportsResolver { Collection result; for (DeclarationDescriptor declarationDescriptor : declarationDescriptors) { if (declarationDescriptor instanceof NamespaceDescriptor) { - result = lookupDescriptorsForSimpleNameReference(selector, ((NamespaceDescriptor) declarationDescriptor).getMemberScope(), isForLastPart); + result = lookupDescriptorsForSimpleNameReference(selector, ((NamespaceDescriptor) declarationDescriptor).getMemberScope(), true, isForLastPart); if (!result.isEmpty()) return result; } if (declarationDescriptor instanceof ClassDescriptor) { @@ -268,7 +265,7 @@ public class ImportsResolver { //on second phase class descriptor is only a descriptor for class object JetType classObjectType = classDescriptor.getClassObjectType(); if (classObjectType == null) return Collections.emptyList(); - return lookupDescriptorsForSimpleNameReference(memberReference, classObjectType.getMemberScope(), true); + return lookupDescriptorsForSimpleNameReference(memberReference, classObjectType.getMemberScope(), false, true); } @NotNull @@ -278,43 +275,22 @@ public class ImportsResolver { ClassDescriptor innerClass = classDescriptor.getInnerClassOrObject(memberReference.getReferencedName()); if (innerClass == null) return Collections.emptyList(); descriptors = Collections.singletonList(innerClass); - storeResolutionResult(descriptors, memberReference, JetScope.EMPTY, true); - return descriptors; + return filterResolutionResult(descriptors, memberReference, JetScope.EMPTY, false, true); } - private Collection lookupVariableMembers(@NotNull JetSimpleNameExpression memberReference, @NotNull VariableDescriptor variableDescriptor) { + private Collection lookupVariableMembers(@NotNull JetSimpleNameExpression memberReference, @NotNull VariableDescriptor variableDescriptor) { assert !firstPhase; JetType variableType = variableDescriptor.getReturnType(); if (variableType == null) return Collections.emptyList(); - return lookupDescriptorsForSimpleNameReference(memberReference, variableType.getMemberScope(), true); + return lookupDescriptorsForSimpleNameReference(memberReference, variableType.getMemberScope(), false, true); } @NotNull - private Collection lookupDescriptorsForSimpleNameReference( + private Collection lookupDescriptorsForSimpleNameReference( @NotNull JetSimpleNameExpression referenceExpression, @NotNull JetScope outerScope, - boolean isLastPart) { - - return lookupDescriptorsForSimpleNameReference(referenceExpression, outerScope, outerScope, isLastPart); - } - - /** - * - * @param referenceExpression - * @param outerScope - * @param bindingScope scope for searching completion descriptors. In most cases it's equal to outer scope - * but for case "import SomeIdentifier" we want an unresolved reference error, so give empty - * outer scope. - * @param isLastPart is the part given by referenceExpression last in import directive. Parameter should be false - * if there's .* after it or some other parts in full qualified name. - * @return - */ - @NotNull - private Collection lookupDescriptorsForSimpleNameReference( - @NotNull JetSimpleNameExpression referenceExpression, - @NotNull JetScope outerScope, - @NotNull JetScope bindingScope, + boolean namespaceLevel, boolean isLastPart) { List descriptors = Lists.newArrayList(); @@ -336,32 +312,58 @@ public class ImportsResolver { } } - storeResolutionResult(descriptors, referenceExpression, bindingScope, isLastPart); - - return descriptors; + return filterResolutionResult(descriptors, referenceExpression, outerScope, namespaceLevel, isLastPart); } - private void storeResolutionResult( + private Collection filterResolutionResult( @NotNull Collection descriptors, @NotNull JetSimpleNameExpression referenceExpression, @NotNull JetScope resolutionScope, + boolean namespaceLevel, //functions and properties can be imported boolean isLastPart) { - if (firstPhase) return; - - if (descriptors.size() == 1 && !(isLastPart && descriptors.iterator().next() instanceof NamespaceDescriptor)) { - trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, descriptors.iterator().next()); + if (firstPhase) { + return Collections2.filter(descriptors, new Predicate() { + @Override + public boolean apply(@Nullable DeclarationDescriptor descriptor) { + return (descriptor instanceof ClassDescriptor) || + (descriptor instanceof NamespaceDescriptor); + } + }); } - else if (descriptors.size() > 1) { - trace.record(BindingContext.AMBIGUOUS_REFERENCE_TARGET, referenceExpression, descriptors); + Collection filteredDescriptors; + if (namespaceLevel) { + filteredDescriptors = descriptors; } else { - trace.report(UNRESOLVED_REFERENCE.on(referenceExpression)); + filteredDescriptors = Collections2.filter(descriptors, new Predicate() { + @Override + public boolean apply(@Nullable DeclarationDescriptor descriptor) { + return (descriptor instanceof NamespaceDescriptor) || + (descriptor instanceof ClassDescriptor) || + (descriptor instanceof VariableDescriptor && ((VariableDescriptor) descriptor).isObjectDeclaration()); + } + }); + } + if (descriptors.size() == 1 && filteredDescriptors.size() <= 1) { + trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, descriptors.iterator().next()); + } + if (filteredDescriptors.isEmpty()) { + if (!descriptors.isEmpty()) { + trace.report(CANNOT_BE_IMPORTED.on(referenceExpression, descriptors.iterator().next())); + } + else { + trace.report(UNRESOLVED_REFERENCE.on(referenceExpression)); + } + } + else if (filteredDescriptors.size() > 1) { + trace.record(BindingContext.AMBIGUOUS_REFERENCE_TARGET, referenceExpression, descriptors); } // If it's not an ambiguous case - store resolution scope if (descriptors.size() <= 1) { trace.record(BindingContext.RESOLUTION_SCOPE, referenceExpression, resolutionScope); } + return filteredDescriptors; } } } diff --git a/compiler/testData/diagnostics/tests/scopes/Imports.jet b/compiler/testData/diagnostics/tests/scopes/Imports.jet index 02e7ecc6acf..e2ca13aac67 100644 --- a/compiler/testData/diagnostics/tests/scopes/Imports.jet +++ b/compiler/testData/diagnostics/tests/scopes/Imports.jet @@ -5,29 +5,29 @@ import b.B //class import b.foo //function import b.ext //extension function import b.value //property -import b.C.bar //function from class object -import b.C.cValue //property from class object +import b.C.bar //function from class object +import b.C.cValue //property from class object import b.constant.fff //function from val import b.constant.dValue //property from val import b.constant -import b.E.f //val from class object +import b.E.f //val from class object import smth.illegal import b.C.smth.illegal -import bar.smth -import bar.* +import b.bar.smth +import b.bar.* fun test(arg: B) { foo(value) arg.ext() - bar() - foo(cValue) + bar() + foo(cValue) fff(dValue) constant.fff(constant.dValue) - f.f() + f.f() } // FILE:b.kt @@ -80,4 +80,20 @@ object C { fun foo() { if (i == 3) f() +} + +//FILE:d.kt +package d + +import A.B +import A.C + +val b : B = B() +val c : B = C + +class A() { + class object { + open class B() {} + object C : B() {} + } } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/scopes/kt900.jet b/compiler/testData/diagnostics/tests/scopes/kt900.jet index 42cb748d254..c0623f56335 100644 --- a/compiler/testData/diagnostics/tests/scopes/kt900.jet +++ b/compiler/testData/diagnostics/tests/scopes/kt900.jet @@ -101,7 +101,7 @@ package d import A.* import M.R -import M.R.bar +import M.R.bar import M.T import M.Y @@ -109,7 +109,7 @@ var r: T = T() val y: T = Y fun f() { - bar() + bar() R.bar() B.foo() } diff --git a/idea/testData/checker/regression/kt960.jet b/idea/testData/checker/regression/kt960.jet deleted file mode 100644 index 0371e95fabf..00000000000 --- a/idea/testData/checker/regression/kt960.jet +++ /dev/null @@ -1,8 +0,0 @@ -// KT-960 import namespace should give unresolved reference -package some - -import java.util - -class Test { - -} \ No newline at end of file