Private constructors are now accessed via synthetic constructor with DEFAULT_CONSTRUCTOR_MARKER as an additional argument #KT-6299 Fixed
A set of tests provided. Some external tests fixed accordingly. Companion object creation changed accordingly. Derived classes now can use base class with the private constructor. Refactoring of AccessorForFunctionDescriptor.
This commit is contained in:
+47
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.kotlin.codegen
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import java.util.*
|
||||
|
||||
open public class AbstractAccessorForFunctionDescriptor(
|
||||
containingDeclaration: DeclarationDescriptor,
|
||||
name: Name
|
||||
) : SimpleFunctionDescriptorImpl(containingDeclaration, null, Annotations.EMPTY,
|
||||
name, CallableMemberDescriptor.Kind.DECLARATION, SourceElement.NO_SOURCE) {
|
||||
|
||||
protected fun copyTypeParameters(descriptor: FunctionDescriptor): List<TypeParameterDescriptor> = descriptor.getTypeParameters().map {
|
||||
val copy = TypeParameterDescriptorImpl.createForFurtherModification(
|
||||
this, it.getAnnotations(), it.isReified(),
|
||||
it.getVariance(), it.getName(),
|
||||
it.getIndex(), SourceElement.NO_SOURCE)
|
||||
for (upperBound in it.getUpperBounds()) {
|
||||
copy.addUpperBound(upperBound)
|
||||
}
|
||||
copy.setInitialized()
|
||||
copy
|
||||
}
|
||||
|
||||
protected fun copyValueParameters(descriptor: FunctionDescriptor): List<ValueParameterDescriptor> =
|
||||
descriptor.getValueParameters().map { it.copy(this, it.getName()) }
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2010-2015 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.kotlin.codegen
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
import java.util.*
|
||||
|
||||
public class AccessorForConstructorDescriptor(
|
||||
private val calleeDescriptor: ConstructorDescriptor,
|
||||
containingDeclaration: DeclarationDescriptor
|
||||
) : AbstractAccessorForFunctionDescriptor(containingDeclaration, Name.special("<init>"))
|
||||
, ConstructorDescriptor
|
||||
, AccessorForCallableDescriptor<ConstructorDescriptor> {
|
||||
|
||||
override fun getCalleeDescriptor(): ConstructorDescriptor = calleeDescriptor
|
||||
|
||||
override fun getContainingDeclaration(): ClassDescriptor = calleeDescriptor.getContainingDeclaration()
|
||||
|
||||
override fun isPrimary(): Boolean = false
|
||||
|
||||
init {
|
||||
initialize(
|
||||
DescriptorUtils.getReceiverParameterType(getExtensionReceiverParameter()),
|
||||
calleeDescriptor.getDispatchReceiverParameter(),
|
||||
copyTypeParameters(calleeDescriptor),
|
||||
copyValueParameters(calleeDescriptor),
|
||||
calleeDescriptor.getReturnType(),
|
||||
Modality.FINAL,
|
||||
Visibilities.INTERNAL
|
||||
)
|
||||
}
|
||||
}
|
||||
+3
-39
@@ -18,20 +18,13 @@ package org.jetbrains.kotlin.codegen;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
||||
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl;
|
||||
import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.resolve.annotations.AnnotationsPackage;
|
||||
import org.jetbrains.kotlin.types.JetType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor.NO_RECEIVER_PARAMETER;
|
||||
|
||||
public class AccessorForFunctionDescriptor extends SimpleFunctionDescriptorImpl implements AccessorForCallableDescriptor<FunctionDescriptor> {
|
||||
public class AccessorForFunctionDescriptor extends AbstractAccessorForFunctionDescriptor implements AccessorForCallableDescriptor<FunctionDescriptor> {
|
||||
|
||||
private final FunctionDescriptor calleeDescriptor;
|
||||
|
||||
@@ -40,9 +33,8 @@ public class AccessorForFunctionDescriptor extends SimpleFunctionDescriptorImpl
|
||||
@NotNull DeclarationDescriptor containingDeclaration,
|
||||
int index
|
||||
) {
|
||||
super(containingDeclaration, null, Annotations.EMPTY,
|
||||
Name.identifier("access$" + (descriptor instanceof ConstructorDescriptor ? "init" : descriptor.getName()) + "$" + index),
|
||||
Kind.DECLARATION, SourceElement.NO_SOURCE);
|
||||
super(containingDeclaration,
|
||||
Name.identifier("access$" + (descriptor instanceof ConstructorDescriptor ? "init" : descriptor.getName()) + "$" + index));
|
||||
this.calleeDescriptor = descriptor;
|
||||
|
||||
initialize(DescriptorUtils.getReceiverParameterType(descriptor.getExtensionReceiverParameter()),
|
||||
@@ -56,34 +48,6 @@ public class AccessorForFunctionDescriptor extends SimpleFunctionDescriptorImpl
|
||||
Visibilities.INTERNAL);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private List<TypeParameterDescriptor> copyTypeParameters(@NotNull FunctionDescriptor descriptor) {
|
||||
List<TypeParameterDescriptor> typeParameters = descriptor.getTypeParameters();
|
||||
List<TypeParameterDescriptor> result = new ArrayList<TypeParameterDescriptor>(typeParameters.size());
|
||||
for (TypeParameterDescriptor typeParameter : typeParameters) {
|
||||
TypeParameterDescriptorImpl copy = TypeParameterDescriptorImpl.createForFurtherModification(
|
||||
this, typeParameter.getAnnotations(), typeParameter.isReified(),
|
||||
typeParameter.getVariance(), typeParameter.getName(), typeParameter.getIndex(), SourceElement.NO_SOURCE
|
||||
);
|
||||
for (JetType upperBound : typeParameter.getUpperBounds()) {
|
||||
copy.addUpperBound(upperBound);
|
||||
}
|
||||
copy.setInitialized();
|
||||
result.add(copy);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private List<ValueParameterDescriptor> copyValueParameters(@NotNull FunctionDescriptor descriptor) {
|
||||
List<ValueParameterDescriptor> valueParameters = descriptor.getValueParameters();
|
||||
List<ValueParameterDescriptor> result = new ArrayList<ValueParameterDescriptor>(valueParameters.size());
|
||||
for (ValueParameterDescriptor valueParameter : valueParameters) {
|
||||
result.add(valueParameter.copy(this, valueParameter.getName()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public FunctionDescriptor getCalleeDescriptor() {
|
||||
|
||||
@@ -170,7 +170,7 @@ public class AsmUtil {
|
||||
|
||||
public static boolean isStaticMethod(OwnerKind kind, CallableMemberDescriptor functionDescriptor) {
|
||||
return isStaticKind(kind) ||
|
||||
JetTypeMapper.isAccessor(functionDescriptor) ||
|
||||
JetTypeMapper.isStaticAccessor(functionDescriptor) ||
|
||||
AnnotationsPackage.isPlatformStaticInObjectOrClass(functionDescriptor);
|
||||
}
|
||||
|
||||
|
||||
@@ -70,6 +70,8 @@ import org.jetbrains.kotlin.resolve.constants.evaluate.EvaluatePackage;
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilPackage;
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil;
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm;
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind;
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature;
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.*;
|
||||
import org.jetbrains.kotlin.types.Approximation;
|
||||
@@ -2410,6 +2412,16 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
callGenerator.putValueIfNeeded(null, Type.INT_TYPE, StackValue.constant(mask, Type.INT_TYPE));
|
||||
}
|
||||
|
||||
// Extra constructor marker argument
|
||||
if (callableMethod instanceof CallableMethod) {
|
||||
List<JvmMethodParameterSignature> callableParameters = ((CallableMethod) callableMethod).getValueParameters();
|
||||
for (JvmMethodParameterSignature parameter: callableParameters) {
|
||||
if (parameter.getKind() == JvmMethodParameterKind.CONSTRUCTOR_MARKER) {
|
||||
callGenerator.putValueIfNeeded(null, parameter.getAsmType(), StackValue.constant(null, parameter.getAsmType()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
callGenerator.genCall(callableMethod, resolvedCall, !masks.isEmpty(), this);
|
||||
}
|
||||
|
||||
@@ -3385,6 +3397,14 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
return generateConstructorCall(resolvedCall, type);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ConstructorDescriptor getConstructorDescriptor(@NotNull ResolvedCall<?> resolvedCall) {
|
||||
FunctionDescriptor accessibleDescriptor = accessibleFunctionDescriptor(resolvedCall);
|
||||
assert accessibleDescriptor instanceof ConstructorDescriptor :
|
||||
"getConstructorDescriptor must be called only for constructors: " + accessibleDescriptor;
|
||||
return (ConstructorDescriptor) accessibleDescriptor;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public StackValue generateConstructorCall(@NotNull final ResolvedCall<?> resolvedCall, @NotNull final Type objectType) {
|
||||
return StackValue.functionCall(objectType, new Function1<InstructionAdapter, Unit>() {
|
||||
@@ -3393,7 +3413,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
v.anew(objectType);
|
||||
v.dup();
|
||||
|
||||
ConstructorDescriptor constructor = (ConstructorDescriptor) resolvedCall.getResultingDescriptor();
|
||||
ConstructorDescriptor constructor = getConstructorDescriptor(resolvedCall);
|
||||
|
||||
ReceiverParameterDescriptor dispatchReceiver = constructor.getDispatchReceiverParameter();
|
||||
if (dispatchReceiver != null) {
|
||||
|
||||
@@ -57,6 +57,7 @@ import org.jetbrains.kotlin.resolve.calls.model.ExpressionValueArgument;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.VarargValueArgument;
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilPackage;
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes;
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmClassSignature;
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind;
|
||||
@@ -831,7 +832,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
private void generateSyntheticAccessor(Map.Entry<DeclarationDescriptor, DeclarationDescriptor> entry) {
|
||||
if (entry.getValue() instanceof FunctionDescriptor) {
|
||||
FunctionDescriptor bridge = (FunctionDescriptor) entry.getValue();
|
||||
final FunctionDescriptor bridge = (FunctionDescriptor) entry.getValue();
|
||||
final FunctionDescriptor original = (FunctionDescriptor) entry.getKey();
|
||||
functionCodegen.generateMethod(
|
||||
Synthetic(null, original), bridge,
|
||||
@@ -840,7 +841,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
public void doGenerateBody(@NotNull ExpressionCodegen codegen, @NotNull JvmMethodSignature signature) {
|
||||
markLineNumberForSyntheticFunction(descriptor, codegen.v);
|
||||
|
||||
generateMethodCallTo(original, codegen.v);
|
||||
generateMethodCallTo(original, bridge, codegen.v);
|
||||
codegen.v.areturn(signature.getReturnType());
|
||||
}
|
||||
}
|
||||
@@ -921,15 +922,21 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
}
|
||||
|
||||
private void generateMethodCallTo(FunctionDescriptor functionDescriptor, InstructionAdapter iv) {
|
||||
private void generateMethodCallTo(
|
||||
@NotNull FunctionDescriptor functionDescriptor,
|
||||
@Nullable FunctionDescriptor bridgeDescriptor,
|
||||
@NotNull InstructionAdapter iv
|
||||
) {
|
||||
boolean isConstructor = functionDescriptor instanceof ConstructorDescriptor;
|
||||
boolean callFromAccessor = !JetTypeMapper.isAccessor(functionDescriptor);
|
||||
boolean bridgeIsAccessorConstructor = bridgeDescriptor instanceof AccessorForConstructorDescriptor;
|
||||
boolean callFromAccessor = bridgeIsAccessorConstructor
|
||||
|| (bridgeDescriptor != null && JetTypeMapper.isAccessor(bridgeDescriptor));
|
||||
CallableMethod callableMethod = isConstructor ?
|
||||
typeMapper.mapToCallableMethod((ConstructorDescriptor) functionDescriptor) :
|
||||
typeMapper.mapToCallableMethod(functionDescriptor, callFromAccessor, context);
|
||||
|
||||
int reg = 1;
|
||||
if (isConstructor) {
|
||||
if (isConstructor && !bridgeIsAccessorConstructor) {
|
||||
iv.anew(callableMethod.getOwner());
|
||||
iv.dup();
|
||||
reg = 0;
|
||||
@@ -941,8 +948,13 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
|
||||
for (Type argType : callableMethod.getParameterTypes()) {
|
||||
iv.load(reg, argType);
|
||||
reg += argType.getSize();
|
||||
if (AsmTypes.DEFAULT_CONSTRUCTOR_MARKER.equals(argType)) {
|
||||
iv.aconst(null);
|
||||
}
|
||||
else {
|
||||
iv.load(reg, argType);
|
||||
reg += argType.getSize();
|
||||
}
|
||||
}
|
||||
callableMethod.genInvokeInstruction(iv);
|
||||
}
|
||||
@@ -1036,7 +1048,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
private void generateCompanionObjectInitializer(@NotNull ClassDescriptor companionObject) {
|
||||
ExpressionCodegen codegen = createOrGetClInitCodegen();
|
||||
FunctionDescriptor constructor = context.accessibleFunctionDescriptor(KotlinPackage.single(companionObject.getConstructors()));
|
||||
generateMethodCallTo(constructor, codegen.v);
|
||||
generateMethodCallTo(constructor, null, codegen.v);
|
||||
codegen.v.dup();
|
||||
StackValue instance = StackValue.onStack(typeMapper.mapClass(companionObject));
|
||||
StackValue.singleton(companionObject, typeMapper).store(instance, codegen.v, true);
|
||||
@@ -1475,7 +1487,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
return;
|
||||
}
|
||||
iv.load(0, OBJECT_TYPE);
|
||||
ConstructorDescriptor delegateConstructor = SamCodegenUtil.resolveSamAdapter(delegationConstructorCall.getResultingDescriptor());
|
||||
ConstructorDescriptor delegateConstructor = SamCodegenUtil.resolveSamAdapter(codegen.getConstructorDescriptor(delegationConstructorCall));
|
||||
|
||||
CallableMethod delegateConstructorCallable = typeMapper.mapToCallableMethod(delegateConstructor);
|
||||
CallableMethod callable = typeMapper.mapToCallableMethod(constructorDescriptor);
|
||||
|
||||
@@ -241,9 +241,12 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
}
|
||||
|
||||
int accessorIndex = accessors.size();
|
||||
if (descriptor instanceof SimpleFunctionDescriptor || descriptor instanceof ConstructorDescriptor) {
|
||||
if (descriptor instanceof SimpleFunctionDescriptor) {
|
||||
accessor = new AccessorForFunctionDescriptor((FunctionDescriptor) descriptor, contextDescriptor, accessorIndex);
|
||||
}
|
||||
else if (descriptor instanceof ConstructorDescriptor) {
|
||||
accessor = new AccessorForConstructorDescriptor((ConstructorDescriptor) descriptor, contextDescriptor);
|
||||
}
|
||||
else if (descriptor instanceof PropertyDescriptor) {
|
||||
if (isForBackingFieldInOuterClass) {
|
||||
accessor = new AccessorForPropertyBackingFieldInOuterClass((PropertyDescriptor) descriptor, contextDescriptor,
|
||||
|
||||
@@ -584,7 +584,7 @@ public class JetTypeMapper {
|
||||
}
|
||||
else {
|
||||
if (isStaticDeclaration(functionDescriptor) ||
|
||||
isAccessor(functionDescriptor) ||
|
||||
isStaticAccessor(functionDescriptor) ||
|
||||
AnnotationsPackage.isPlatformStaticInObjectOrClass(functionDescriptor)) {
|
||||
invokeOpcode = INVOKESTATIC;
|
||||
}
|
||||
@@ -643,6 +643,11 @@ public class JetTypeMapper {
|
||||
return descriptor instanceof AccessorForCallableDescriptor<?>;
|
||||
}
|
||||
|
||||
public static boolean isStaticAccessor(@NotNull CallableMemberDescriptor descriptor) {
|
||||
if (descriptor instanceof AccessorForConstructorDescriptor) return false;
|
||||
return isAccessor(descriptor);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static FunctionDescriptor findAnyDeclaration(@NotNull FunctionDescriptor function) {
|
||||
if (function.getKind() == CallableMemberDescriptor.Kind.DECLARATION) {
|
||||
@@ -748,6 +753,10 @@ public class JetTypeMapper {
|
||||
writeParameter(sw, parameter.getType());
|
||||
}
|
||||
|
||||
if (f instanceof AccessorForConstructorDescriptor) {
|
||||
writeParameter(sw, JvmMethodParameterKind.CONSTRUCTOR_MARKER, DEFAULT_CONSTRUCTOR_MARKER);
|
||||
}
|
||||
|
||||
writeVoidReturn(sw);
|
||||
}
|
||||
else {
|
||||
|
||||
+2
-1
@@ -23,7 +23,8 @@ public enum JvmMethodParameterKind {
|
||||
RECEIVER,
|
||||
CAPTURED_LOCAL_VARIABLE,
|
||||
ENUM_NAME_OR_ORDINAL,
|
||||
SUPER_CALL_PARAM;
|
||||
SUPER_CALL_PARAM,
|
||||
CONSTRUCTOR_MARKER;
|
||||
|
||||
public boolean isSkippedInGenericSignature() {
|
||||
return this == OUTER || this == ENUM_NAME_OR_ORDINAL;
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
// See also KT-6299
|
||||
public open class Outer private constructor() {
|
||||
class Inner: Outer()
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val outer = Outer.Inner()
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
// See also KT-6299
|
||||
public open class Outer private constructor() {
|
||||
companion object {
|
||||
fun foo() = Outer()
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val outer = Outer.foo()
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
// See also KT-6299
|
||||
public open class Outer private constructor() {
|
||||
companion object {
|
||||
inline fun foo() = Outer()
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val outer = Outer.foo()
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
// See also KT-6299
|
||||
public open class Outer private constructor(val s: String) {
|
||||
inner class Inner: Outer("O") {
|
||||
fun foo(): String {
|
||||
return this.s + this@Outer.s
|
||||
}
|
||||
}
|
||||
class Nested: Outer("K")
|
||||
fun bar() = Inner()
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val inner = Outer.Nested().bar()
|
||||
return inner.foo()
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
// See also KT-6299
|
||||
public open class Outer private constructor(val x: Int) {
|
||||
constructor(): this(42)
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val outer = Outer()
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// See also KT-6299
|
||||
public open class Outer private constructor(val s: String, val f: Boolean = true) {
|
||||
class Inner: Outer("xyz")
|
||||
class Other: Outer("abc", true)
|
||||
class Another: Outer("", false)
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val outer = Outer.Inner()
|
||||
val other = Outer.Other()
|
||||
val another = Outer.Another()
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
// See also KT-6299
|
||||
public open class Outer private constructor(val x: Int = 0) {
|
||||
class Inner: Outer()
|
||||
class Other: Outer(42)
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val outer = Outer.Inner()
|
||||
val other = Outer.Other()
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// See also KT-6299
|
||||
public open class Outer private constructor(val p: Outer?) {
|
||||
object First: Outer(null)
|
||||
class Other(p: Outer = First): Outer(p)
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val second = Outer.Other()
|
||||
val third = Outer.Other(second)
|
||||
val fourth = Outer.Other(third)
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// See also KT-6299
|
||||
public open class Outer private constructor(val p: Outer?) {
|
||||
object Inner: Outer(null)
|
||||
object Other: Outer(Inner)
|
||||
object Another: Outer(Other)
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val outer = Outer.Inner
|
||||
val other = Outer.Other
|
||||
val another = Outer.Another
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// See also KT-6299
|
||||
public open class Outer private constructor(val s: String, vararg i: Int) {
|
||||
class Inner: Outer("xyz")
|
||||
class Other: Outer("abc", 1, 2, 3)
|
||||
class Another: Outer("", 42)
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
val outer = Outer.Inner()
|
||||
val other = Outer.Other()
|
||||
val another = Outer.Another()
|
||||
return "OK"
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// private constructors are transformed into synthetic
|
||||
class PrivateConstructor private constructor() {
|
||||
class Nested { val a = PrivateConstructor() }
|
||||
}
|
||||
|
||||
fun check(klass: Class<*>) {
|
||||
var hasSynthetic = false
|
||||
var hasSimple = false
|
||||
for (method in klass.getDeclaredConstructors()) {
|
||||
if (method.isSynthetic()) {
|
||||
hasSynthetic = true
|
||||
}
|
||||
else {
|
||||
hasSimple = true
|
||||
}
|
||||
}
|
||||
if (hasSynthetic && hasSimple) return
|
||||
throw AssertionError("Class should have both synthetic and non-synthetic constructor: ($hasSynthetic, $hasSimple)")
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
check(javaClass<PrivateConstructor>())
|
||||
// Also check that synthetic accessors really work
|
||||
PrivateConstructor.Nested()
|
||||
return "OK"
|
||||
}
|
||||
@@ -2,10 +2,6 @@
|
||||
// This is crucial for some JVM frameworks like Quasar which rely on the bytecode being similar to the one generated by javac
|
||||
// See https://youtrack.jetbrains.com/issue/KT-6870
|
||||
|
||||
class PrivateConstructor private constructor() {
|
||||
class Nested { val a = PrivateConstructor() }
|
||||
}
|
||||
|
||||
class PrivatePropertyGet {
|
||||
private val x = 42
|
||||
|
||||
@@ -33,13 +29,11 @@ fun check(klass: Class<*>) {
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
check(javaClass<PrivateConstructor>())
|
||||
check(javaClass<PrivatePropertyGet>())
|
||||
check(javaClass<PrivatePropertySet>())
|
||||
check(javaClass<PrivateMethod>())
|
||||
|
||||
// Also check that synthetic accessors really work
|
||||
PrivateConstructor.Nested()
|
||||
PrivatePropertyGet().Inner()
|
||||
PrivatePropertySet().Inner()
|
||||
PrivateMethod().Inner()
|
||||
|
||||
@@ -4,4 +4,4 @@ class A {
|
||||
}
|
||||
}
|
||||
// A and companion object constructor call
|
||||
// 2 ALOAD 0
|
||||
// 3 ALOAD 0
|
||||
+1
-1
@@ -4,5 +4,5 @@ class A {
|
||||
}
|
||||
}
|
||||
// A and companion object constructor call
|
||||
// 2 ALOAD 0
|
||||
// 3 ALOAD 0
|
||||
// 1 synthetic access\$getR
|
||||
|
||||
@@ -234,7 +234,7 @@ public abstract class AbstractWriteFlagsTest extends UsefulTestCase {
|
||||
|
||||
@Override
|
||||
public MethodVisitor visitMethod(int access, @NotNull String name, @NotNull String desc, String signature, String[] exceptions) {
|
||||
if (name.equals(funName)) {
|
||||
if (name.equals(funName) && (access & Opcodes.ACC_SYNTHETIC) == 0) {
|
||||
this.access = access;
|
||||
isExists = true;
|
||||
}
|
||||
|
||||
+69
@@ -5984,6 +5984,75 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/privateConstructors")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class PrivateConstructors extends AbstractBlackBoxCodegenTest {
|
||||
public void testAllFilesPresentInPrivateConstructors() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/privateConstructors"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("base.kt")
|
||||
public void testBase() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/privateConstructors/base.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("companion.kt")
|
||||
public void testCompanion() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/privateConstructors/companion.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inline.kt")
|
||||
public void testInline() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/privateConstructors/inline.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("inner.kt")
|
||||
public void testInner() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/privateConstructors/inner.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("secondary.kt")
|
||||
public void testSecondary() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/privateConstructors/secondary.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("withArguments.kt")
|
||||
public void testWithArguments() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/privateConstructors/withArguments.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("withDefault.kt")
|
||||
public void testWithDefault() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/privateConstructors/withDefault.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("withLinkedClasses.kt")
|
||||
public void testWithLinkedClasses() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/privateConstructors/withLinkedClasses.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("withLinkedObjects.kt")
|
||||
public void testWithLinkedObjects() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/privateConstructors/withLinkedObjects.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("withVarargs.kt")
|
||||
public void testWithVarargs() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/privateConstructors/withVarargs.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/box/properties")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
+15
@@ -2312,6 +2312,21 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxWithStdlib/privateConstructor")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class PrivateConstructor extends AbstractBlackBoxCodegenTest {
|
||||
public void testAllFilesPresentInPrivateConstructor() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxWithStdlib/privateConstructor"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("synthetic.kt")
|
||||
public void testSynthetic() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/privateConstructor/synthetic.kt");
|
||||
doTestWithStdlib(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxWithStdlib/ranges")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
-2
@@ -1,8 +1,6 @@
|
||||
a java.lang.Deprecated 0
|
||||
p org.test 0
|
||||
c 0 0/SomeClass$Companion
|
||||
a org.jetbrains.annotations.NotNull 1
|
||||
m 1 0/SomeClass$Companion access$init$0
|
||||
c 0 0/SomeClass$SomeInnerObject
|
||||
c 0 0/SomeClass$InnerClass
|
||||
c 0 0/SomeClass$InnerClass$InnerClassInInnerClass
|
||||
|
||||
+2
-4
@@ -3,9 +3,7 @@ p org.test 0
|
||||
m 0 0/SomeClass$Companion a
|
||||
a kotlin.inline 1
|
||||
m 1 0/SomeClass$Companion a
|
||||
a org.jetbrains.annotations.NotNull 2
|
||||
m 2 0/SomeClass$Companion access$init$0
|
||||
a java.lang.Deprecated 3
|
||||
f 3 0/SomeClass OBJECT$
|
||||
a java.lang.Deprecated 2
|
||||
f 2 0/SomeClass OBJECT$
|
||||
m 0 0/SomeClass a
|
||||
m 1 0/SomeClass a
|
||||
|
||||
Reference in New Issue
Block a user