Move utilities out of runtime modules

DescriptorUtils & DescriptorSubstitutor contained a lot of utilities that were
used only in compiler & IDE. Move them closer to their usages
This commit is contained in:
Alexander Udalov
2013-10-24 16:36:33 +04:00
parent e04f7c24fa
commit eb11a7dc88
22 changed files with 270 additions and 259 deletions
@@ -43,6 +43,7 @@ import org.jetbrains.jet.descriptors.serialization.ProtoBuf;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.DeclarationResolver;
import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.calls.CallResolverUtil; import org.jetbrains.jet.lang.resolve.calls.CallResolverUtil;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
@@ -838,7 +839,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
iv.anew(thisDescriptorType); iv.anew(thisDescriptorType);
iv.dup(); iv.dup();
ConstructorDescriptor constructor = DescriptorUtils.getConstructorOfDataClass(descriptor); ConstructorDescriptor constructor = DeclarationResolver.getConstructorOfDataClass(descriptor);
assert function.getValueParameters().size() == constructor.getValueParameters().size() : assert function.getValueParameters().size() == constructor.getValueParameters().size() :
"Number of parameters of copy function and constructor are different. " + "Number of parameters of copy function and constructor are different. " +
"Copy: " + function.getValueParameters().size() + ", " + "Copy: " + function.getValueParameters().size() + ", " +
@@ -1124,9 +1125,11 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
protected void genInitSingleton(ClassDescriptor fieldTypeDescriptor, StackValue.Field field) { protected void genInitSingleton(ClassDescriptor fieldTypeDescriptor, StackValue.Field field) {
if (state.getClassBuilderMode() == ClassBuilderMode.FULL) { if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
ConstructorDescriptor constructorDescriptor = DescriptorUtils.getConstructorOfSingletonObject(fieldTypeDescriptor); Collection<ConstructorDescriptor> constructors = fieldTypeDescriptor.getConstructors();
assert constructors.size() == 1 : "Class of singleton object must have only one constructor: " + constructors;
ExpressionCodegen codegen = createOrGetClInitCodegen(); ExpressionCodegen codegen = createOrGetClInitCodegen();
FunctionDescriptor fd = codegen.accessibleFunctionDescriptor(constructorDescriptor); FunctionDescriptor fd = codegen.accessibleFunctionDescriptor(constructors.iterator().next());
generateMethodCallTo(fd, codegen.v); generateMethodCallTo(fd, codegen.v);
field.store(field.type, codegen.v); field.store(field.type, codegen.v);
} }
@@ -23,12 +23,12 @@ import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor;
import org.jetbrains.jet.lang.descriptors.impl.MutablePackageFragmentDescriptor; import org.jetbrains.jet.lang.descriptors.impl.MutablePackageFragmentDescriptor;
import org.jetbrains.jet.lang.descriptors.impl.TypeParameterDescriptorImpl; import org.jetbrains.jet.lang.descriptors.impl.TypeParameterDescriptorImpl;
import org.jetbrains.jet.lang.reflect.ReflectionTypes; import org.jetbrains.jet.lang.reflect.ReflectionTypes;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.ImportPath; import org.jetbrains.jet.lang.resolve.ImportPath;
import org.jetbrains.jet.lang.resolve.java.mapping.JavaToKotlinClassMap; import org.jetbrains.jet.lang.resolve.java.mapping.JavaToKotlinClassMap;
import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.types.*; import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import java.util.*; import java.util.*;
@@ -117,7 +117,7 @@ public class JvmRuntimeTypes {
JetType functionType = KotlinBuiltIns.getInstance().getFunctionType( JetType functionType = KotlinBuiltIns.getInstance().getFunctionType(
Annotations.EMPTY, Annotations.EMPTY,
receiverParameter == null ? null : receiverParameter.getType(), receiverParameter == null ? null : receiverParameter.getType(),
DescriptorUtils.getValueParametersTypes(descriptor.getValueParameters()), ExpressionTypingUtils.getValueParametersTypes(descriptor.getValueParameters()),
descriptor.getReturnType() descriptor.getReturnType()
); );
@@ -162,7 +162,7 @@ public class JvmRuntimeTypes {
JetType kFunctionType = reflectionTypes.getKFunctionType( JetType kFunctionType = reflectionTypes.getKFunctionType(
Annotations.EMPTY, Annotations.EMPTY,
receiverType, receiverType,
DescriptorUtils.getValueParametersTypes(descriptor.getValueParameters()), ExpressionTypingUtils.getValueParametersTypes(descriptor.getValueParameters()),
descriptor.getReturnType(), descriptor.getReturnType(),
receiverParameter != null receiverParameter != null
); );
@@ -32,10 +32,7 @@ import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import org.jetbrains.jet.renderer.DescriptorRenderer; import org.jetbrains.jet.renderer.DescriptorRenderer;
import java.util.Collection; import java.util.*;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class JavaToKotlinMethodMap { public class JavaToKotlinMethodMap {
public static final JavaToKotlinMethodMap INSTANCE = new JavaToKotlinMethodMap(); public static final JavaToKotlinMethodMap INSTANCE = new JavaToKotlinMethodMap();
@@ -55,7 +52,7 @@ public class JavaToKotlinMethodMap {
List<FunctionDescriptor> result = Lists.newArrayList(); List<FunctionDescriptor> result = Lists.newArrayList();
Set<ClassDescriptor> allSuperClasses = DescriptorUtils.getAllSuperClasses(containingClass); Set<ClassDescriptor> allSuperClasses = new HashSet<ClassDescriptor>(DescriptorUtils.getSuperclassDescriptors(containingClass));
String serializedMethod = JavaSignatureFormatter.getInstance().formatMethod(javaMethod); String serializedMethod = JavaSignatureFormatter.getInstance().formatMethod(javaMethod);
for (ClassData classData : classDatas) { for (ClassData classData : classDatas) {
@@ -21,7 +21,7 @@ import com.intellij.psi.impl.JavaConstantExpressionEvaluator;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.evaluate.ConstantExpressionEvaluator;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
import org.jetbrains.jet.lang.resolve.constants.ConstantsPackage; import org.jetbrains.jet.lang.resolve.constants.ConstantsPackage;
import org.jetbrains.jet.lang.resolve.java.structure.JavaField; import org.jetbrains.jet.lang.resolve.java.structure.JavaField;
@@ -36,7 +36,7 @@ public class JavaPropertyInitializerEvaluatorImpl implements JavaPropertyInitial
if (evaluatedExpression != null) { if (evaluatedExpression != null) {
return ConstantsPackage.createCompileTimeConstant( return ConstantsPackage.createCompileTimeConstant(
evaluatedExpression, evaluatedExpression,
DescriptorUtils.isPropertyCompileTimeConstant(descriptor), ConstantExpressionEvaluator.object$.isPropertyCompileTimeConstant(descriptor),
false, false,
true, true,
descriptor.getType()); descriptor.getType());
@@ -58,6 +58,7 @@ import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue; import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ThisReceiver; import org.jetbrains.jet.lang.resolve.scopes.receivers.ThisReceiver;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.lexer.JetTokens;
import org.jetbrains.jet.plugin.MainFunctionDetector; import org.jetbrains.jet.plugin.MainFunctionDetector;
@@ -591,7 +592,7 @@ public class JetFlowInformationProvider {
VariableDescriptor variableDescriptor = PseudocodeUtil.extractVariableDescriptorIfAny( VariableDescriptor variableDescriptor = PseudocodeUtil.extractVariableDescriptorIfAny(
instruction, false, trace.getBindingContext()); instruction, false, trace.getBindingContext());
if (variableDescriptor == null || !declaredVariables.contains(variableDescriptor) if (variableDescriptor == null || !declaredVariables.contains(variableDescriptor)
|| !DescriptorUtils.isLocal(variableDescriptor.getContainingDeclaration(), variableDescriptor)) { || !ExpressionTypingUtils.isLocal(variableDescriptor.getContainingDeclaration(), variableDescriptor)) {
return; return;
} }
PseudocodeVariablesData.VariableUseState variableUseState = in.get(variableDescriptor); PseudocodeVariablesData.VariableUseState variableUseState = in.get(variableDescriptor);
@@ -41,6 +41,17 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet
val evaluator = ConstantExpressionEvaluator(trace) val evaluator = ConstantExpressionEvaluator(trace)
return evaluator.evaluate(expression, expectedType) return evaluator.evaluate(expression, expectedType)
} }
public fun isPropertyCompileTimeConstant(descriptor: VariableDescriptor): Boolean {
if (descriptor.isVar()) {
return false
}
if (DescriptorUtils.isClassObject(descriptor.getContainingDeclaration()) || DescriptorUtils.isTopLevelDeclaration(descriptor)) {
val returnType = descriptor.getType()
return KotlinBuiltIns.getInstance().isPrimitiveType(returnType) || KotlinBuiltIns.getInstance().getStringType() == returnType
}
return false
}
} }
private fun evaluate(expression: JetExpression, expectedType: JetType?): CompileTimeConstant<*>? { private fun evaluate(expression: JetExpression, expectedType: JetType?): CompileTimeConstant<*>? {
@@ -311,7 +322,7 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet
else else
compileTimeConstant.getValue() compileTimeConstant.getValue()
return createCompileTimeConstant(value, expectedType, isPure = false, return createCompileTimeConstant(value, expectedType, isPure = false,
canBeUsedInAnnotation = DescriptorUtils.isPropertyCompileTimeConstant(callableDescriptor), canBeUsedInAnnotation = isPropertyCompileTimeConstant(callableDescriptor),
usesVariableAsConstant = true) usesVariableAsConstant = true)
} }
} }
@@ -89,7 +89,7 @@ public class BindingContextUtils {
public static JetFile getContainingFile(@NotNull BindingContext context, @NotNull DeclarationDescriptor declarationDescriptor) { public static JetFile getContainingFile(@NotNull BindingContext context, @NotNull DeclarationDescriptor declarationDescriptor) {
// declarationDescriptor may describe a synthesized element which doesn't have PSI // declarationDescriptor may describe a synthesized element which doesn't have PSI
// To workaround that, we find a top-level parent (which is inside a PackageFragmentDescriptor), which is guaranteed to have PSI // To workaround that, we find a top-level parent (which is inside a PackageFragmentDescriptor), which is guaranteed to have PSI
DeclarationDescriptor descriptor = DescriptorUtils.findTopLevelParent(declarationDescriptor); DeclarationDescriptor descriptor = findTopLevelParent(declarationDescriptor);
if (descriptor == null) return null; if (descriptor == null) return null;
PsiElement declaration = descriptorToDeclaration(context, descriptor); PsiElement declaration = descriptorToDeclaration(context, descriptor);
@@ -100,6 +100,18 @@ public class BindingContextUtils {
return (JetFile) containingFile; return (JetFile) containingFile;
} }
@Nullable
private static DeclarationDescriptor findTopLevelParent(@NotNull DeclarationDescriptor declarationDescriptor) {
DeclarationDescriptor descriptor = declarationDescriptor;
if (declarationDescriptor instanceof PropertyAccessorDescriptor) {
descriptor = ((PropertyAccessorDescriptor) descriptor).getCorrespondingProperty();
}
while (!(descriptor == null || DescriptorUtils.isTopLevelDeclaration(descriptor))) {
descriptor = descriptor.getContainingDeclaration();
}
return descriptor;
}
@Nullable @Nullable
private static PsiElement doGetDescriptorToDeclaration(@NotNull BindingContext context, @NotNull DeclarationDescriptor descriptor) { private static PsiElement doGetDescriptorToDeclaration(@NotNull BindingContext context, @NotNull DeclarationDescriptor descriptor) {
return context.get(DESCRIPTOR_TO_DECLARATION, descriptor); return context.get(DESCRIPTOR_TO_DECLARATION, descriptor);
@@ -203,13 +203,20 @@ public class DeclarationResolver {
MutableClassDescriptor classDescriptor = (MutableClassDescriptor) entry.getValue(); MutableClassDescriptor classDescriptor = (MutableClassDescriptor) entry.getValue();
if (klass instanceof JetClass && klass.hasPrimaryConstructor() && KotlinBuiltIns.getInstance().isData(classDescriptor)) { if (klass instanceof JetClass && klass.hasPrimaryConstructor() && KotlinBuiltIns.getInstance().isData(classDescriptor)) {
ConstructorDescriptor constructor = DescriptorUtils.getConstructorOfDataClass(classDescriptor); ConstructorDescriptor constructor = getConstructorOfDataClass(classDescriptor);
createComponentFunctions(classDescriptor, constructor); createComponentFunctions(classDescriptor, constructor);
createCopyFunction(classDescriptor, constructor); createCopyFunction(classDescriptor, constructor);
} }
} }
} }
@NotNull
public static ConstructorDescriptor getConstructorOfDataClass(@NotNull ClassDescriptor classDescriptor) {
Collection<ConstructorDescriptor> constructors = classDescriptor.getConstructors();
assert constructors.size() == 1 : "Data class must have only one constructor: " + classDescriptor.getConstructors();
return constructors.iterator().next();
}
private void createComponentFunctions(@NotNull MutableClassDescriptor classDescriptor, @NotNull ConstructorDescriptor constructorDescriptor) { private void createComponentFunctions(@NotNull MutableClassDescriptor classDescriptor, @NotNull ConstructorDescriptor constructorDescriptor) {
int parameterIndex = 0; int parameterIndex = 0;
for (ValueParameterDescriptor parameter : constructorDescriptor.getValueParameters()) { for (ValueParameterDescriptor parameter : constructorDescriptor.getValueParameters()) {
@@ -546,7 +546,7 @@ public class DescriptorResolver {
JetType variableType = type; JetType variableType = type;
if (valueParameter.hasModifier(VARARG_KEYWORD)) { if (valueParameter.hasModifier(VARARG_KEYWORD)) {
varargElementType = type; varargElementType = type;
variableType = DescriptorUtils.getVarargParameterType(type); variableType = getVarargParameterType(type);
} }
ValueParameterDescriptorImpl valueParameterDescriptor = new ValueParameterDescriptorImpl( ValueParameterDescriptorImpl valueParameterDescriptor = new ValueParameterDescriptorImpl(
declarationDescriptor, declarationDescriptor,
@@ -563,6 +563,15 @@ public class DescriptorResolver {
return valueParameterDescriptor; return valueParameterDescriptor;
} }
@NotNull
private static JetType getVarargParameterType(@NotNull JetType elementType) {
JetType primitiveArrayType = KotlinBuiltIns.getInstance().getPrimitiveArrayJetTypeByPrimitiveJetType(elementType);
if (primitiveArrayType != null) {
return primitiveArrayType;
}
return KotlinBuiltIns.getInstance().getArrayType(Variance.INVARIANT, elementType);
}
public List<TypeParameterDescriptorImpl> resolveTypeParametersForCallableDescriptor( public List<TypeParameterDescriptorImpl> resolveTypeParametersForCallableDescriptor(
DeclarationDescriptor containingDescriptor, DeclarationDescriptor containingDescriptor,
WritableScope extensibleScope, WritableScope extensibleScope,
@@ -791,7 +800,7 @@ public class DescriptorResolver {
type = ErrorUtils.createErrorType("Annotation is absent"); type = ErrorUtils.createErrorType("Annotation is absent");
} }
if (parameter.hasModifier(VARARG_KEYWORD)) { if (parameter.hasModifier(VARARG_KEYWORD)) {
return DescriptorUtils.getVarargParameterType(type); return getVarargParameterType(type);
} }
return type; return type;
} }
@@ -1259,7 +1268,7 @@ public class DescriptorResolver {
parameterScope, parameterScope,
valueParameters, trace), valueParameters, trace),
resolveVisibilityFromModifiers(modifierList, getDefaultConstructorVisibility(classDescriptor)), resolveVisibilityFromModifiers(modifierList, getDefaultConstructorVisibility(classDescriptor)),
DescriptorUtils.isConstructorOfStaticNestedClass(constructorDescriptor)); isConstructorOfStaticNestedClass(constructorDescriptor));
if (isAnnotationClass(classDescriptor)) { if (isAnnotationClass(classDescriptor)) {
CompileTimeConstantUtils.checkConstructorParametersType(valueParameters, trace); CompileTimeConstantUtils.checkConstructorParametersType(valueParameters, trace);
} }
@@ -1425,6 +1434,19 @@ public class DescriptorResolver {
return true; return true;
} }
private static boolean isInsideOuterClassOrItsSubclass(@Nullable DeclarationDescriptor nested, @NotNull ClassDescriptor outer) {
if (nested == null) return false;
if (nested instanceof ClassDescriptor && isSubclass((ClassDescriptor) nested, outer)) return true;
return isInsideOuterClassOrItsSubclass(nested.getContainingDeclaration(), outer);
}
@Nullable
public static ClassDescriptor getContainingClass(@NotNull JetScope scope) {
return getParentOfType(scope.getContainingDeclaration(), ClassDescriptor.class, false);
}
public static void checkParameterHasNoValOrVar( public static void checkParameterHasNoValOrVar(
@NotNull BindingTrace trace, @NotNull BindingTrace trace,
@NotNull JetParameter parameter, @NotNull JetParameter parameter,
@@ -21,11 +21,11 @@ import gnu.trove.TObjectHashingStrategy;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.OverrideResolver; import org.jetbrains.jet.lang.resolve.OverrideResolver;
import org.jetbrains.jet.lang.resolve.calls.model.MutableResolvedCall; import org.jetbrains.jet.lang.resolve.calls.model.MutableResolvedCall;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
import org.jetbrains.jet.lang.resolve.calls.model.VariableAsFunctionResolvedCall; import org.jetbrains.jet.lang.resolve.calls.model.VariableAsFunctionResolvedCall;
import org.jetbrains.jet.lang.types.BoundsSubstitutor;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeUtils; import org.jetbrains.jet.lang.types.TypeUtils;
import org.jetbrains.jet.lang.types.checker.JetTypeChecker; import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
@@ -131,7 +131,7 @@ public class OverloadingConflictResolver {
if (isGenericF && !isGenericG) return false; if (isGenericF && !isGenericG) return false;
if (isGenericF && isGenericG) { if (isGenericF && isGenericG) {
return moreSpecific(DescriptorUtils.substituteBounds(f), DescriptorUtils.substituteBounds(g), false); return moreSpecific(BoundsSubstitutor.substituteBounds(f), BoundsSubstitutor.substituteBounds(g), false);
} }
} }
@@ -38,8 +38,11 @@ import org.jetbrains.jet.lang.types.ErrorUtils;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.PackageType; import org.jetbrains.jet.lang.types.PackageType;
import org.jetbrains.jet.lang.types.checker.JetTypeChecker; import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils;
import java.util.*; import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.isOrOverridesSynthesized; import static org.jetbrains.jet.lang.resolve.calls.CallResolverUtil.isOrOverridesSynthesized;
import static org.jetbrains.jet.lang.resolve.calls.tasks.ExplicitReceiverKind.*; import static org.jetbrains.jet.lang.resolve.calls.tasks.ExplicitReceiverKind.*;
@@ -54,7 +57,7 @@ public class TaskPrioritizer {
@NotNull Collection<ResolutionCandidate<D>> nonlocal @NotNull Collection<ResolutionCandidate<D>> nonlocal
) { ) {
for (ResolutionCandidate<D> resolvedCall : allDescriptors) { for (ResolutionCandidate<D> resolvedCall : allDescriptors) {
if (DescriptorUtils.isLocal(containerOfTheCurrentLocality, resolvedCall.getDescriptor())) { if (ExpressionTypingUtils.isLocal(containerOfTheCurrentLocality, resolvedCall.getDescriptor())) {
local.add(resolvedCall); local.add(resolvedCall);
} }
else { else {
@@ -0,0 +1,121 @@
/*
* 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.lang.types;
import com.google.common.base.Function;
import com.google.common.collect.Collections2;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor;
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
import org.jetbrains.jet.utils.DFS;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class BoundsSubstitutor {
private static final Function<TypeProjection,JetType> PROJECTIONS_TO_TYPES = new Function<TypeProjection, JetType>() {
@Override
public JetType apply(TypeProjection projection) {
return projection.getType();
}
};
private BoundsSubstitutor() {
}
@NotNull
public static <D extends CallableDescriptor> D substituteBounds(@NotNull D functionDescriptor) {
List<TypeParameterDescriptor> typeParameters = functionDescriptor.getTypeParameters();
if (typeParameters.isEmpty()) return functionDescriptor;
// TODO: this does not handle any recursion in the bounds
@SuppressWarnings("unchecked")
D substitutedFunction = (D) functionDescriptor.substitute(createUpperBoundsSubstitutor(typeParameters));
assert substitutedFunction != null : "Substituting upper bounds should always be legal";
return substitutedFunction;
}
@NotNull
private static TypeSubstitutor createUpperBoundsSubstitutor(@NotNull List<TypeParameterDescriptor> typeParameters) {
Map<TypeConstructor, TypeProjection> mutableSubstitution = new HashMap<TypeConstructor, TypeProjection>();
TypeSubstitutor substitutor = TypeSubstitutor.create(mutableSubstitution);
// todo assert: no loops
for (TypeParameterDescriptor descriptor : topologicallySortTypeParameters(typeParameters)) {
JetType upperBoundsAsType = descriptor.getUpperBoundsAsType();
JetType substitutedUpperBoundsAsType = substitutor.substitute(upperBoundsAsType, Variance.INVARIANT);
mutableSubstitution.put(descriptor.getTypeConstructor(), new TypeProjectionImpl(substitutedUpperBoundsAsType));
}
return substitutor;
}
@NotNull
private static List<TypeParameterDescriptor> topologicallySortTypeParameters(@NotNull final List<TypeParameterDescriptor> typeParameters) {
// In the end, we want every parameter to have no references to those after it in the list
// This gives us the reversed order: the one that refers to everybody else comes first
List<TypeParameterDescriptor> topOrder = DFS.topologicalOrder(
typeParameters,
new DFS.Neighbors<TypeParameterDescriptor>() {
@NotNull
@Override
public Iterable<TypeParameterDescriptor> getNeighbors(TypeParameterDescriptor current) {
return getTypeParametersFromUpperBounds(current, typeParameters);
}
});
assert topOrder.size() == typeParameters.size() : "All type parameters must be visited, but only " + topOrder + " were";
// Now, the one that refers to everybody else stands in the last position
Collections.reverse(topOrder);
return topOrder;
}
@NotNull
private static List<TypeParameterDescriptor> getTypeParametersFromUpperBounds(
@NotNull TypeParameterDescriptor current,
@NotNull final List<TypeParameterDescriptor> typeParameters
) {
return DFS.dfs(
current.getUpperBounds(),
new DFS.Neighbors<JetType>() {
@NotNull
@Override
public Iterable<JetType> getNeighbors(JetType current) {
return Collections2.transform(current.getArguments(), PROJECTIONS_TO_TYPES);
}
},
new DFS.NodeHandlerWithListResult<JetType, TypeParameterDescriptor>() {
@Override
public boolean beforeChildren(JetType current) {
ClassifierDescriptor declarationDescriptor = current.getConstructor().getDeclarationDescriptor();
// typeParameters in a list, but it contains very few elements, so it's fine to call contains() on it
//noinspection SuspiciousMethodCalls
if (typeParameters.contains(declarationDescriptor)) {
result.add((TypeParameterDescriptor) declarationDescriptor);
}
return true;
}
}
);
}
}
@@ -498,7 +498,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
JetType type = components.reflectionTypes.getKFunctionType( JetType type = components.reflectionTypes.getKFunctionType(
Annotations.EMPTY, Annotations.EMPTY,
receiverType, receiverType,
DescriptorUtils.getValueParametersTypes(descriptor.getValueParameters()), getValueParametersTypes(descriptor.getValueParameters()),
descriptor.getReturnType(), descriptor.getReturnType(),
receiverParameter != null receiverParameter != null
); );
@@ -111,7 +111,7 @@ public class ClosureExpressionsTypingVisitor extends ExpressionTypingVisitor {
functionDescriptor.setReturnType(safeReturnType); functionDescriptor.setReturnType(safeReturnType);
JetType receiver = DescriptorUtils.getReceiverParameterType(functionDescriptor.getReceiverParameter()); JetType receiver = DescriptorUtils.getReceiverParameterType(functionDescriptor.getReceiverParameter());
List<JetType> valueParametersTypes = DescriptorUtils.getValueParametersTypes(functionDescriptor.getValueParameters()); List<JetType> valueParametersTypes = ExpressionTypingUtils.getValueParametersTypes(functionDescriptor.getValueParameters());
JetType resultType = KotlinBuiltIns.getInstance().getFunctionType( JetType resultType = KotlinBuiltIns.getInstance().getFunctionType(
Annotations.EMPTY, receiver, valueParametersTypes, safeReturnType); Annotations.EMPTY, receiver, valueParametersTypes, safeReturnType);
if (!noExpectedType(expectedType) && KotlinBuiltIns.getInstance().isFunctionOrExtensionFunctionType(expectedType)) { if (!noExpectedType(expectedType) && KotlinBuiltIns.getInstance().isFunctionOrExtensionFunctionType(expectedType)) {
@@ -187,7 +187,7 @@ public class ClosureExpressionsTypingVisitor extends ExpressionTypingVisitor {
} }
else { else {
if (expectedValueParameters != null && declaredValueParameters.size() != expectedValueParameters.size()) { if (expectedValueParameters != null && declaredValueParameters.size() != expectedValueParameters.size()) {
List<JetType> expectedParameterTypes = DescriptorUtils.getValueParametersTypes(expectedValueParameters); List<JetType> expectedParameterTypes = ExpressionTypingUtils.getValueParametersTypes(expectedValueParameters);
context.trace.report(EXPECTED_PARAMETERS_NUMBER_MISMATCH.on(functionLiteral, expectedParameterTypes.size(), expectedParameterTypes)); context.trace.report(EXPECTED_PARAMETERS_NUMBER_MISMATCH.on(functionLiteral, expectedParameterTypes.size(), expectedParameterTypes));
} }
for (int i = 0; i < declaredValueParameters.size(); i++) { for (int i = 0; i < declaredValueParameters.size(); i++) {
@@ -370,7 +370,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
// http://youtrack.jetbrains.net/issue/KT-527 // http://youtrack.jetbrains.net/issue/KT-527
VariableDescriptor olderVariable = context.scope.getLocalVariable(variableDescriptor.getName()); VariableDescriptor olderVariable = context.scope.getLocalVariable(variableDescriptor.getName());
if (olderVariable != null && DescriptorUtils.isLocal(context.scope.getContainingDeclaration(), olderVariable)) { if (olderVariable != null && isLocal(context.scope.getContainingDeclaration(), olderVariable)) {
PsiElement declaration = BindingContextUtils.descriptorToDeclaration(context.trace.getBindingContext(), variableDescriptor); PsiElement declaration = BindingContextUtils.descriptorToDeclaration(context.trace.getBindingContext(), variableDescriptor);
context.trace.report(Errors.NAME_SHADOWING.on(declaration, variableDescriptor.getName().asString())); context.trace.report(Errors.NAME_SHADOWING.on(declaration, variableDescriptor.getName().asString()));
} }
@@ -395,7 +395,7 @@ public class ExpressionTypingServices {
JetExpression defaultValue = jetParameter.getDefaultValue(); JetExpression defaultValue = jetParameter.getDefaultValue();
if (defaultValue != null) { if (defaultValue != null) {
getType(declaringScope, defaultValue, valueParameterDescriptor.getType(), dataFlowInfo, trace); getType(declaringScope, defaultValue, valueParameterDescriptor.getType(), dataFlowInfo, trace);
if (DescriptorUtils.isAnnotationClass(DescriptorUtils.getContainingClass(declaringScope))) { if (DescriptorUtils.isAnnotationClass(DescriptorResolver.getContainingClass(declaringScope))) {
ConstantExpressionEvaluator.object$.evaluate(defaultValue, trace, valueParameterDescriptor.getType()); ConstantExpressionEvaluator.object$.evaluate(defaultValue, trace, valueParameterDescriptor.getType());
} }
} }
@@ -427,7 +427,7 @@ public class ExpressionTypingUtils {
} }
public static void checkVariableShadowing(@NotNull ExpressionTypingContext context, @NotNull VariableDescriptor variableDescriptor, VariableDescriptor oldDescriptor) { public static void checkVariableShadowing(@NotNull ExpressionTypingContext context, @NotNull VariableDescriptor variableDescriptor, VariableDescriptor oldDescriptor) {
if (oldDescriptor != null && DescriptorUtils.isLocal(variableDescriptor.getContainingDeclaration(), oldDescriptor)) { if (oldDescriptor != null && isLocal(variableDescriptor.getContainingDeclaration(), oldDescriptor)) {
PsiElement declaration = BindingContextUtils.descriptorToDeclaration(context.trace.getBindingContext(), variableDescriptor); PsiElement declaration = BindingContextUtils.descriptorToDeclaration(context.trace.getBindingContext(), variableDescriptor);
if (declaration != null) { if (declaration != null) {
context.trace.report(Errors.NAME_SHADOWING.on(declaration, variableDescriptor.getName().asString())); context.trace.report(Errors.NAME_SHADOWING.on(declaration, variableDescriptor.getName().asString()));
@@ -486,4 +486,44 @@ public class ExpressionTypingUtils {
public static boolean isUnaryExpressionDependentOnExpectedType(@NotNull JetUnaryExpression expression) { public static boolean isUnaryExpressionDependentOnExpectedType(@NotNull JetUnaryExpression expression) {
return expression.getOperationReference().getReferencedNameElementType() == JetTokens.EXCLEXCL; return expression.getOperationReference().getReferencedNameElementType() == JetTokens.EXCLEXCL;
} }
@NotNull
public static List<JetType> getValueParametersTypes(@NotNull List<ValueParameterDescriptor> valueParameters) {
List<JetType> parameterTypes = new ArrayList<JetType>(valueParameters.size());
for (ValueParameterDescriptor parameter : valueParameters) {
parameterTypes.add(parameter.getType());
}
return parameterTypes;
}
/**
* The primary case for local extensions is the following:
*
* I had a locally declared extension function or a local variable of function type called foo
* And I called it on my x
* Now, someone added function foo() to the class of x
* My code should not change
*
* thus
*
* local extension prevail over members (and members prevail over all non-local extensions)
*/
public static boolean isLocal(DeclarationDescriptor containerOfTheCurrentLocality, DeclarationDescriptor candidate) {
if (candidate instanceof ValueParameterDescriptor) {
return true;
}
DeclarationDescriptor parent = candidate.getContainingDeclaration();
if (!(parent instanceof FunctionDescriptor)) {
return false;
}
FunctionDescriptor functionDescriptor = (FunctionDescriptor) parent;
DeclarationDescriptor current = containerOfTheCurrentLocality;
while (current != null) {
if (current == functionDescriptor) {
return true;
}
current = current.getContainingDeclaration();
}
return false;
}
} }
@@ -41,13 +41,15 @@ import org.jetbrains.jet.lang.psi.JetDeclaration;
import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingContextUtils; import org.jetbrains.jet.lang.resolve.BindingContextUtils;
import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.types.JetType;
import java.io.File; import java.io.File;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.net.URL; import java.net.URL;
import java.net.URLClassLoader; import java.net.URLClassLoader;
import static org.jetbrains.jet.lang.types.TypeUtils.getAllSupertypes;
@SuppressWarnings("JUnitTestCaseWithNoTests") @SuppressWarnings("JUnitTestCaseWithNoTests")
public class TestlibTest extends UsefulTestCase { public class TestlibTest extends UsefulTestCase {
public static Test suite() { public static Test suite() {
@@ -123,8 +125,8 @@ public class TestlibTest extends UsefulTestCase {
BindingContext.DECLARATION_TO_DESCRIPTOR, BindingContext.DECLARATION_TO_DESCRIPTOR,
declaration); declaration);
for (ClassDescriptor superClass : DescriptorUtils.getAllSuperClasses(descriptor)) { for (JetType superType : getAllSupertypes(descriptor.getDefaultType())) {
if (!"junit/framework/Test".equals(typeMapper.mapClass(superClass).getInternalName())) continue; if (!"junit/framework/Test".equals(typeMapper.mapType(superType).getInternalName())) continue;
String name = typeMapper.mapClass(descriptor).getInternalName(); String name = typeMapper.mapClass(descriptor).getInternalName();
@@ -23,11 +23,11 @@ import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.descriptors.ModuleDescriptor; import org.jetbrains.jet.lang.descriptors.ModuleDescriptor;
import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.psi.JetPsiFactory; import org.jetbrains.jet.lang.psi.JetPsiFactory;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.lazy.KotlinTestWithEnvironment; import org.jetbrains.jet.lang.resolve.lazy.KotlinTestWithEnvironment;
import org.jetbrains.jet.lang.resolve.lazy.LazyResolveTestUtil; import org.jetbrains.jet.lang.resolve.lazy.LazyResolveTestUtil;
import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.types.BoundsSubstitutor;
import org.jetbrains.jet.renderer.DescriptorRenderer; import org.jetbrains.jet.renderer.DescriptorRenderer;
import java.util.Collection; import java.util.Collection;
@@ -76,7 +76,7 @@ public class BoundsSubstitutorTest extends KotlinTestWithEnvironment {
assert functions.size() == 1 : "Many functions defined"; assert functions.size() == 1 : "Many functions defined";
FunctionDescriptor function = ContainerUtil.getFirstItem(functions); FunctionDescriptor function = ContainerUtil.getFirstItem(functions);
FunctionDescriptor substituted = DescriptorUtils.substituteBounds(function); FunctionDescriptor substituted = BoundsSubstitutor.substituteBounds(function);
String actual = DescriptorRenderer.COMPACT.render(substituted); String actual = DescriptorRenderer.COMPACT.render(substituted);
assertEquals(expected, actual); assertEquals(expected, actual);
} }
@@ -17,8 +17,6 @@
package org.jetbrains.jet.lang.resolve; package org.jetbrains.jet.lang.resolve;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.*;
@@ -33,7 +31,6 @@ import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lang.types.checker.JetTypeChecker; import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import javax.rmi.CORBA.ClassDesc;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
@@ -45,19 +42,6 @@ public class DescriptorUtils {
private DescriptorUtils() { private DescriptorUtils() {
} }
@NotNull
public static <D extends CallableDescriptor> D substituteBounds(@NotNull D functionDescriptor) {
List<TypeParameterDescriptor> typeParameters = functionDescriptor.getTypeParameters();
if (typeParameters.isEmpty()) return functionDescriptor;
// TODO: this does not handle any recursion in the bounds
@SuppressWarnings("unchecked")
D substitutedFunction = (D) functionDescriptor.substitute(DescriptorSubstitutor.createUpperBoundsSubstitutor(typeParameters));
assert substitutedFunction != null : "Substituting upper bounds should always be legal";
return substitutedFunction;
}
@Nullable @Nullable
public static ReceiverParameterDescriptor getExpectedThisObjectIfNeeded(@NotNull DeclarationDescriptor containingDeclaration) { public static ReceiverParameterDescriptor getExpectedThisObjectIfNeeded(@NotNull DeclarationDescriptor containingDeclaration) {
if (containingDeclaration instanceof ClassDescriptor) { if (containingDeclaration instanceof ClassDescriptor) {
@@ -72,38 +56,7 @@ public class DescriptorUtils {
} }
/** /**
* The primary case for local extensions is the following: * Descriptor may be local itself or have a local ancestor
*
* I had a locally declared extension function or a local variable of function type called foo
* And I called it on my x
* Now, someone added function foo() to the class of x
* My code should not change
*
* thus
*
* local extension prevail over members (and members prevail over all non-local extensions)
*/
public static boolean isLocal(DeclarationDescriptor containerOfTheCurrentLocality, DeclarationDescriptor candidate) {
if (candidate instanceof ValueParameterDescriptor) {
return true;
}
DeclarationDescriptor parent = candidate.getContainingDeclaration();
if (!(parent instanceof FunctionDescriptor)) {
return false;
}
FunctionDescriptor functionDescriptor = (FunctionDescriptor) parent;
DeclarationDescriptor current = containerOfTheCurrentLocality;
while (current != null) {
if (current == functionDescriptor) {
return true;
}
current = current.getContainingDeclaration();
}
return false;
}
/**
* descriptor may be local itself or have a local ancestor
*/ */
public static boolean isLocal(@NotNull DeclarationDescriptor descriptor) { public static boolean isLocal(@NotNull DeclarationDescriptor descriptor) {
DeclarationDescriptor current = descriptor; DeclarationDescriptor current = descriptor;
@@ -166,18 +119,6 @@ public class DescriptorUtils {
return getContainingModule(first).equals(getContainingModule(second)); return getContainingModule(first).equals(getContainingModule(second));
} }
@Nullable
public static DeclarationDescriptor findTopLevelParent(@NotNull DeclarationDescriptor declarationDescriptor) {
DeclarationDescriptor descriptor = declarationDescriptor;
if (declarationDescriptor instanceof PropertyAccessorDescriptor) {
descriptor = ((PropertyAccessorDescriptor) descriptor).getCorrespondingProperty();
}
while (!(descriptor == null || isTopLevelDeclaration(descriptor))) {
descriptor = descriptor.getContainingDeclaration();
}
return descriptor;
}
@Nullable @Nullable
public static <D extends DeclarationDescriptor> D getParentOfType( public static <D extends DeclarationDescriptor> D getParentOfType(
@Nullable DeclarationDescriptor descriptor, @Nullable DeclarationDescriptor descriptor,
@@ -372,55 +313,9 @@ public class DescriptorUtils {
return (ClassDescriptor) classifier; return (ClassDescriptor) classifier;
} }
@NotNull
public static ConstructorDescriptor getConstructorOfDataClass(ClassDescriptor classDescriptor) {
ConstructorDescriptor descriptor = getConstructorDescriptorIfOnlyOne(classDescriptor);
assert descriptor != null : "Data class must have only one constructor: " + classDescriptor.getConstructors();
return descriptor;
}
@NotNull
public static ConstructorDescriptor getConstructorOfSingletonObject(ClassDescriptor classDescriptor) {
ConstructorDescriptor descriptor = getConstructorDescriptorIfOnlyOne(classDescriptor);
assert descriptor != null : "Class of singleton object must have only one constructor: " + classDescriptor.getConstructors();
return descriptor;
}
@Nullable
private static ConstructorDescriptor getConstructorDescriptorIfOnlyOne(ClassDescriptor classDescriptor) {
Collection<ConstructorDescriptor> constructors = classDescriptor.getConstructors();
return constructors.size() != 1 ? null : constructors.iterator().next();
}
@Nullable @Nullable
public static JetType getReceiverParameterType(@Nullable ReceiverParameterDescriptor receiverParameterDescriptor) { public static JetType getReceiverParameterType(@Nullable ReceiverParameterDescriptor receiverParameterDescriptor) {
if (receiverParameterDescriptor == null) { return receiverParameterDescriptor == null ? null : receiverParameterDescriptor.getType();
return null;
}
return receiverParameterDescriptor.getType();
}
@NotNull
public static JetType getVarargParameterType(@NotNull JetType elementType) {
JetType primitiveArrayType = KotlinBuiltIns.getInstance().getPrimitiveArrayJetTypeByPrimitiveJetType(elementType);
return primitiveArrayType != null ? primitiveArrayType : KotlinBuiltIns.getInstance().getArrayType(Variance.INVARIANT, elementType);
}
@NotNull
public static List<JetType> getValueParametersTypes(@NotNull List<ValueParameterDescriptor> valueParameters) {
List<JetType> parameterTypes = Lists.newArrayList();
for (ValueParameterDescriptor parameter : valueParameters) {
parameterTypes.add(parameter.getType());
}
return parameterTypes;
}
public static boolean isInsideOuterClassOrItsSubclass(@Nullable DeclarationDescriptor nested, @NotNull ClassDescriptor outer) {
if (nested == null) return false;
if (nested instanceof ClassDescriptor && isSubclass((ClassDescriptor) nested, outer)) return true;
return isInsideOuterClassOrItsSubclass(nested.getContainingDeclaration(), outer);
} }
public static boolean isConstructorOfStaticNestedClass(@Nullable CallableDescriptor descriptor) { public static boolean isConstructorOfStaticNestedClass(@Nullable CallableDescriptor descriptor) {
@@ -437,12 +332,6 @@ public class DescriptorUtils {
!((ClassDescriptor) descriptor).isInner(); !((ClassDescriptor) descriptor).isInner();
} }
@Nullable
public static ClassDescriptor getContainingClass(@NotNull JetScope scope) {
DeclarationDescriptor containingDeclaration = scope.getContainingDeclaration();
return getParentOfType(containingDeclaration, ClassDescriptor.class, false);
}
@NotNull @NotNull
public static JetScope getStaticNestedClassesScope(@NotNull ClassDescriptor descriptor) { public static JetScope getStaticNestedClassesScope(@NotNull ClassDescriptor descriptor) {
JetScope innerClassesScope = descriptor.getUnsubstitutedInnerClassesScope(); JetScope innerClassesScope = descriptor.getUnsubstitutedInnerClassesScope();
@@ -468,18 +357,6 @@ public class DescriptorUtils {
&& methodTypeParameters.isEmpty(); && methodTypeParameters.isEmpty();
} }
@NotNull
public static Set<ClassDescriptor> getAllSuperClasses(@NotNull ClassDescriptor klass) {
Set<JetType> allSupertypes = TypeUtils.getAllSupertypes(klass.getDefaultType());
Set<ClassDescriptor> allSuperclasses = Sets.newHashSet();
for (JetType supertype : allSupertypes) {
ClassDescriptor superclass = TypeUtils.getClassDescriptor(supertype);
assert superclass != null;
allSuperclasses.add(superclass);
}
return allSuperclasses;
}
/** /**
* @return true iff {@code descriptor}'s first non-class container is a package * @return true iff {@code descriptor}'s first non-class container is a package
*/ */
@@ -507,17 +384,6 @@ public class DescriptorUtils {
return descriptor; return descriptor;
} }
public static boolean isPropertyCompileTimeConstant(@NotNull VariableDescriptor descriptor) {
if (descriptor.isVar()) {
return false;
}
if (isClassObject(descriptor.getContainingDeclaration()) || isTopLevelDeclaration(descriptor)) {
JetType type = descriptor.getType();
return KotlinBuiltIns.getInstance().isPrimitiveType(type) || KotlinBuiltIns.getInstance().getStringType().equals(type);
}
return false;
}
public static boolean shouldRecordInitializerForProperty(@NotNull VariableDescriptor variable, @NotNull JetType type) { public static boolean shouldRecordInitializerForProperty(@NotNull VariableDescriptor variable, @NotNull JetType type) {
if (variable.isVar() || type.isError()) return false; if (variable.isVar() || type.isError()) return false;
@@ -1,5 +1,5 @@
/* /*
* Copyright 2010-2013 JetBrains s.r.o. * Copyright 2010-2014 JetBrains s.r.o.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@@ -16,38 +16,28 @@
package org.jetbrains.jet.lang.types; package org.jetbrains.jet.lang.types;
import com.google.common.base.Function;
import com.google.common.collect.Collections2;
import com.google.common.collect.Maps;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
import org.jetbrains.jet.lang.descriptors.impl.TypeParameterDescriptorImpl; import org.jetbrains.jet.lang.descriptors.impl.TypeParameterDescriptorImpl;
import org.jetbrains.jet.utils.DFS;
import java.util.Collections; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
public class DescriptorSubstitutor { public class DescriptorSubstitutor {
private DescriptorSubstitutor() {
private static final Function<TypeProjection,JetType> PROJECTIONS_TO_TYPES = new Function<TypeProjection, JetType>() { }
@Override
public JetType apply(TypeProjection projection) {
return projection.getType();
}
};
@NotNull @NotNull
public static TypeSubstitutor substituteTypeParameters( public static TypeSubstitutor substituteTypeParameters(
@NotNull List<TypeParameterDescriptor> typeParameters, @NotNull List<TypeParameterDescriptor> typeParameters,
@NotNull final TypeSubstitutor originalSubstitutor, @NotNull final TypeSubstitutor originalSubstitutor,
@NotNull DeclarationDescriptor newContainingDeclaration, @NotNull DeclarationDescriptor newContainingDeclaration,
@NotNull List<TypeParameterDescriptor> result) { @NotNull List<TypeParameterDescriptor> result
final Map<TypeConstructor, TypeProjection> mutableSubstitution = Maps.newHashMap(); ) {
final Map<TypeConstructor, TypeProjection> mutableSubstitution = new HashMap<TypeConstructor, TypeProjection>();
TypeSubstitutor substitutor = TypeSubstitutor.create(new TypeSubstitution() { TypeSubstitutor substitutor = TypeSubstitutor.create(new TypeSubstitution() {
@Override @Override
public TypeProjection get(TypeConstructor key) { public TypeProjection get(TypeConstructor key) {
if (originalSubstitutor.inRange(key)) { if (originalSubstitutor.inRange(key)) {
@@ -66,7 +56,9 @@ public class DescriptorSubstitutor {
return "DescriptorSubstitutor.substituteTypeParameters(" + mutableSubstitution + " / " + originalSubstitutor.getSubstitution() + ")"; return "DescriptorSubstitutor.substituteTypeParameters(" + mutableSubstitution + " / " + originalSubstitutor.getSubstitution() + ")";
} }
}); });
Map<TypeParameterDescriptor, TypeParameterDescriptorImpl> substitutedMap = Maps.newHashMap();
Map<TypeParameterDescriptor, TypeParameterDescriptorImpl> substitutedMap =
new HashMap<TypeParameterDescriptor, TypeParameterDescriptorImpl>();
for (TypeParameterDescriptor descriptor : typeParameters) { for (TypeParameterDescriptor descriptor : typeParameters) {
TypeParameterDescriptorImpl substituted = TypeParameterDescriptorImpl.createForFurtherModification( TypeParameterDescriptorImpl substituted = TypeParameterDescriptorImpl.createForFurtherModification(
newContainingDeclaration, newContainingDeclaration,
@@ -74,7 +66,8 @@ public class DescriptorSubstitutor {
descriptor.isReified(), descriptor.isReified(),
descriptor.getVariance(), descriptor.getVariance(),
descriptor.getName(), descriptor.getName(),
descriptor.getIndex()); descriptor.getIndex()
);
substituted.setInitialized(); substituted.setInitialized();
mutableSubstitution.put(descriptor.getTypeConstructor(), new TypeProjectionImpl(substituted.getDefaultType())); mutableSubstitution.put(descriptor.getTypeConstructor(), new TypeProjectionImpl(substituted.getDefaultType()));
@@ -92,72 +85,4 @@ public class DescriptorSubstitutor {
return substitutor; return substitutor;
} }
@NotNull
public static TypeSubstitutor createUpperBoundsSubstitutor(
@NotNull List<TypeParameterDescriptor> typeParameters
) {
Map<TypeConstructor, TypeProjection> mutableSubstitution = Maps.newHashMap();
TypeSubstitutor substitutor = TypeSubstitutor.create(mutableSubstitution);
// todo assert: no loops
for (TypeParameterDescriptor descriptor : topologicallySortTypeParameters(typeParameters)) {
JetType upperBoundsAsType = descriptor.getUpperBoundsAsType();
JetType substitutedUpperBoundsAsType = substitutor.substitute(upperBoundsAsType, Variance.INVARIANT);
mutableSubstitution.put(descriptor.getTypeConstructor(), new TypeProjectionImpl(substitutedUpperBoundsAsType));
}
return substitutor;
}
private static List<TypeParameterDescriptor> topologicallySortTypeParameters(final List<TypeParameterDescriptor> typeParameters) {
// In the end, we want every parameter to have no references to those after it in the list
// This gives us the reversed order: the one that refers to everybody else comes first
List<TypeParameterDescriptor> topOrder = DFS.topologicalOrder(
typeParameters,
new DFS.Neighbors<TypeParameterDescriptor>() {
@NotNull
@Override
public Iterable<TypeParameterDescriptor> getNeighbors(TypeParameterDescriptor current) {
return getTypeParametersFromUpperBounds(current, typeParameters);
}
});
assert topOrder.size() == typeParameters.size() : "All type parameters must be visited, but only " + topOrder + " were";
// Now, the one that refers to everybody else stands in the last position
Collections.reverse(topOrder);
return topOrder;
}
private static List<TypeParameterDescriptor> getTypeParametersFromUpperBounds(
TypeParameterDescriptor current,
final List<TypeParameterDescriptor> typeParameters
) {
return DFS.dfs(
current.getUpperBounds(),
new DFS.Neighbors<JetType>() {
@NotNull
@Override
public Iterable<JetType> getNeighbors(JetType current) {
return Collections2.transform(current.getArguments(), PROJECTIONS_TO_TYPES);
}
},
new DFS.NodeHandlerWithListResult<JetType, TypeParameterDescriptor>() {
@Override
public boolean beforeChildren(JetType current) {
ClassifierDescriptor declarationDescriptor = current.getConstructor().getDeclarationDescriptor();
// typeParameters in a list, but it contains very few elements, so it's fine to call contains() on it
//noinspection SuspiciousMethodCalls
if (typeParameters.contains(declarationDescriptor)) {
result.add((TypeParameterDescriptor) declarationDescriptor);
}
return true;
}
}
);
}
} }
@@ -29,6 +29,7 @@ import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.java.PackageClassUtils; import org.jetbrains.jet.lang.resolve.java.PackageClassUtils;
import org.jetbrains.jet.lang.resolve.kotlin.VirtualFileFinder; import org.jetbrains.jet.lang.resolve.kotlin.VirtualFileFinder;
import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils;
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getFqName; import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getFqName;
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getFqNameSafe; import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getFqNameSafe;
@@ -113,7 +114,7 @@ public final class DecompiledNavigationUtils {
} }
if (containerDescriptor instanceof ClassDescriptor) { if (containerDescriptor instanceof ClassDescriptor) {
if (containerDescriptor.getContainingDeclaration() instanceof ClassDescriptor if (containerDescriptor.getContainingDeclaration() instanceof ClassDescriptor
|| DescriptorUtils.isLocal(containerDescriptor.getContainingDeclaration(), containerDescriptor)) { || ExpressionTypingUtils.isLocal(containerDescriptor.getContainingDeclaration(), containerDescriptor)) {
return getContainerFqName(containerDescriptor.getContainingDeclaration()); return getContainerFqName(containerDescriptor.getContainingDeclaration());
} }
return getFqNameSafe(containerDescriptor); return getFqNameSafe(containerDescriptor);