From c318191f5d4955539acbfe314235aa7373ce79d0 Mon Sep 17 00:00:00 2001 From: Alex Tkachman Date: Tue, 10 Jan 2012 21:14:22 +0200 Subject: [PATCH 1/2] KT-935 resolved call used on += --- .../jet/codegen/ExpressionCodegen.java | 13 +++++++- .../testData/codegen/regressions/kt935.kt | 30 +++++++++++++++++++ .../jet/codegen/PrimitiveTypesTest.java | 4 +++ 3 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 compiler/testData/codegen/regressions/kt935.kt diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index fbdec54b7f9..75f29f34539 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -1864,12 +1864,23 @@ public class ExpressionCodegen extends JetVisitor { } private void callAugAssignMethod(JetBinaryExpression expression, CallableMethod callable, Type lhsType, final boolean keepReturnValue) { + ResolvedCall resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, expression.getOperationReference()); + assert resolvedCall != null; + StackValue value = gen(expression.getLeft()); if (keepReturnValue) { value.dupReceiver(v); } value.put(lhsType, v); - genToJVMStack(expression.getRight()); + StackValue receiver = StackValue.onStack(lhsType); + + if(!(resolvedCall.getResultingDescriptor() instanceof ConstructorDescriptor)) { // otherwise already + receiver = StackValue.receiver(resolvedCall, receiver, this, callable); + receiver.put(receiver.type, v); + } + + pushTypeArguments(resolvedCall); + pushMethodArguments(resolvedCall, callable.getValueParameterTypes()); callable.invoke(v); if (keepReturnValue) { value.store(v); diff --git a/compiler/testData/codegen/regressions/kt935.kt b/compiler/testData/codegen/regressions/kt935.kt new file mode 100644 index 00000000000..7b76c881cdf --- /dev/null +++ b/compiler/testData/codegen/regressions/kt935.kt @@ -0,0 +1,30 @@ +package bottles + +fun box() : String { + var bottles = 10 + while (bottles > 0) { + print(bottlesOfBeer(bottles) + " on the wall, ") + println(bottlesOfBeer(bottles) + ".") + print("Take one down, pass it around, ") + if (--bottles == 0) { + println("no more bottles of beer on the wall.") + } + else { + println(bottlesOfBeer(bottles) + " on the wall.") + } + } + return "OK" +} + +fun bottlesOfBeer(count : Int) : String { + val result = StringBuilder() + result += count + result += if (count > 1) " bottles of beer" else " bottle of beer" + return result.toString() ?: "" +} + +// An excerpt from the standard library +fun print(message : String) { System.out?.print(message) } +fun println(message : String) { System.out?.println(message) } +fun StringBuilder.plusAssign(o : Any) { append(o) } +val Array.isEmpty : Boolean get() = size == 0 \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/codegen/PrimitiveTypesTest.java b/compiler/tests/org/jetbrains/jet/codegen/PrimitiveTypesTest.java index 77eeccc0997..fc073e4bd1f 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/PrimitiveTypesTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/PrimitiveTypesTest.java @@ -387,4 +387,8 @@ public class PrimitiveTypesTest extends CodegenTestCase { public void testKt945 () { blackBoxFile("regressions/kt945.jet"); } + + public void testKt935 () { + blackBoxFile("regressions/kt935.kt"); + } } From 0573efa6fbcabe84992fad07aea7b11f93845f2a Mon Sep 17 00:00:00 2001 From: Nikolay Krasko Date: Wed, 11 Jan 2012 13:55:20 +0400 Subject: [PATCH 2/2] KT-960 import namespace should give unresolved reference --- .../jet/lang/resolve/ImportsResolver.java | 89 +++++++++++++------ idea/testData/checker/regression/kt960.jet | 8 ++ 2 files changed, 72 insertions(+), 25 deletions(-) create mode 100644 idea/testData/checker/regression/kt960.jet 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 3eca5209219..4733a48afdd 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ImportsResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/ImportsResolver.java @@ -69,22 +69,20 @@ public class ImportsResolver { if (importedReference == null) return; Collection descriptors; if (importedReference instanceof JetQualifiedExpression) { - descriptors = lookupDescriptorsForQualifiedExpression((JetQualifiedExpression) importedReference, namespaceScope); + descriptors = lookupDescriptorsForQualifiedExpression((JetQualifiedExpression) importedReference, + namespaceScope, !importDirective.isAllUnder()); } else { assert importedReference instanceof JetSimpleNameExpression; - if (importDirective.isAllUnder()) { - // Example: import java.* - descriptors = lookupDescriptorsForSimpleNameReference((JetSimpleNameExpression) importedReference, namespaceScope); - } - else { - // Example: import IDENTIFIER - // Should be unresolved error - descriptors = lookupDescriptorsForSimpleNameReference((JetSimpleNameExpression) importedReference, JetScope.EMPTY); - trace.record(BindingContext.RESOLUTION_SCOPE, importedReference, namespaceScope); - } + // 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()); } + JetSimpleNameExpression referenceExpression = getLastReference(importedReference); if (importDirective.isAllUnder()) { if (referenceExpression == null || !canImportMembersFrom(descriptors, referenceExpression)) return; @@ -147,16 +145,19 @@ public class ImportsResolver { } @NotNull - private Collection lookupDescriptorsForQualifiedExpression(@NotNull JetQualifiedExpression importedReference, @NotNull JetScope outerScope) { + private Collection lookupDescriptorsForQualifiedExpression( + @NotNull JetQualifiedExpression importedReference, @NotNull JetScope outerScope, boolean isForLastPart) { + JetExpression receiverExpression = importedReference.getReceiverExpression(); Collection declarationDescriptors; if (receiverExpression instanceof JetQualifiedExpression) { - declarationDescriptors = lookupDescriptorsForQualifiedExpression((JetQualifiedExpression) receiverExpression, outerScope); + declarationDescriptors = lookupDescriptorsForQualifiedExpression((JetQualifiedExpression) receiverExpression, outerScope, false); } else { assert receiverExpression instanceof JetSimpleNameExpression; - declarationDescriptors = lookupDescriptorsForSimpleNameReference((JetSimpleNameExpression) receiverExpression, outerScope); + declarationDescriptors = lookupDescriptorsForSimpleNameReference((JetSimpleNameExpression) receiverExpression, outerScope, false); } + JetExpression selectorExpression = importedReference.getSelectorExpression(); assert selectorExpression instanceof JetSimpleNameExpression; JetSimpleNameExpression selector = (JetSimpleNameExpression) selectorExpression; @@ -166,7 +167,7 @@ public class ImportsResolver { } for (DeclarationDescriptor declarationDescriptor : declarationDescriptors) { if (declarationDescriptor instanceof NamespaceDescriptor) { - return lookupDescriptorsForSimpleNameReference(selector, ((NamespaceDescriptor) declarationDescriptor).getMemberScope()); + return lookupDescriptorsForSimpleNameReference(selector, ((NamespaceDescriptor) declarationDescriptor).getMemberScope(), isForLastPart); } if (declarationDescriptor instanceof ClassDescriptor) { return lookupObjectMembers(selector, (ClassDescriptor) declarationDescriptor); @@ -195,7 +196,9 @@ public class ImportsResolver { return canImport; } - private boolean canImportMembersFrom(@NotNull DeclarationDescriptor descriptor, @NotNull JetSimpleNameExpression reference, @NotNull BindingTrace trace) { + private boolean canImportMembersFrom(@NotNull DeclarationDescriptor descriptor, + @NotNull JetSimpleNameExpression reference, + @NotNull BindingTrace trace) { assert !firstPhase; if (descriptor instanceof NamespaceDescriptor) { return true; @@ -222,7 +225,7 @@ public class ImportsResolver { if (firstPhase) return Collections.emptyList(); JetType classObjectType = classDescriptor.getClassObjectType(); assert classObjectType != null; - Collection members = lookupDescriptorsForSimpleNameReference(memberReference, classObjectType.getMemberScope()); + Collection members = lookupDescriptorsForSimpleNameReference(memberReference, classObjectType.getMemberScope(), true); return addBoundToReceiver(members, classDescriptor); } @@ -231,17 +234,42 @@ public class ImportsResolver { JetType variableType = variableDescriptor.getReturnType(); if (variableType == null) return Collections.emptyList(); - Collection members = lookupDescriptorsForSimpleNameReference(memberReference, variableType.getMemberScope()); + Collection members = lookupDescriptorsForSimpleNameReference(memberReference, variableType.getMemberScope(), true); return addBoundToReceiver(members, variableDescriptor); } @NotNull - public static Collection addBoundToReceiver(@NotNull Collection descriptors, @NotNull final DeclarationDescriptor receiver) { + public static Collection addBoundToReceiver(@NotNull Collection descriptors, + @NotNull final DeclarationDescriptor receiver) { return Collections2.transform(descriptors, DescriptorUtils.getAddBoundToReceiverFunction(receiver)); } @NotNull - private Collection lookupDescriptorsForSimpleNameReference(@NotNull JetSimpleNameExpression referenceExpression, @NotNull JetScope outerScope) { + 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 isLastPart) { List descriptors = Lists.newArrayList(); String referencedName = referenceExpression.getReferencedName(); @@ -256,9 +284,21 @@ public class ImportsResolver { descriptors.addAll(outerScope.getProperties(referencedName)); } + + storeResolutionResult(descriptors, referenceExpression, bindingScope, isLastPart); + + return descriptors; + } + + private void storeResolutionResult( + @NotNull Collection descriptors, + @NotNull JetSimpleNameExpression referenceExpression, + @NotNull JetScope resolutionScope, + boolean isLastPart) { + if (!firstPhase) { - if (descriptors.size() == 1) { - trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, descriptors.get(0)); + if (descriptors.size() == 1 && !(isLastPart && descriptors.iterator().next() instanceof NamespaceDescriptor)) { + trace.record(BindingContext.REFERENCE_TARGET, referenceExpression, descriptors.iterator().next()); } else if (descriptors.size() > 1) { trace.record(BindingContext.AMBIGUOUS_REFERENCE_TARGET, referenceExpression, descriptors); @@ -268,11 +308,10 @@ public class ImportsResolver { } // If it's not an ambiguous case - store resolution scope - if (descriptors.size() <= 1 && outerScope != JetScope.EMPTY) { - trace.record(BindingContext.RESOLUTION_SCOPE, referenceExpression, outerScope); + if (descriptors.size() <= 1) { + trace.record(BindingContext.RESOLUTION_SCOPE, referenceExpression, resolutionScope); } } - return descriptors; } } } diff --git a/idea/testData/checker/regression/kt960.jet b/idea/testData/checker/regression/kt960.jet new file mode 100644 index 00000000000..0371e95fabf --- /dev/null +++ b/idea/testData/checker/regression/kt960.jet @@ -0,0 +1,8 @@ +// KT-960 import namespace should give unresolved reference +package some + +import java.util + +class Test { + +} \ No newline at end of file