Add labels for extension properties

#KT-2824 Fixed
This commit is contained in:
Natalia.Ukhorskaya
2012-11-09 11:52:17 +04:00
parent d4212ecdfc
commit 94fbf2bdf4
15 changed files with 401 additions and 11 deletions
@@ -108,7 +108,7 @@ public interface LocalLookup {
RECEIVER {
@Override
public boolean isCase(DeclarationDescriptor d, GenerationState state) {
return d instanceof FunctionDescriptor;
return d instanceof CallableDescriptor;
}
@Override
@@ -130,7 +130,7 @@ public interface LocalLookup {
@Override
public StackValue outerValue(EnclosedValueDescriptor d, ExpressionCodegen expressionCodegen) {
CallableDescriptor descriptor = (FunctionDescriptor) d.getDescriptor();
CallableDescriptor descriptor = (CallableDescriptor) d.getDescriptor();
return StackValue.local(descriptor.getExpectedThisObject() != null ? 1 : 0, d.getType());
}
};
@@ -434,7 +434,7 @@ public class BodyResolver {
JetScope declaringScope = context.getDeclaringScopes().apply(accessor);
JetScope propertyDeclarationInnerScope = descriptorResolver.getPropertyDeclarationInnerScope(
declaringScope, propertyDescriptor.getTypeParameters(), propertyDescriptor.getReceiverParameter(), trace);
propertyDescriptor, declaringScope, propertyDescriptor.getTypeParameters(), propertyDescriptor.getReceiverParameter(), trace);
WritableScope accessorScope = new WritableScopeImpl(
propertyDeclarationInnerScope, declaringScope.getContainingDeclaration(), new TraceBasedRedeclarationHandler(trace), "Accessor scope");
accessorScope.changeLockLevel(WritableScope.LockLevel.READING);
@@ -479,7 +479,8 @@ public class BodyResolver {
public void resolvePropertyInitializer(JetProperty property, PropertyDescriptor propertyDescriptor, JetExpression initializer, JetScope scope) {
JetType expectedTypeForInitializer = property.getTypeRef() != null ? propertyDescriptor.getType() : NO_EXPECTED_TYPE;
JetScope propertyDeclarationInnerScope = descriptorResolver.getPropertyDeclarationInnerScope(scope, propertyDescriptor.getTypeParameters(), NO_RECEIVER_PARAMETER, trace);
JetScope propertyDeclarationInnerScope = descriptorResolver.getPropertyDeclarationInnerScopeForInitializer(
scope, propertyDescriptor.getTypeParameters(), NO_RECEIVER_PARAMETER, trace);
expressionTypingServices.getType(propertyDeclarationInnerScope, initializer, expectedTypeForInitializer, DataFlowInfo.EMPTY, trace);
}
@@ -839,12 +839,39 @@ public class DescriptorResolver {
}
public JetScope getPropertyDeclarationInnerScope(
@NotNull JetScope outerScope, @NotNull List<? extends TypeParameterDescriptor> typeParameters,
@Nullable ReceiverParameterDescriptor receiver, BindingTrace trace
@NotNull PropertyDescriptor propertyDescriptor,
@NotNull JetScope outerScope,
@NotNull List<? extends TypeParameterDescriptor> typeParameters,
@Nullable ReceiverParameterDescriptor receiver,
BindingTrace trace
) {
return getPropertyDeclarationInnerScope(propertyDescriptor, outerScope, typeParameters, receiver, trace, true);
}
public JetScope getPropertyDeclarationInnerScopeForInitializer(
@NotNull JetScope outerScope,
@NotNull List<? extends TypeParameterDescriptor> typeParameters,
@Nullable ReceiverParameterDescriptor receiver,
BindingTrace trace
) {
return getPropertyDeclarationInnerScope(null, outerScope, typeParameters, receiver, trace, false);
}
private JetScope getPropertyDeclarationInnerScope(
@Nullable PropertyDescriptor propertyDescriptor, // PropertyDescriptor can be null for property scope which hasn't label to property (in this case addLabelForProperty parameter must be false
@NotNull JetScope outerScope,
@NotNull List<? extends TypeParameterDescriptor> typeParameters,
@Nullable ReceiverParameterDescriptor receiver,
BindingTrace trace,
boolean addLabelForProperty
) {
WritableScopeImpl result = new WritableScopeImpl(
outerScope, outerScope.getContainingDeclaration(), new TraceBasedRedeclarationHandler(trace),
"Property declaration inner scope");
if (addLabelForProperty) {
assert propertyDescriptor != null : "PropertyDescriptor can be null for property scope which hasn't label to property";
result.addLabeledDeclaration(propertyDescriptor);
}
for (TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
result.addTypeParameterDescriptor(typeParameterDescriptor);
}
@@ -909,7 +936,8 @@ public class DescriptorResolver {
ReceiverParameterDescriptor receiverDescriptor = resolveReceiverParameterFor(propertyDescriptor, receiverType);
JetScope propertyScope = getPropertyDeclarationInnerScope(scope, typeParameterDescriptors, NO_RECEIVER_PARAMETER, trace);
JetScope propertyScope = getPropertyDeclarationInnerScope(propertyDescriptor, scope, typeParameterDescriptors,
NO_RECEIVER_PARAMETER, trace);
JetType type = getVariableType(propertyScope, property, DataFlowInfo.EMPTY, true, trace);
@@ -19,10 +19,7 @@ package org.jetbrains.jet.lang.types.expressions;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
@@ -140,6 +137,10 @@ public class LabelResolver {
FunctionDescriptor functionDescriptor = (FunctionDescriptor) declarationDescriptor;
thisReceiver = functionDescriptor.getReceiverParameter();
}
else if (declarationDescriptor instanceof PropertyDescriptor) {
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) declarationDescriptor;
thisReceiver = propertyDescriptor.getReceiverParameter();
}
else {
throw new UnsupportedOperationException("Unsupported descriptor: " + declarationDescriptor); // TODO
}
@@ -0,0 +1,29 @@
val Int.getter: Int
get() {
return this@getter
}
var Int.setter1: Int = 2
get() {
return this@setter1
}
set(i: Int) {
$setter1 = this@setter1
}
var Int.setter2: Int = 2
set(i: Int) {
$setter2 = this@setter2
}
fun box(): String {
val i = 1
if (i.getter != 1) return "getter failed"
i.setter1 = 2
if (i.setter1 != 1) return "setter1 failed"
i.setter2 = 2
if (i.setter2 != 1) return "setter2 failed"
return "OK"
}
@@ -0,0 +1,23 @@
val Int.getter: Int
get() {
return {
this@getter
}.invoke()
}
var Int.setter: Int = 1
set(i: Int) {
$setter = {
this@setter
}.invoke()
}
fun box(): String {
val i = 1
if (i.getter != 1) return "getter failed"
i.setter = 2
if (i.setter != 1) return "setter failed"
return "OK"
}
@@ -0,0 +1,27 @@
val Int.getter: Int
get() {
val extFun = { Int.() ->
this@getter
}
return this@getter.extFun()
}
var Int.setter: Int = 1
set(i: Int) {
val extFun = { Int.() ->
this@setter
}
this@setter.extFun()
}
fun box(): String {
val i = 1
if (i.getter != 1) return "getter failed"
i.setter = 1
if (i.setter != 1) return "setter failed"
return "OK"
}
@@ -0,0 +1,53 @@
trait Base {
fun foo(): Int
}
val Int.getter: Int
get() {
return object: Base {
override fun foo(): Int {
return this@getter
}
}.foo()
}
var Int.setter1: Int = 2
set(i: Int) {
$setter1 = object: Base {
override fun foo(): Int {
this@setter1
return 1
}
}.foo()
}
var Int.setter2: Int = 2
get() {
return object: Base {
override fun foo(): Int {
return this@setter2
}
}.foo()
}
set(i: Int) {
$setter2 = object: Base {
override fun foo(): Int {
this@setter2
return 1
}
}.foo()
}
fun box(): String {
val i = 1
if (i.getter != 1) return "getter failed"
i.setter1 = 2
if (i.setter1 != 1) return "setter1 failed"
i.setter2 = 2
if (i.setter2 != 1) return "setter2 failed"
return "OK"
}
@@ -0,0 +1,17 @@
class Test {
val Int.innerGetter: Int
get() {
return this@innerGetter
}
fun test(): Int {
val i = 1
if (i.innerGetter != 1) return 0
return 1
}
}
fun box(): String {
if (Test().test() != 1) return "inner getter or setter failed"
return "OK"
}
@@ -0,0 +1,8 @@
trait Base {
fun foo()
}
val String.test: Base = object: Base {
override fun foo() {
this<!UNRESOLVED_REFERENCE!>@test<!>
}
}
@@ -0,0 +1,47 @@
trait Base {
fun foo()
}
val ~getter1~Int.getter1: Int
get() {
return `getter1`this@getter1
}
val ~getter2~Int.getter2: Base
get() {
return object: Base {
override fun foo() {
`getter2`this@getter2
}
}
}
val ~getter3~Int.getter3: Base
get() = object: Base {
override fun foo() {
`getter3`this@getter3
}
}
val ~getter4~Int.getter4: Int
get() {
return {
`getter4`this@getter4
}.invoke()
}
val ~getter5~Int.getter5: Int
get() {
val extFun = { Int.() ->
`getter5`this@getter5
}
return `getter5`this@getter5.extFun()
}
class Test {
val ~innerGetter1~Int.innerGetter1: Int
get() {
return `innerGetter1`this@innerGetter1
}
}
@@ -0,0 +1,32 @@
trait Base {
fun foo()
}
var ~setter1~Int.setter1: Int = 2
set(i: Int) {
$setter1 = `setter1`this@setter1
}
var ~setter2~Int.setter2: Base? = null
set(i: Base?) {
$setter2 = object: Base {
override fun foo() {
`setter2`this@setter2
}
}
}
var ~setter3~Int.setter3: Int = 1
set(i: Int) {
{
`setter3`this@setter3
}.invoke()
}
var ~setter4~Int.setter4: Int = 1
set(i: Int) {
val extFun = { Int.() ->
`setter4`this@setter4
}
`setter4`this@setter4.extFun()
}
@@ -3570,6 +3570,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
doTest("compiler/testData/diagnostics/tests/thisAndSuper/thisInNestedClasses.kt");
}
@TestMetadata("thisInPropertyInitializer.kt")
public void testThisInPropertyInitializer() throws Exception {
doTest("compiler/testData/diagnostics/tests/thisAndSuper/thisInPropertyInitializer.kt");
}
@TestMetadata("thisInToplevelFunction.kt")
public void testThisInToplevelFunction() throws Exception {
doTest("compiler/testData/diagnostics/tests/thisAndSuper/thisInToplevelFunction.kt");
@@ -0,0 +1,58 @@
/*
* Copyright 2010-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.codegen.labels;
import org.jetbrains.jet.ConfigurationKind;
import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment;
import org.jetbrains.jet.codegen.CodegenTestCase;
import org.jetbrains.jet.test.generator.SimpleTestClassModel;
import org.jetbrains.jet.test.generator.TestGenerator;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
public abstract class AbstractLabelGenTest extends CodegenTestCase {
private static final String REDUNDANT_PATH_PREFIX = "compiler/testData/codegen";
@Override
public void setUp() throws Exception {
super.setUp();
createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_AND_ANNOTATIONS);
}
protected void doTest(String path) throws IOException {
String relativePath = path.substring(REDUNDANT_PATH_PREFIX.length());
blackBoxFile(relativePath);
}
public static void main(String[] args) throws IOException {
String aPackage = "org.jetbrains.jet.codegen.labels";
Class<AbstractLabelGenTest> thisClass = AbstractLabelGenTest.class;
new TestGenerator(
"compiler/tests/",
aPackage,
"LabelGenTestGenerated",
thisClass,
Arrays.asList(
new SimpleTestClassModel(new File("compiler/testData/codegen/label"), true, "kt", "doTest")
),
thisClass
).generateAndSave();
}
}
@@ -0,0 +1,61 @@
/*
* Copyright 2010-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.codegen.labels;
import junit.framework.Assert;
import junit.framework.Test;
import junit.framework.TestSuite;
import java.io.File;
import org.jetbrains.jet.JetTestUtils;
import org.jetbrains.jet.test.InnerTestClasses;
import org.jetbrains.jet.test.TestMetadata;
import org.jetbrains.jet.codegen.labels.AbstractLabelGenTest;
/** This class is generated by {@link org.jetbrains.jet.codegen.labels.AbstractLabelGenTest}. DO NOT MODIFY MANUALLY */
@TestMetadata("compiler/testData/codegen/label")
public class LabelGenTestGenerated extends AbstractLabelGenTest {
public void testAllFilesPresentInLabel() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.codegen.labels.AbstractLabelGenTest", new File("compiler/testData/codegen/label"), "kt", true);
}
@TestMetadata("propertyAccessor.kt")
public void testPropertyAccessor() throws Exception {
doTest("compiler/testData/codegen/label/propertyAccessor.kt");
}
@TestMetadata("propertyAccessorFunctionLiteral.kt")
public void testPropertyAccessorFunctionLiteral() throws Exception {
doTest("compiler/testData/codegen/label/propertyAccessorFunctionLiteral.kt");
}
@TestMetadata("propertyAccessorInnerExtensionFun.kt")
public void testPropertyAccessorInnerExtensionFun() throws Exception {
doTest("compiler/testData/codegen/label/propertyAccessorInnerExtensionFun.kt");
}
@TestMetadata("propertyAccessorObject.kt")
public void testPropertyAccessorObject() throws Exception {
doTest("compiler/testData/codegen/label/propertyAccessorObject.kt");
}
@TestMetadata("propertyInClassAccessor.kt")
public void testPropertyInClassAccessor() throws Exception {
doTest("compiler/testData/codegen/label/propertyInClassAccessor.kt");
}
}