forbid import of functions and properties from objects
This commit is contained in:
@@ -84,6 +84,8 @@ public interface Errors {
|
|||||||
SimpleDiagnosticFactory EXPRESSION_EXPECTED_NAMESPACE_FOUND = SimpleDiagnosticFactory.create(ERROR, "Expression expected, but a namespace name found");
|
SimpleDiagnosticFactory EXPRESSION_EXPECTED_NAMESPACE_FOUND = SimpleDiagnosticFactory.create(ERROR, "Expression expected, but a namespace name found");
|
||||||
|
|
||||||
ParameterizedDiagnosticFactory1<DeclarationDescriptor> CANNOT_IMPORT_FROM_ELEMENT = ParameterizedDiagnosticFactory1.create(ERROR, "Cannot import from ''{0}''", NAME);
|
ParameterizedDiagnosticFactory1<DeclarationDescriptor> CANNOT_IMPORT_FROM_ELEMENT = ParameterizedDiagnosticFactory1.create(ERROR, "Cannot import from ''{0}''", NAME);
|
||||||
|
ParameterizedDiagnosticFactory1<DeclarationDescriptor> 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");
|
SimpleDiagnosticFactory CANNOT_INFER_PARAMETER_TYPE = SimpleDiagnosticFactory.create(ERROR, "Cannot infer a type for this parameter. To specify it explicitly use the {(p : Type) => ...} notation");
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package org.jetbrains.jet.lang.resolve;
|
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 com.google.common.collect.Lists;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@@ -75,13 +77,8 @@ public class ImportsResolver {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assert importedReference instanceof JetSimpleNameExpression;
|
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,
|
descriptors = lookupDescriptorsForSimpleNameReference((JetSimpleNameExpression) importedReference,
|
||||||
resolveScope, namespaceScope, !importDirective.isAllUnder());
|
namespaceScope, true, !importDirective.isAllUnder());
|
||||||
}
|
}
|
||||||
|
|
||||||
JetSimpleNameExpression referenceExpression = getLastReference(importedReference);
|
JetSimpleNameExpression referenceExpression = getLastReference(importedReference);
|
||||||
@@ -174,7 +171,7 @@ public class ImportsResolver {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assert receiverExpression instanceof JetSimpleNameExpression;
|
assert receiverExpression instanceof JetSimpleNameExpression;
|
||||||
declarationDescriptors = lookupDescriptorsForSimpleNameReference((JetSimpleNameExpression) receiverExpression, outerScope, false);
|
declarationDescriptors = lookupDescriptorsForSimpleNameReference((JetSimpleNameExpression) receiverExpression, outerScope, true, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
JetExpression selectorExpression = importedReference.getSelectorExpression();
|
JetExpression selectorExpression = importedReference.getSelectorExpression();
|
||||||
@@ -187,7 +184,7 @@ public class ImportsResolver {
|
|||||||
Collection<? extends DeclarationDescriptor> result;
|
Collection<? extends DeclarationDescriptor> result;
|
||||||
for (DeclarationDescriptor declarationDescriptor : declarationDescriptors) {
|
for (DeclarationDescriptor declarationDescriptor : declarationDescriptors) {
|
||||||
if (declarationDescriptor instanceof NamespaceDescriptor) {
|
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 (!result.isEmpty()) return result;
|
||||||
}
|
}
|
||||||
if (declarationDescriptor instanceof ClassDescriptor) {
|
if (declarationDescriptor instanceof ClassDescriptor) {
|
||||||
@@ -268,7 +265,7 @@ public class ImportsResolver {
|
|||||||
//on second phase class descriptor is only a descriptor for class object
|
//on second phase class descriptor is only a descriptor for class object
|
||||||
JetType classObjectType = classDescriptor.getClassObjectType();
|
JetType classObjectType = classDescriptor.getClassObjectType();
|
||||||
if (classObjectType == null) return Collections.emptyList();
|
if (classObjectType == null) return Collections.emptyList();
|
||||||
return lookupDescriptorsForSimpleNameReference(memberReference, classObjectType.getMemberScope(), true);
|
return lookupDescriptorsForSimpleNameReference(memberReference, classObjectType.getMemberScope(), false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -278,43 +275,22 @@ public class ImportsResolver {
|
|||||||
ClassDescriptor innerClass = classDescriptor.getInnerClassOrObject(memberReference.getReferencedName());
|
ClassDescriptor innerClass = classDescriptor.getInnerClassOrObject(memberReference.getReferencedName());
|
||||||
if (innerClass == null) return Collections.emptyList();
|
if (innerClass == null) return Collections.emptyList();
|
||||||
descriptors = Collections.<DeclarationDescriptor>singletonList(innerClass);
|
descriptors = Collections.<DeclarationDescriptor>singletonList(innerClass);
|
||||||
storeResolutionResult(descriptors, memberReference, JetScope.EMPTY, true);
|
return filterResolutionResult(descriptors, memberReference, JetScope.EMPTY, false, true);
|
||||||
return descriptors;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Collection<DeclarationDescriptor> lookupVariableMembers(@NotNull JetSimpleNameExpression memberReference, @NotNull VariableDescriptor variableDescriptor) {
|
private Collection<? extends DeclarationDescriptor> lookupVariableMembers(@NotNull JetSimpleNameExpression memberReference, @NotNull VariableDescriptor variableDescriptor) {
|
||||||
assert !firstPhase;
|
assert !firstPhase;
|
||||||
|
|
||||||
JetType variableType = variableDescriptor.getReturnType();
|
JetType variableType = variableDescriptor.getReturnType();
|
||||||
if (variableType == null) return Collections.emptyList();
|
if (variableType == null) return Collections.emptyList();
|
||||||
return lookupDescriptorsForSimpleNameReference(memberReference, variableType.getMemberScope(), true);
|
return lookupDescriptorsForSimpleNameReference(memberReference, variableType.getMemberScope(), false, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private Collection<DeclarationDescriptor> lookupDescriptorsForSimpleNameReference(
|
private Collection<? extends DeclarationDescriptor> lookupDescriptorsForSimpleNameReference(
|
||||||
@NotNull JetSimpleNameExpression referenceExpression,
|
@NotNull JetSimpleNameExpression referenceExpression,
|
||||||
@NotNull JetScope outerScope,
|
@NotNull JetScope outerScope,
|
||||||
boolean isLastPart) {
|
boolean namespaceLevel,
|
||||||
|
|
||||||
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<DeclarationDescriptor> lookupDescriptorsForSimpleNameReference(
|
|
||||||
@NotNull JetSimpleNameExpression referenceExpression,
|
|
||||||
@NotNull JetScope outerScope,
|
|
||||||
@NotNull JetScope bindingScope,
|
|
||||||
boolean isLastPart) {
|
boolean isLastPart) {
|
||||||
|
|
||||||
List<DeclarationDescriptor> descriptors = Lists.newArrayList();
|
List<DeclarationDescriptor> descriptors = Lists.newArrayList();
|
||||||
@@ -336,32 +312,58 @@ public class ImportsResolver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
storeResolutionResult(descriptors, referenceExpression, bindingScope, isLastPart);
|
return filterResolutionResult(descriptors, referenceExpression, outerScope, namespaceLevel, isLastPart);
|
||||||
|
|
||||||
return descriptors;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void storeResolutionResult(
|
private Collection<? extends DeclarationDescriptor> filterResolutionResult(
|
||||||
@NotNull Collection<? extends DeclarationDescriptor> descriptors,
|
@NotNull Collection<? extends DeclarationDescriptor> descriptors,
|
||||||
@NotNull JetSimpleNameExpression referenceExpression,
|
@NotNull JetSimpleNameExpression referenceExpression,
|
||||||
@NotNull JetScope resolutionScope,
|
@NotNull JetScope resolutionScope,
|
||||||
|
boolean namespaceLevel, //functions and properties can be imported
|
||||||
boolean isLastPart) {
|
boolean isLastPart) {
|
||||||
if (firstPhase) return;
|
if (firstPhase) {
|
||||||
|
return Collections2.filter(descriptors, new Predicate<DeclarationDescriptor>() {
|
||||||
if (descriptors.size() == 1 && !(isLastPart && descriptors.iterator().next() instanceof NamespaceDescriptor)) {
|
@Override
|
||||||
trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, descriptors.iterator().next());
|
public boolean apply(@Nullable DeclarationDescriptor descriptor) {
|
||||||
|
return (descriptor instanceof ClassDescriptor) ||
|
||||||
|
(descriptor instanceof NamespaceDescriptor);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
else if (descriptors.size() > 1) {
|
Collection<? extends DeclarationDescriptor> filteredDescriptors;
|
||||||
trace.record(BindingContext.AMBIGUOUS_REFERENCE_TARGET, referenceExpression, descriptors);
|
if (namespaceLevel) {
|
||||||
|
filteredDescriptors = descriptors;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
trace.report(UNRESOLVED_REFERENCE.on(referenceExpression));
|
filteredDescriptors = Collections2.filter(descriptors, new Predicate<DeclarationDescriptor>() {
|
||||||
|
@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 it's not an ambiguous case - store resolution scope
|
||||||
if (descriptors.size() <= 1) {
|
if (descriptors.size() <= 1) {
|
||||||
trace.record(BindingContext.RESOLUTION_SCOPE, referenceExpression, resolutionScope);
|
trace.record(BindingContext.RESOLUTION_SCOPE, referenceExpression, resolutionScope);
|
||||||
}
|
}
|
||||||
|
return filteredDescriptors;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,29 +5,29 @@ import b.B //class
|
|||||||
import b.foo //function
|
import b.foo //function
|
||||||
import b.ext //extension function
|
import b.ext //extension function
|
||||||
import b.value //property
|
import b.value //property
|
||||||
import b.C.bar //function from class object
|
import b.C.<!CANNOT_BE_IMPORTED!>bar<!> //function from class object
|
||||||
import b.C.cValue //property from class object
|
import b.C.<!CANNOT_BE_IMPORTED!>cValue<!> //property from class object
|
||||||
import b.<!CANNOT_IMPORT_FROM_ELEMENT!>constant<!>.fff //function from val
|
import b.<!CANNOT_IMPORT_FROM_ELEMENT!>constant<!>.fff //function from val
|
||||||
import b.<!CANNOT_IMPORT_FROM_ELEMENT!>constant<!>.dValue //property from val
|
import b.<!CANNOT_IMPORT_FROM_ELEMENT!>constant<!>.dValue //property from val
|
||||||
import b.constant
|
import b.constant
|
||||||
import b.E.f //val from class object
|
import b.E.<!CANNOT_BE_IMPORTED!>f<!> //val from class object
|
||||||
import <!UNRESOLVED_REFERENCE!>smth<!>.illegal
|
import <!UNRESOLVED_REFERENCE!>smth<!>.illegal
|
||||||
import b.C.<!UNRESOLVED_REFERENCE!>smth<!>.illegal
|
import b.C.<!UNRESOLVED_REFERENCE!>smth<!>.illegal
|
||||||
import <!CANNOT_IMPORT_FROM_ELEMENT!>bar<!>.smth
|
import b.<!CANNOT_IMPORT_FROM_ELEMENT!>bar<!>.smth
|
||||||
import <!CANNOT_IMPORT_FROM_ELEMENT!>bar<!>.*
|
import b.<!CANNOT_IMPORT_FROM_ELEMENT!>bar<!>.*
|
||||||
|
|
||||||
fun test(arg: B) {
|
fun test(arg: B) {
|
||||||
foo(value)
|
foo(value)
|
||||||
arg.ext()
|
arg.ext()
|
||||||
|
|
||||||
bar()
|
<!UNRESOLVED_REFERENCE!>bar<!>()
|
||||||
foo(cValue)
|
foo(<!UNRESOLVED_REFERENCE!>cValue<!>)
|
||||||
|
|
||||||
<!UNRESOLVED_REFERENCE!>fff<!>(<!UNRESOLVED_REFERENCE!>dValue<!>)
|
<!UNRESOLVED_REFERENCE!>fff<!>(<!UNRESOLVED_REFERENCE!>dValue<!>)
|
||||||
|
|
||||||
constant.fff(constant.dValue)
|
constant.fff(constant.dValue)
|
||||||
|
|
||||||
f.f()
|
<!UNRESOLVED_REFERENCE!>f<!>.f()
|
||||||
}
|
}
|
||||||
|
|
||||||
// FILE:b.kt
|
// FILE:b.kt
|
||||||
@@ -80,4 +80,20 @@ object C {
|
|||||||
|
|
||||||
fun foo() {
|
fun foo() {
|
||||||
if (i == 3) f()
|
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() {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -101,7 +101,7 @@ package d
|
|||||||
|
|
||||||
import A.*
|
import A.*
|
||||||
import M.R
|
import M.R
|
||||||
import M.R.bar
|
import M.R.<!CANNOT_BE_IMPORTED!>bar<!>
|
||||||
import M.T
|
import M.T
|
||||||
import M.Y
|
import M.Y
|
||||||
|
|
||||||
@@ -109,7 +109,7 @@ var r: T = T()
|
|||||||
val y: T = Y
|
val y: T = Y
|
||||||
|
|
||||||
fun f() {
|
fun f() {
|
||||||
bar()
|
<!UNRESOLVED_REFERENCE!>bar<!>()
|
||||||
R.bar()
|
R.bar()
|
||||||
B.foo()
|
B.foo()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
// KT-960 import namespace should give unresolved reference
|
|
||||||
package some
|
|
||||||
|
|
||||||
import java.<error>util</error>
|
|
||||||
|
|
||||||
class Test {
|
|
||||||
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user