Allow top-level local delegated properties in scripts
This commit is contained in:
@@ -445,6 +445,10 @@ public class PropertyCodegen {
|
||||
else if (parent instanceof KtFile) {
|
||||
container = (KtFile) parent;
|
||||
}
|
||||
else if (KtPsiUtil.isScriptDeclaration(property)) {
|
||||
container = KtPsiUtil.getScript(property);
|
||||
assert container != null : "Script declaration for property '" + property.getText() + "' should be not null!";
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException("Unknown delegated property container: " + parent);
|
||||
}
|
||||
|
||||
@@ -69,6 +69,7 @@ public class ScriptCodegen extends MemberCodegen<KtScript> {
|
||||
private final KtScript scriptDeclaration;
|
||||
private final ScriptContext context;
|
||||
private final ScriptDescriptor scriptDescriptor;
|
||||
private final Type classAsmType;
|
||||
|
||||
private ScriptCodegen(
|
||||
@NotNull KtScript scriptDeclaration,
|
||||
@@ -80,16 +81,15 @@ public class ScriptCodegen extends MemberCodegen<KtScript> {
|
||||
this.scriptDeclaration = scriptDeclaration;
|
||||
this.context = context;
|
||||
this.scriptDescriptor = context.getScriptDescriptor();
|
||||
classAsmType = typeMapper.mapClass(context.getContextDescriptor());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void generateDeclaration() {
|
||||
Type classType = typeMapper.mapClass(context.getContextDescriptor());
|
||||
|
||||
v.defineClass(scriptDeclaration,
|
||||
V1_6,
|
||||
ACC_PUBLIC | ACC_SUPER,
|
||||
classType.getInternalName(),
|
||||
classAsmType.getInternalName(),
|
||||
null,
|
||||
"java/lang/Object",
|
||||
ArrayUtil.EMPTY_STRING_ARRAY);
|
||||
@@ -103,6 +103,11 @@ public class ScriptCodegen extends MemberCodegen<KtScript> {
|
||||
context.intoFunction(scriptDescriptor.getUnsubstitutedPrimaryConstructor()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void generateSyntheticParts() {
|
||||
generatePropertyMetadataArrayFieldIfNeeded(classAsmType);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void generateKotlinMetadataAnnotation() {
|
||||
// TODO
|
||||
|
||||
@@ -385,7 +385,6 @@ public interface Errors {
|
||||
DiagnosticFactory0<KtPropertyDelegate> ABSTRACT_DELEGATED_PROPERTY = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtPropertyAccessor> ACCESSOR_FOR_DELEGATED_PROPERTY = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtPropertyDelegate> DELEGATED_PROPERTY_IN_INTERFACE = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtPropertyDelegate> SCRIPT_TOP_LEVEL_LOCAL_VARIABLE_WITH_DELEGATE = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
DiagnosticFactory0<KtProperty> PROPERTY_WITH_NO_TYPE_NO_INITIALIZER = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE);
|
||||
|
||||
|
||||
-1
@@ -214,7 +214,6 @@ public class DefaultErrorMessages {
|
||||
MAP.put(ABSTRACT_DELEGATED_PROPERTY, "Delegated property cannot be abstract");
|
||||
MAP.put(ACCESSOR_FOR_DELEGATED_PROPERTY, "Delegated property cannot have accessors with non-default implementations");
|
||||
MAP.put(DELEGATED_PROPERTY_IN_INTERFACE, "Delegated properties are not allowed in interfaces");
|
||||
MAP.put(SCRIPT_TOP_LEVEL_LOCAL_VARIABLE_WITH_DELEGATE, "Top-level local variables in scripts are not allowed to have delegates");
|
||||
|
||||
MAP.put(INAPPLICABLE_LATEINIT_MODIFIER, "''lateinit'' modifier {0}", STRING);
|
||||
|
||||
|
||||
@@ -400,14 +400,6 @@ class DeclarationsChecker(
|
||||
exposedChecker.checkProperty(property, propertyDescriptor)
|
||||
checkPropertyTypeParametersAreUsedInReceiverType(propertyDescriptor)
|
||||
checkImplicitCallableType(property, propertyDescriptor)
|
||||
checkDelegatedPropertyInScript(property)
|
||||
}
|
||||
|
||||
private fun checkDelegatedPropertyInScript(property: KtProperty) {
|
||||
val delegate = property.delegate
|
||||
if (delegate != null && KtPsiUtil.isScriptDeclaration(property)) {
|
||||
trace.report(SCRIPT_TOP_LEVEL_LOCAL_VARIABLE_WITH_DELEGATE.on(delegate))
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkPropertyTypeParametersAreUsedInReceiverType(descriptor: PropertyDescriptor) {
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
class Delegate {
|
||||
operator fun getValue(t: Any?, p: KProperty<*>): Int = 3
|
||||
}
|
||||
|
||||
|
||||
val prop: Int by Delegate()
|
||||
|
||||
val x = prop
|
||||
|
||||
// expected: x: 3
|
||||
@@ -8,7 +8,7 @@ class Delegate {
|
||||
}
|
||||
}
|
||||
|
||||
val a: Int <!SCRIPT_TOP_LEVEL_LOCAL_VARIABLE_WITH_DELEGATE!>by Delegate()<!>
|
||||
val a: Int by Delegate()
|
||||
|
||||
class Foo {
|
||||
val a: Int by Delegate()
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
>>> import kotlin.reflect.KProperty;
|
||||
>>> class Delegate {
|
||||
... var inner = 1
|
||||
... operator fun getValue(t: Any?, p: KProperty<*>): Int = inner
|
||||
... operator fun setValue(t: Any?, p: KProperty<*>, i: Int) {
|
||||
... inner = i
|
||||
... }
|
||||
...}
|
||||
|
||||
>>> var prop1: Int = 1
|
||||
>>> prop1
|
||||
1
|
||||
>>> prop1 = 2
|
||||
>>> prop1
|
||||
2
|
||||
>>> var prop2: Int = 100
|
||||
>>> prop2
|
||||
100
|
||||
>>> prop2 = prop2 + 2
|
||||
>>> prop2
|
||||
102
|
||||
>>> prop1
|
||||
2
|
||||
@@ -149,6 +149,12 @@ public class ScriptCodegenTestGenerated extends AbstractScriptCodegenTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("topLevelLocalDelegatedProperty.kts")
|
||||
public void testTopLevelLocalDelegatedProperty() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/script/topLevelLocalDelegatedProperty.kts");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("topLevelProperty.kts")
|
||||
public void testTopLevelProperty() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/script/topLevelProperty.kts");
|
||||
|
||||
@@ -107,6 +107,12 @@ public class ReplInterpreterTestGenerated extends AbstractReplInterpreterTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("topLevelLocalDelegatedProperty.repl")
|
||||
public void testTopLevelLocalDelegatedProperty() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/repl/topLevelLocalDelegatedProperty.repl");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("twoClosures.repl")
|
||||
public void testTwoClosures() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/repl/twoClosures.repl");
|
||||
|
||||
Reference in New Issue
Block a user