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:
@@ -17,8 +17,6 @@
|
||||
package org.jetbrains.jet.lang.resolve;
|
||||
|
||||
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.Nullable;
|
||||
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.lang.KotlinBuiltIns;
|
||||
|
||||
import javax.rmi.CORBA.ClassDesc;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
@@ -45,19 +42,6 @@ public class 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
|
||||
public static ReceiverParameterDescriptor getExpectedThisObjectIfNeeded(@NotNull DeclarationDescriptor containingDeclaration) {
|
||||
if (containingDeclaration instanceof ClassDescriptor) {
|
||||
@@ -72,38 +56,7 @@ public class DescriptorUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* descriptor may be local itself or have a local ancestor
|
||||
* Descriptor may be local itself or have a local ancestor
|
||||
*/
|
||||
public static boolean isLocal(@NotNull DeclarationDescriptor descriptor) {
|
||||
DeclarationDescriptor current = descriptor;
|
||||
@@ -166,18 +119,6 @@ public class DescriptorUtils {
|
||||
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
|
||||
public static <D extends DeclarationDescriptor> D getParentOfType(
|
||||
@Nullable DeclarationDescriptor descriptor,
|
||||
@@ -372,55 +313,9 @@ public class DescriptorUtils {
|
||||
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
|
||||
public static JetType getReceiverParameterType(@Nullable ReceiverParameterDescriptor receiverParameterDescriptor) {
|
||||
if (receiverParameterDescriptor == null) {
|
||||
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);
|
||||
return receiverParameterDescriptor == null ? null : receiverParameterDescriptor.getType();
|
||||
}
|
||||
|
||||
public static boolean isConstructorOfStaticNestedClass(@Nullable CallableDescriptor descriptor) {
|
||||
@@ -437,12 +332,6 @@ public class DescriptorUtils {
|
||||
!((ClassDescriptor) descriptor).isInner();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static ClassDescriptor getContainingClass(@NotNull JetScope scope) {
|
||||
DeclarationDescriptor containingDeclaration = scope.getContainingDeclaration();
|
||||
return getParentOfType(containingDeclaration, ClassDescriptor.class, false);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static JetScope getStaticNestedClassesScope(@NotNull ClassDescriptor descriptor) {
|
||||
JetScope innerClassesScope = descriptor.getUnsubstitutedInnerClassesScope();
|
||||
@@ -468,18 +357,6 @@ public class DescriptorUtils {
|
||||
&& 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
|
||||
*/
|
||||
@@ -507,17 +384,6 @@ public class DescriptorUtils {
|
||||
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) {
|
||||
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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,38 +16,28 @@
|
||||
|
||||
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.jet.lang.descriptors.ClassifierDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
||||
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.Map;
|
||||
|
||||
public class DescriptorSubstitutor {
|
||||
|
||||
private static final Function<TypeProjection,JetType> PROJECTIONS_TO_TYPES = new Function<TypeProjection, JetType>() {
|
||||
@Override
|
||||
public JetType apply(TypeProjection projection) {
|
||||
return projection.getType();
|
||||
}
|
||||
};
|
||||
private DescriptorSubstitutor() {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static TypeSubstitutor substituteTypeParameters(
|
||||
@NotNull List<TypeParameterDescriptor> typeParameters,
|
||||
@NotNull final TypeSubstitutor originalSubstitutor,
|
||||
@NotNull DeclarationDescriptor newContainingDeclaration,
|
||||
@NotNull List<TypeParameterDescriptor> result) {
|
||||
final Map<TypeConstructor, TypeProjection> mutableSubstitution = Maps.newHashMap();
|
||||
@NotNull List<TypeParameterDescriptor> result
|
||||
) {
|
||||
final Map<TypeConstructor, TypeProjection> mutableSubstitution = new HashMap<TypeConstructor, TypeProjection>();
|
||||
TypeSubstitutor substitutor = TypeSubstitutor.create(new TypeSubstitution() {
|
||||
|
||||
@Override
|
||||
public TypeProjection get(TypeConstructor key) {
|
||||
if (originalSubstitutor.inRange(key)) {
|
||||
@@ -66,7 +56,9 @@ public class DescriptorSubstitutor {
|
||||
return "DescriptorSubstitutor.substituteTypeParameters(" + mutableSubstitution + " / " + originalSubstitutor.getSubstitution() + ")";
|
||||
}
|
||||
});
|
||||
Map<TypeParameterDescriptor, TypeParameterDescriptorImpl> substitutedMap = Maps.newHashMap();
|
||||
|
||||
Map<TypeParameterDescriptor, TypeParameterDescriptorImpl> substitutedMap =
|
||||
new HashMap<TypeParameterDescriptor, TypeParameterDescriptorImpl>();
|
||||
for (TypeParameterDescriptor descriptor : typeParameters) {
|
||||
TypeParameterDescriptorImpl substituted = TypeParameterDescriptorImpl.createForFurtherModification(
|
||||
newContainingDeclaration,
|
||||
@@ -74,7 +66,8 @@ public class DescriptorSubstitutor {
|
||||
descriptor.isReified(),
|
||||
descriptor.getVariance(),
|
||||
descriptor.getName(),
|
||||
descriptor.getIndex());
|
||||
descriptor.getIndex()
|
||||
);
|
||||
substituted.setInitialized();
|
||||
|
||||
mutableSubstitution.put(descriptor.getTypeConstructor(), new TypeProjectionImpl(substituted.getDefaultType()));
|
||||
@@ -92,72 +85,4 @@ public class DescriptorSubstitutor {
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user