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) {
|
else if (parent instanceof KtFile) {
|
||||||
container = (KtFile) parent;
|
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 {
|
else {
|
||||||
throw new UnsupportedOperationException("Unknown delegated property container: " + parent);
|
throw new UnsupportedOperationException("Unknown delegated property container: " + parent);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ public class ScriptCodegen extends MemberCodegen<KtScript> {
|
|||||||
private final KtScript scriptDeclaration;
|
private final KtScript scriptDeclaration;
|
||||||
private final ScriptContext context;
|
private final ScriptContext context;
|
||||||
private final ScriptDescriptor scriptDescriptor;
|
private final ScriptDescriptor scriptDescriptor;
|
||||||
|
private final Type classAsmType;
|
||||||
|
|
||||||
private ScriptCodegen(
|
private ScriptCodegen(
|
||||||
@NotNull KtScript scriptDeclaration,
|
@NotNull KtScript scriptDeclaration,
|
||||||
@@ -80,16 +81,15 @@ public class ScriptCodegen extends MemberCodegen<KtScript> {
|
|||||||
this.scriptDeclaration = scriptDeclaration;
|
this.scriptDeclaration = scriptDeclaration;
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.scriptDescriptor = context.getScriptDescriptor();
|
this.scriptDescriptor = context.getScriptDescriptor();
|
||||||
|
classAsmType = typeMapper.mapClass(context.getContextDescriptor());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void generateDeclaration() {
|
protected void generateDeclaration() {
|
||||||
Type classType = typeMapper.mapClass(context.getContextDescriptor());
|
|
||||||
|
|
||||||
v.defineClass(scriptDeclaration,
|
v.defineClass(scriptDeclaration,
|
||||||
V1_6,
|
V1_6,
|
||||||
ACC_PUBLIC | ACC_SUPER,
|
ACC_PUBLIC | ACC_SUPER,
|
||||||
classType.getInternalName(),
|
classAsmType.getInternalName(),
|
||||||
null,
|
null,
|
||||||
"java/lang/Object",
|
"java/lang/Object",
|
||||||
ArrayUtil.EMPTY_STRING_ARRAY);
|
ArrayUtil.EMPTY_STRING_ARRAY);
|
||||||
@@ -103,6 +103,11 @@ public class ScriptCodegen extends MemberCodegen<KtScript> {
|
|||||||
context.intoFunction(scriptDescriptor.getUnsubstitutedPrimaryConstructor()));
|
context.intoFunction(scriptDescriptor.getUnsubstitutedPrimaryConstructor()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void generateSyntheticParts() {
|
||||||
|
generatePropertyMetadataArrayFieldIfNeeded(classAsmType);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void generateKotlinMetadataAnnotation() {
|
protected void generateKotlinMetadataAnnotation() {
|
||||||
// TODO
|
// TODO
|
||||||
|
|||||||
@@ -385,7 +385,6 @@ public interface Errors {
|
|||||||
DiagnosticFactory0<KtPropertyDelegate> ABSTRACT_DELEGATED_PROPERTY = DiagnosticFactory0.create(ERROR);
|
DiagnosticFactory0<KtPropertyDelegate> ABSTRACT_DELEGATED_PROPERTY = DiagnosticFactory0.create(ERROR);
|
||||||
DiagnosticFactory0<KtPropertyAccessor> ACCESSOR_FOR_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> 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);
|
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(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(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(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);
|
MAP.put(INAPPLICABLE_LATEINIT_MODIFIER, "''lateinit'' modifier {0}", STRING);
|
||||||
|
|
||||||
|
|||||||
@@ -400,14 +400,6 @@ class DeclarationsChecker(
|
|||||||
exposedChecker.checkProperty(property, propertyDescriptor)
|
exposedChecker.checkProperty(property, propertyDescriptor)
|
||||||
checkPropertyTypeParametersAreUsedInReceiverType(propertyDescriptor)
|
checkPropertyTypeParametersAreUsedInReceiverType(propertyDescriptor)
|
||||||
checkImplicitCallableType(property, 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) {
|
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 {
|
class Foo {
|
||||||
val a: Int by Delegate()
|
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);
|
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")
|
@TestMetadata("topLevelProperty.kts")
|
||||||
public void testTopLevelProperty() throws Exception {
|
public void testTopLevelProperty() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/script/topLevelProperty.kts");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/script/topLevelProperty.kts");
|
||||||
|
|||||||
@@ -107,6 +107,12 @@ public class ReplInterpreterTestGenerated extends AbstractReplInterpreterTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("topLevelLocalDelegatedProperty.repl")
|
||||||
|
public void testTopLevelLocalDelegatedProperty() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/repl/topLevelLocalDelegatedProperty.repl");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("twoClosures.repl")
|
@TestMetadata("twoClosures.repl")
|
||||||
public void testTwoClosures() throws Exception {
|
public void testTwoClosures() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/repl/twoClosures.repl");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/repl/twoClosures.repl");
|
||||||
|
|||||||
Reference in New Issue
Block a user