Make top-level property backing field private in bytecode
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.kotlin.codegen;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import kotlin.CollectionsKt;
|
||||
import kotlin.StringsKt;
|
||||
import kotlin.jvm.functions.Function1;
|
||||
@@ -31,7 +32,6 @@ import org.jetbrains.kotlin.load.java.JvmAbi;
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames;
|
||||
import org.jetbrains.kotlin.load.kotlin.ModuleMapping;
|
||||
import org.jetbrains.kotlin.load.kotlin.ModuleVisibilityUtilsKt;
|
||||
import org.jetbrains.kotlin.load.kotlin.incremental.IncrementalPackageFragmentProvider;
|
||||
import org.jetbrains.kotlin.psi.JetFile;
|
||||
import org.jetbrains.kotlin.psi.JetFunction;
|
||||
import org.jetbrains.kotlin.psi.codeFragmentUtil.CodeFragmentUtilKt;
|
||||
@@ -77,25 +77,21 @@ public class JvmCodegenUtil {
|
||||
|
||||
return !isFakeOverride && !isDelegate &&
|
||||
(((context.hasThisDescriptor() && containingDeclaration == context.getThisDescriptor()) ||
|
||||
((context.getParentContext() instanceof PackageContext || context.getParentContext() instanceof MultifileClassPartContext)
|
||||
&& isSamePackageInSameModule(context.getParentContext().getContextDescriptor(), containingDeclaration)))
|
||||
((context.getParentContext() instanceof FacadePartWithSourceFile)
|
||||
&& isWithinSameFile(((FacadePartWithSourceFile) context.getParentContext()).getSourceFile(), descriptor)))
|
||||
&& context.getContextKind() != OwnerKind.DEFAULT_IMPLS);
|
||||
}
|
||||
|
||||
private static boolean isSamePackageInSameModule(
|
||||
@NotNull DeclarationDescriptor callerOwner,
|
||||
@NotNull DeclarationDescriptor calleeOwner
|
||||
private static boolean isWithinSameFile(
|
||||
@Nullable JetFile callerFile,
|
||||
@NotNull CallableMemberDescriptor descriptor
|
||||
) {
|
||||
if (callerOwner instanceof PackageFragmentDescriptor && calleeOwner instanceof PackageFragmentDescriptor) {
|
||||
PackageFragmentDescriptor callerFragment = (PackageFragmentDescriptor) callerOwner;
|
||||
PackageFragmentDescriptor calleeFragment = (PackageFragmentDescriptor) calleeOwner;
|
||||
DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration().getOriginal();
|
||||
if (containingDeclaration instanceof PackageFragmentDescriptor) {
|
||||
PsiElement calleeElement = DescriptorToSourceUtils.descriptorToDeclaration(descriptor);
|
||||
PsiFile calleeFile = calleeElement != null ? calleeElement.getContainingFile() : null;
|
||||
return callerFile != null && callerFile != SourceFile.NO_SOURCE_FILE && calleeFile == callerFile;
|
||||
|
||||
// backing field should be used directly within same module of same package
|
||||
if (callerFragment == calleeFragment) {
|
||||
return true;
|
||||
}
|
||||
return callerFragment.getFqName().equals(calleeFragment.getFqName())
|
||||
&& calleeFragment instanceof IncrementalPackageFragmentProvider.IncrementalPackageFragment;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -162,7 +162,7 @@ public class MultifileClassCodegen(
|
||||
var generatePart = false
|
||||
val partClassInfo = state.fileClassesProvider.getFileClassInfo(file)
|
||||
val partType = AsmUtil.asmTypeByFqNameWithoutInnerClasses(partClassInfo.fileClassFqName)
|
||||
val partContext = state.rootContext.intoMultifileClassPart(packageFragment, facadeClassType, partType)
|
||||
val partContext = state.rootContext.intoMultifileClassPart(packageFragment, facadeClassType, partType, file)
|
||||
|
||||
for (declaration in file.declarations) {
|
||||
if (declaration is JetProperty || declaration is JetNamedFunction) {
|
||||
|
||||
@@ -87,7 +87,7 @@ public class PackageCodegen {
|
||||
}
|
||||
|
||||
Type fileClassType = AsmUtil.asmTypeByFqNameWithoutInnerClasses(fileClassInfo.getFileClassFqName());
|
||||
PackageContext packagePartContext = state.getRootContext().intoPackagePart(packageFragment, fileClassType);
|
||||
PackageContext packagePartContext = state.getRootContext().intoPackagePart(packageFragment, fileClassType, file);
|
||||
|
||||
boolean generatePackagePart = false;
|
||||
|
||||
|
||||
@@ -340,7 +340,7 @@ public class PropertyCodegen {
|
||||
else if (!isDelegate && hasJvmFieldAnnotation) {
|
||||
modifiers |= getDefaultVisibilityFlag(propertyDescriptor.getVisibility());
|
||||
}
|
||||
else if (kind != OwnerKind.PACKAGE || isDelegate) {
|
||||
else {
|
||||
modifiers |= ACC_PRIVATE;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.codegen.binding.MutableClosure;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.codegen.state.JetTypeMapper;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.psi.JetFile;
|
||||
import org.jetbrains.kotlin.psi.JetSuperExpression;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
@@ -180,17 +181,18 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PackageContext intoPackagePart(@NotNull PackageFragmentDescriptor descriptor, Type packagePartType) {
|
||||
return new PackageContext(descriptor, this, packagePartType);
|
||||
public PackageContext intoPackagePart(@NotNull PackageFragmentDescriptor descriptor, Type packagePartType, @Nullable JetFile sourceFile) {
|
||||
return new PackageContext(descriptor, this, packagePartType, sourceFile);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public FieldOwnerContext<PackageFragmentDescriptor> intoMultifileClassPart(
|
||||
@NotNull PackageFragmentDescriptor descriptor,
|
||||
@NotNull Type multifileClassType,
|
||||
@NotNull Type filePartType
|
||||
@NotNull Type filePartType,
|
||||
@NotNull JetFile sourceFile
|
||||
) {
|
||||
return new MultifileClassPartContext(descriptor, this, multifileClassType, filePartType);
|
||||
return new MultifileClassPartContext(descriptor, this, multifileClassType, filePartType, sourceFile);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* 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.context;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.psi.JetFile;
|
||||
|
||||
public interface FacadePartWithSourceFile {
|
||||
|
||||
@Nullable
|
||||
JetFile getSourceFile();
|
||||
}
|
||||
+14
-2
@@ -16,18 +16,24 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen.context;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor;
|
||||
import org.jetbrains.kotlin.psi.JetFile;
|
||||
import org.jetbrains.org.objectweb.asm.Type;
|
||||
|
||||
public class MultifileClassPartContext extends MultifileClassContextBase implements DelegatingToPartContext {
|
||||
public class MultifileClassPartContext extends MultifileClassContextBase implements DelegatingToPartContext, FacadePartWithSourceFile {
|
||||
private final JetFile sourceFile;
|
||||
|
||||
public MultifileClassPartContext(
|
||||
PackageFragmentDescriptor descriptor,
|
||||
CodegenContext parent,
|
||||
Type multifileClassType,
|
||||
Type filePartType
|
||||
Type filePartType,
|
||||
@NotNull JetFile sourceFile
|
||||
) {
|
||||
super(descriptor, parent, multifileClassType, filePartType);
|
||||
this.sourceFile = sourceFile;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -35,4 +41,10 @@ public class MultifileClassPartContext extends MultifileClassContextBase impleme
|
||||
public Type getImplementationOwnerClassType() {
|
||||
return getFilePartType();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public JetFile getSourceFile() {
|
||||
return sourceFile;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,18 +20,22 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.codegen.OwnerKind;
|
||||
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor;
|
||||
import org.jetbrains.kotlin.psi.JetFile;
|
||||
import org.jetbrains.org.objectweb.asm.Type;
|
||||
|
||||
public class PackageContext extends FieldOwnerContext<PackageFragmentDescriptor> implements DelegatingToPartContext {
|
||||
public class PackageContext extends FieldOwnerContext<PackageFragmentDescriptor> implements DelegatingToPartContext, FacadePartWithSourceFile {
|
||||
private final Type packagePartType;
|
||||
@Nullable private JetFile sourceFile;
|
||||
|
||||
public PackageContext(
|
||||
@NotNull PackageFragmentDescriptor contextDescriptor,
|
||||
@NotNull CodegenContext parent,
|
||||
@Nullable Type packagePartType
|
||||
@Nullable Type packagePartType,
|
||||
@Nullable JetFile sourceFile
|
||||
) {
|
||||
super(contextDescriptor, OwnerKind.PACKAGE, parent, null, null, null);
|
||||
this.packagePartType = packagePartType;
|
||||
this.sourceFile = sourceFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -49,4 +53,10 @@ public class PackageContext extends FieldOwnerContext<PackageFragmentDescriptor>
|
||||
public Type getImplementationOwnerClassType() {
|
||||
return packagePartType;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public JetFile getSourceFile() {
|
||||
return sourceFile;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ public class PackageFacadeContext extends PackageContext implements DelegatingFa
|
||||
@NotNull Type packagePartType,
|
||||
@NotNull Type publicFacadeType
|
||||
) {
|
||||
super(contextDescriptor, parent, packagePartType);
|
||||
super(contextDescriptor, parent, packagePartType, null);
|
||||
|
||||
this.publicFacadeType = publicFacadeType;
|
||||
}
|
||||
|
||||
@@ -109,7 +109,8 @@ public class InlineCodegen extends CallGenerator {
|
||||
|
||||
initialFrameSize = codegen.getFrameMap().getCurrentSize();
|
||||
|
||||
context = (MethodContext) getContext(functionDescriptor, state);
|
||||
PsiElement element = DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor);
|
||||
context = (MethodContext) getContext(functionDescriptor, state, element != null ? (JetFile) element.getContainingFile() : null);
|
||||
jvmSignature = typeMapper.mapSignature(functionDescriptor, context.getContextKind());
|
||||
|
||||
// TODO: implement AS_FUNCTION inline strategy
|
||||
@@ -586,12 +587,12 @@ public class InlineCodegen extends CallGenerator {
|
||||
activeLambda = null;
|
||||
}
|
||||
|
||||
public static CodegenContext getContext(DeclarationDescriptor descriptor, GenerationState state) {
|
||||
public static CodegenContext getContext(@NotNull DeclarationDescriptor descriptor, @NotNull GenerationState state, @Nullable JetFile sourceFile) {
|
||||
if (descriptor instanceof PackageFragmentDescriptor) {
|
||||
return new PackageContext((PackageFragmentDescriptor) descriptor, state.getRootContext(), null);
|
||||
return new PackageContext((PackageFragmentDescriptor) descriptor, state.getRootContext(), null, sourceFile);
|
||||
}
|
||||
|
||||
CodegenContext parent = getContext(descriptor.getContainingDeclaration(), state);
|
||||
CodegenContext parent = getContext(descriptor.getContainingDeclaration(), state, sourceFile);
|
||||
|
||||
if (descriptor instanceof ClassDescriptor) {
|
||||
OwnerKind kind = DescriptorUtils.isInterface(descriptor) ? OwnerKind.DEFAULT_IMPLS : OwnerKind.IMPLEMENTATION;
|
||||
|
||||
+1
-1
@@ -376,7 +376,7 @@ public class KotlinJavaFileStubProvider<T extends WithFileStubAndExtraDiagnostic
|
||||
PackageCodegen packageCodegen = state.getFactory().forPackage(getPackageFqName(), files);
|
||||
JetFile file = classOrObject.getContainingJetFile();
|
||||
Type packagePartType = FileClasses.getFileClassType(state.getFileClassesProvider(), file);
|
||||
PackageContext context = state.getRootContext().intoPackagePart(packageCodegen.getPackageFragment(), packagePartType);
|
||||
PackageContext context = state.getRootContext().intoPackagePart(packageCodegen.getPackageFragment(), packagePartType, file);
|
||||
packageCodegen.generateClassOrObject(classOrObject, context);
|
||||
state.getFactory().asList();
|
||||
}
|
||||
|
||||
+6
-6
@@ -1,14 +1,14 @@
|
||||
public final class FileFacadeKt {
|
||||
@org.jetbrains.annotations.Nullable
|
||||
static final java.lang.String nullableVal = "";
|
||||
private static final java.lang.String nullableVal = "";
|
||||
@org.jetbrains.annotations.Nullable
|
||||
static java.lang.String nullableVar;
|
||||
private static java.lang.String nullableVar;
|
||||
@org.jetbrains.annotations.NotNull
|
||||
static final java.lang.String notNullVal = "";
|
||||
private static final java.lang.String notNullVal = "";
|
||||
@org.jetbrains.annotations.NotNull
|
||||
static java.lang.String notNullVar;
|
||||
static final java.lang.String privateNn = "";
|
||||
static final java.lang.String privateN = "";
|
||||
private static java.lang.String notNullVar;
|
||||
private static final java.lang.String privateNn = "";
|
||||
private static final java.lang.String privateN = "";
|
||||
|
||||
@org.jetbrains.annotations.NotNull
|
||||
public static final java.lang.String notNull(@org.jetbrains.annotations.NotNull java.lang.String a) { /* compiled code */ }
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
// FULL_JDK
|
||||
package test
|
||||
|
||||
import java.lang.reflect.Modifier
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
|
||||
private val prop = "O"
|
||||
|
||||
private fun test() = "K"
|
||||
|
||||
fun box(): String {
|
||||
val clazz = Class.forName("test.PrivateVisibilityKt")
|
||||
assertTrue(Modifier.isPrivate(clazz.getDeclaredMethod("test").modifiers), "Private top level function should be private")
|
||||
assertTrue(Modifier.isPrivate(clazz.getDeclaredField("prop").modifiers), "Backing field for private top level property should be private")
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -23,7 +23,7 @@
|
||||
@kotlin.annotation.Target @java.lang.annotation.Retention @java.lang.annotation.Target @kotlin.jvm.internal.KotlinClass Anno
|
||||
|
||||
@kotlin.jvm.internal.KotlinFileFacade DefaultTargetsKt {
|
||||
final @Anno field p2: int
|
||||
private final @Anno field p2: int
|
||||
method <clinit>(): void
|
||||
public final method getP(): int
|
||||
public final method getP2(): int
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
// TESTED_OBJECT_KIND: property
|
||||
// TESTED_OBJECTS: TopLevelPropertyKt, test
|
||||
// IS_FULL_CONTAINING_CLASS_NAME: false
|
||||
// FLAGS: ACC_DEPRECATED, ACC_FINAL, ACC_STATIC
|
||||
// FLAGS: ACC_DEPRECATED, ACC_FINAL, ACC_STATIC, ACC_PRIVATE
|
||||
|
||||
@@ -79,7 +79,7 @@ public class PropertyGenTest extends CodegenTestCase {
|
||||
Field field = fields[0];
|
||||
field.setAccessible(true);
|
||||
assertEquals("x", field.getName());
|
||||
assertEquals(Modifier.STATIC | Modifier.FINAL, field.getModifiers());
|
||||
assertEquals(Modifier.STATIC | Modifier.FINAL | Modifier.PRIVATE, field.getModifiers());
|
||||
assertEquals(239, field.get(null));
|
||||
}
|
||||
|
||||
|
||||
+6
@@ -4666,6 +4666,12 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode
|
||||
doTestWithStdlib(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("privateVisibility.kt")
|
||||
public void testPrivateVisibility() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/topLevelPrivate/privateVisibility.kt");
|
||||
doTestWithStdlib(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("syntheticAccessor.kt")
|
||||
public void testSyntheticAccessor() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/topLevelPrivate/syntheticAccessor.kt");
|
||||
|
||||
Reference in New Issue
Block a user