
org.jetbrains.jet.codegen.JvmCodegenUtil Maven / Gradle / Ivy
/*
* Copyright 2010-2013 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;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.Stack;
import kotlin.Function1;
import kotlin.KotlinPackage;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.codegen.binding.CalculatedClosure;
import org.jetbrains.jet.codegen.context.CodegenContext;
import org.jetbrains.jet.codegen.context.MethodContext;
import org.jetbrains.jet.codegen.context.PackageContext;
import org.jetbrains.jet.codegen.state.JetTypeMapper;
import org.jetbrains.jet.config.IncrementalCompilation;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.Annotations;
import org.jetbrains.jet.lang.descriptors.impl.SimpleFunctionDescriptorImpl;
import org.jetbrains.jet.lang.descriptors.impl.TypeParameterDescriptorImpl;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.calls.CallResolverUtil;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeUtils;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import static org.jetbrains.jet.lang.descriptors.Modality.ABSTRACT;
public class JvmCodegenUtil {
private JvmCodegenUtil() {
}
public static boolean isInterface(DeclarationDescriptor descriptor) {
if (descriptor instanceof ClassDescriptor) {
ClassKind kind = ((ClassDescriptor) descriptor).getKind();
return kind == ClassKind.TRAIT || kind == ClassKind.ANNOTATION_CLASS;
}
return false;
}
public static boolean isInterface(JetType type) {
return isInterface(type.getConstructor().getDeclarationDescriptor());
}
public static SimpleFunctionDescriptor createInvoke(FunctionDescriptor fd) {
int arity = fd.getValueParameters().size();
SimpleFunctionDescriptorImpl invokeDescriptor = SimpleFunctionDescriptorImpl.create(
fd.getExpectedThisObject() != null
? KotlinBuiltIns.getInstance().getExtensionFunction(arity) : KotlinBuiltIns.getInstance().getFunction(arity),
Annotations.EMPTY,
Name.identifier("invoke"),
CallableMemberDescriptor.Kind.DECLARATION
);
invokeDescriptor.initialize(DescriptorUtils.getReceiverParameterType(fd.getReceiverParameter()),
fd.getExpectedThisObject(),
Collections.emptyList(),
fd.getValueParameters(),
fd.getReturnType(),
Modality.FINAL,
Visibilities.PUBLIC
);
return invokeDescriptor;
}
public static boolean isConst(@NotNull CalculatedClosure closure) {
return closure.getCaptureThis() == null && closure.getCaptureReceiverType() == null && closure.getCaptureVariables().isEmpty();
}
public static T peekFromStack(Stack stack) {
return stack.empty() ? null : stack.peek();
}
public static JetType getSuperClass(ClassDescriptor classDescriptor) {
List superclassDescriptors = DescriptorUtils.getSuperclassDescriptors(classDescriptor);
for (ClassDescriptor descriptor : superclassDescriptors) {
if (descriptor.getKind() != ClassKind.TRAIT) {
return descriptor.getDefaultType();
}
}
return KotlinBuiltIns.getInstance().getAnyType();
}
@Nullable
public static FunctionDescriptor getDeclaredFunctionByRawSignature(
@NotNull ClassDescriptor owner,
@NotNull Name name,
@NotNull ClassifierDescriptor returnedClassifier,
@NotNull ClassifierDescriptor... valueParameterClassifiers
) {
Collection functions = owner.getDefaultType().getMemberScope().getFunctions(name);
for (FunctionDescriptor function : functions) {
if (!CallResolverUtil.isOrOverridesSynthesized(function)
&& function.getTypeParameters().isEmpty()
&& valueParameterClassesMatch(function.getValueParameters(), Arrays.asList(valueParameterClassifiers))
&& rawTypeMatches(function.getReturnType(), returnedClassifier)) {
return function;
}
}
return null;
}
private static boolean valueParameterClassesMatch(
@NotNull List parameters,
@NotNull List classifiers) {
if (parameters.size() != classifiers.size()) return false;
for (int i = 0; i < parameters.size(); i++) {
ValueParameterDescriptor parameterDescriptor = parameters.get(i);
ClassifierDescriptor classDescriptor = classifiers.get(i);
if (!rawTypeMatches(parameterDescriptor.getType(), classDescriptor)) {
return false;
}
}
return true;
}
private static boolean rawTypeMatches(JetType type, ClassifierDescriptor classifier) {
return type.getConstructor().getDeclarationDescriptor().getOriginal() == classifier.getOriginal();
}
public static boolean isCallInsideSameClassAsDeclared(CallableMemberDescriptor declarationDescriptor, CodegenContext context) {
boolean isFakeOverride = declarationDescriptor.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE;
boolean isDelegate = declarationDescriptor.getKind() == CallableMemberDescriptor.Kind.DELEGATION;
DeclarationDescriptor containingDeclaration = declarationDescriptor.getContainingDeclaration();
containingDeclaration = containingDeclaration.getOriginal();
return !isFakeOverride && !isDelegate &&
(((context.hasThisDescriptor() && containingDeclaration == context.getThisDescriptor()) ||
(context.getParentContext() instanceof PackageContext
&& isSamePackageInSameModule(context.getParentContext().getContextDescriptor(), containingDeclaration)))
&& context.getContextKind() != OwnerKind.TRAIT_IMPL);
}
private static boolean isSamePackageInSameModule(
@NotNull DeclarationDescriptor owner1,
@NotNull DeclarationDescriptor owner2
) {
if (owner1 instanceof PackageFragmentDescriptor && owner2 instanceof PackageFragmentDescriptor) {
PackageFragmentDescriptor fragment1 = (PackageFragmentDescriptor) owner1;
PackageFragmentDescriptor fragment2 = (PackageFragmentDescriptor) owner2;
if (!IncrementalCompilation.ENABLED) {
return fragment1 == fragment2;
}
// backing field should be used directly within same module of same package
// TODO calls from other modules/libraries should use facade: KT-4590
return fragment1.getFqName().equals(fragment2.getFqName()) && DescriptorUtils.areInSameModule(fragment1, fragment2);
}
return false;
}
public static boolean isCallInsideSameModuleAsDeclared(CallableMemberDescriptor declarationDescriptor, CodegenContext context) {
if (context == CodegenContext.STATIC) {
return true;
}
DeclarationDescriptor contextDescriptor = context.getContextDescriptor();
return DescriptorUtils.areInSameModule(declarationDescriptor, contextDescriptor);
}
public static boolean hasAbstractMembers(@NotNull ClassDescriptor classDescriptor) {
return KotlinPackage.any(classDescriptor.getDefaultType().getMemberScope().getAllDescriptors(),
new Function1() {
@Override
public Boolean invoke(DeclarationDescriptor descriptor) {
return descriptor instanceof CallableMemberDescriptor &&
((CallableMemberDescriptor) descriptor).getModality() == ABSTRACT;
}
}
);
}
/**
* A work-around of the generic nullability problem in the type checker
* @return true if a value of this type can be null
*/
public static boolean isNullableType(@NotNull JetType type) {
if (type.isNullable()) {
return true;
}
if (type.getConstructor().getDeclarationDescriptor() instanceof TypeParameterDescriptor) {
return TypeUtils.hasNullableSuperType(type);
}
return false;
}
public static boolean couldUseDirectAccessToProperty(
@NotNull PropertyDescriptor propertyDescriptor,
boolean forGetter,
boolean isInsideClass,
boolean isDelegated,
MethodContext context
) {
if (context.isInlineFunction()) {
return false;
}
PropertyAccessorDescriptor accessorDescriptor = forGetter ? propertyDescriptor.getGetter() : propertyDescriptor.getSetter();
boolean isExtensionProperty = propertyDescriptor.getReceiverParameter() != null;
boolean specialTypeProperty = isDelegated ||
isExtensionProperty ||
DescriptorUtils.isClassObject(propertyDescriptor.getContainingDeclaration()) ||
JetTypeMapper.isAccessor(propertyDescriptor);
return isInsideClass &&
!specialTypeProperty &&
(accessorDescriptor == null ||
accessorDescriptor.isDefault() &&
(!isExternallyAccessible(propertyDescriptor) || accessorDescriptor.getModality() == Modality.FINAL));
}
private static boolean isExternallyAccessible(@NotNull PropertyDescriptor propertyDescriptor) {
return propertyDescriptor.getVisibility() != Visibilities.PRIVATE ||
DescriptorUtils.isClassObject(propertyDescriptor.getContainingDeclaration()) ||
DescriptorUtils.isTopLevelDeclaration(propertyDescriptor);
}
@NotNull
public static ImplementationBodyCodegen getParentBodyCodegen(@Nullable MemberCodegen> classBodyCodegen) {
assert classBodyCodegen != null && classBodyCodegen.getParentCodegen() instanceof ImplementationBodyCodegen
: "Class object should have appropriate parent BodyCodegen";
return (ImplementationBodyCodegen) classBodyCodegen.getParentCodegen();
}
static int getPathHashCode(@NotNull VirtualFile file) {
// Conversion to system-dependent name seems to be unnecessary, but it's hard to check now:
// it was introduced when fixing KT-2839, which appeared again (KT-3639).
// If you try to remove it, run tests on Windows.
return FileUtil.toSystemDependentName(file.getPath()).hashCode();
}
@Nullable
public static ClassDescriptor getExpectedThisObjectForConstructorCall(
@NotNull ConstructorDescriptor descriptor,
@Nullable CalculatedClosure closure
) {
//for compilation against sources
if (closure != null) {
return closure.getCaptureThis();
}
//for compilation against binaries
//TODO: It's best to use this code also for compilation against sources
// but sometimes structures that have expectedThisObject (bug?) mapped to static classes
ReceiverParameterDescriptor expectedThisObject = descriptor.getExpectedThisObject();
if (expectedThisObject != null) {
ClassDescriptor expectedThisClass = (ClassDescriptor) expectedThisObject.getContainingDeclaration();
if (!expectedThisClass.getKind().isSingleton()) {
return expectedThisClass;
}
}
return null;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy