diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index 15ef11f2960..6650d907bfb 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -43,6 +43,7 @@ import org.jetbrains.jet.descriptors.serialization.ProtoBuf; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.psi.*; 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.calls.CallResolverUtil; import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; @@ -838,7 +839,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { iv.anew(thisDescriptorType); iv.dup(); - ConstructorDescriptor constructor = DescriptorUtils.getConstructorOfDataClass(descriptor); + ConstructorDescriptor constructor = DeclarationResolver.getConstructorOfDataClass(descriptor); assert function.getValueParameters().size() == constructor.getValueParameters().size() : "Number of parameters of copy function and constructor are different. " + "Copy: " + function.getValueParameters().size() + ", " + @@ -1124,9 +1125,11 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { protected void genInitSingleton(ClassDescriptor fieldTypeDescriptor, StackValue.Field field) { if (state.getClassBuilderMode() == ClassBuilderMode.FULL) { - ConstructorDescriptor constructorDescriptor = DescriptorUtils.getConstructorOfSingletonObject(fieldTypeDescriptor); + Collection constructors = fieldTypeDescriptor.getConstructors(); + assert constructors.size() == 1 : "Class of singleton object must have only one constructor: " + constructors; + ExpressionCodegen codegen = createOrGetClInitCodegen(); - FunctionDescriptor fd = codegen.accessibleFunctionDescriptor(constructorDescriptor); + FunctionDescriptor fd = codegen.accessibleFunctionDescriptor(constructors.iterator().next()); generateMethodCallTo(fd, codegen.v); field.store(field.type, codegen.v); } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/JvmRuntimeTypes.java b/compiler/backend/src/org/jetbrains/jet/codegen/JvmRuntimeTypes.java index 86818b815b4..25e7ab540d8 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/JvmRuntimeTypes.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/JvmRuntimeTypes.java @@ -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.TypeParameterDescriptorImpl; 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.java.mapping.JavaToKotlinClassMap; import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.types.*; +import org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; import java.util.*; @@ -117,7 +117,7 @@ public class JvmRuntimeTypes { JetType functionType = KotlinBuiltIns.getInstance().getFunctionType( Annotations.EMPTY, receiverParameter == null ? null : receiverParameter.getType(), - DescriptorUtils.getValueParametersTypes(descriptor.getValueParameters()), + ExpressionTypingUtils.getValueParametersTypes(descriptor.getValueParameters()), descriptor.getReturnType() ); @@ -162,7 +162,7 @@ public class JvmRuntimeTypes { JetType kFunctionType = reflectionTypes.getKFunctionType( Annotations.EMPTY, receiverType, - DescriptorUtils.getValueParametersTypes(descriptor.getValueParameters()), + ExpressionTypingUtils.getValueParametersTypes(descriptor.getValueParameters()), descriptor.getReturnType(), receiverParameter != null ); diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/JavaToKotlinMethodMap.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/JavaToKotlinMethodMap.java index e44ce419307..36866814156 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/JavaToKotlinMethodMap.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/JavaToKotlinMethodMap.java @@ -32,10 +32,7 @@ import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; import org.jetbrains.jet.renderer.DescriptorRenderer; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; public class JavaToKotlinMethodMap { public static final JavaToKotlinMethodMap INSTANCE = new JavaToKotlinMethodMap(); @@ -55,7 +52,7 @@ public class JavaToKotlinMethodMap { List result = Lists.newArrayList(); - Set allSuperClasses = DescriptorUtils.getAllSuperClasses(containingClass); + Set allSuperClasses = new HashSet(DescriptorUtils.getSuperclassDescriptors(containingClass)); String serializedMethod = JavaSignatureFormatter.getInstance().formatMethod(javaMethod); for (ClassData classData : classDatas) { diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaPropertyInitializerEvaluatorImpl.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaPropertyInitializerEvaluatorImpl.java index 929a1ecfe28..bfe6d1706fe 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaPropertyInitializerEvaluatorImpl.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaPropertyInitializerEvaluatorImpl.java @@ -21,7 +21,7 @@ import com.intellij.psi.impl.JavaConstantExpressionEvaluator; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; 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.ConstantsPackage; import org.jetbrains.jet.lang.resolve.java.structure.JavaField; @@ -36,7 +36,7 @@ public class JavaPropertyInitializerEvaluatorImpl implements JavaPropertyInitial if (evaluatedExpression != null) { return ConstantsPackage.createCompileTimeConstant( evaluatedExpression, - DescriptorUtils.isPropertyCompileTimeConstant(descriptor), + ConstantExpressionEvaluator.object$.isPropertyCompileTimeConstant(descriptor), false, true, descriptor.getType()); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java index 8bafae1e6a1..6566a125ad4 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/cfg/JetFlowInformationProvider.java @@ -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.ThisReceiver; 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.lexer.JetTokens; import org.jetbrains.jet.plugin.MainFunctionDetector; @@ -591,7 +592,7 @@ public class JetFlowInformationProvider { VariableDescriptor variableDescriptor = PseudocodeUtil.extractVariableDescriptorIfAny( instruction, false, trace.getBindingContext()); if (variableDescriptor == null || !declaredVariables.contains(variableDescriptor) - || !DescriptorUtils.isLocal(variableDescriptor.getContainingDeclaration(), variableDescriptor)) { + || !ExpressionTypingUtils.isLocal(variableDescriptor.getContainingDeclaration(), variableDescriptor)) { return; } PseudocodeVariablesData.VariableUseState variableUseState = in.get(variableDescriptor); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/evaluate/ConstantExpressionEvaluator.kt b/compiler/frontend/src/org/jetbrains/jet/lang/evaluate/ConstantExpressionEvaluator.kt index 3131614b810..98336f2dd07 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/evaluate/ConstantExpressionEvaluator.kt +++ b/compiler/frontend/src/org/jetbrains/jet/lang/evaluate/ConstantExpressionEvaluator.kt @@ -41,6 +41,17 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet val evaluator = ConstantExpressionEvaluator(trace) 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<*>? { @@ -311,7 +322,7 @@ public class ConstantExpressionEvaluator private (val trace: BindingTrace) : Jet else compileTimeConstant.getValue() return createCompileTimeConstant(value, expectedType, isPure = false, - canBeUsedInAnnotation = DescriptorUtils.isPropertyCompileTimeConstant(callableDescriptor), + canBeUsedInAnnotation = isPropertyCompileTimeConstant(callableDescriptor), usesVariableAsConstant = true) } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContextUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContextUtils.java index b982bd5197d..a0f5f88c882 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContextUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/BindingContextUtils.java @@ -89,7 +89,7 @@ public class BindingContextUtils { public static JetFile getContainingFile(@NotNull BindingContext context, @NotNull DeclarationDescriptor declarationDescriptor) { // 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 - DeclarationDescriptor descriptor = DescriptorUtils.findTopLevelParent(declarationDescriptor); + DeclarationDescriptor descriptor = findTopLevelParent(declarationDescriptor); if (descriptor == null) return null; PsiElement declaration = descriptorToDeclaration(context, descriptor); @@ -100,6 +100,18 @@ public class BindingContextUtils { 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 private static PsiElement doGetDescriptorToDeclaration(@NotNull BindingContext context, @NotNull DeclarationDescriptor descriptor) { return context.get(DESCRIPTOR_TO_DECLARATION, descriptor); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DeclarationResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DeclarationResolver.java index 8527d137a00..ded579ce706 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DeclarationResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DeclarationResolver.java @@ -203,13 +203,20 @@ public class DeclarationResolver { MutableClassDescriptor classDescriptor = (MutableClassDescriptor) entry.getValue(); if (klass instanceof JetClass && klass.hasPrimaryConstructor() && KotlinBuiltIns.getInstance().isData(classDescriptor)) { - ConstructorDescriptor constructor = DescriptorUtils.getConstructorOfDataClass(classDescriptor); + ConstructorDescriptor constructor = getConstructorOfDataClass(classDescriptor); createComponentFunctions(classDescriptor, constructor); createCopyFunction(classDescriptor, constructor); } } } + @NotNull + public static ConstructorDescriptor getConstructorOfDataClass(@NotNull ClassDescriptor classDescriptor) { + Collection 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) { int parameterIndex = 0; for (ValueParameterDescriptor parameter : constructorDescriptor.getValueParameters()) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java index 9afc4b1a47a..f10296c0801 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/DescriptorResolver.java @@ -546,7 +546,7 @@ public class DescriptorResolver { JetType variableType = type; if (valueParameter.hasModifier(VARARG_KEYWORD)) { varargElementType = type; - variableType = DescriptorUtils.getVarargParameterType(type); + variableType = getVarargParameterType(type); } ValueParameterDescriptorImpl valueParameterDescriptor = new ValueParameterDescriptorImpl( declarationDescriptor, @@ -563,6 +563,15 @@ public class DescriptorResolver { 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 resolveTypeParametersForCallableDescriptor( DeclarationDescriptor containingDescriptor, WritableScope extensibleScope, @@ -791,7 +800,7 @@ public class DescriptorResolver { type = ErrorUtils.createErrorType("Annotation is absent"); } if (parameter.hasModifier(VARARG_KEYWORD)) { - return DescriptorUtils.getVarargParameterType(type); + return getVarargParameterType(type); } return type; } @@ -1259,7 +1268,7 @@ public class DescriptorResolver { parameterScope, valueParameters, trace), resolveVisibilityFromModifiers(modifierList, getDefaultConstructorVisibility(classDescriptor)), - DescriptorUtils.isConstructorOfStaticNestedClass(constructorDescriptor)); + isConstructorOfStaticNestedClass(constructorDescriptor)); if (isAnnotationClass(classDescriptor)) { CompileTimeConstantUtils.checkConstructorParametersType(valueParameters, trace); } @@ -1425,6 +1434,19 @@ public class DescriptorResolver { 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( @NotNull BindingTrace trace, @NotNull JetParameter parameter, diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/results/OverloadingConflictResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/results/OverloadingConflictResolver.java index 2bd6d32a3c8..ab5a4ca37f7 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/results/OverloadingConflictResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/results/OverloadingConflictResolver.java @@ -21,11 +21,11 @@ import gnu.trove.TObjectHashingStrategy; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; 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.calls.model.MutableResolvedCall; import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; 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.TypeUtils; import org.jetbrains.jet.lang.types.checker.JetTypeChecker; @@ -131,7 +131,7 @@ public class OverloadingConflictResolver { if (isGenericF && !isGenericG) return false; if (isGenericF && isGenericG) { - return moreSpecific(DescriptorUtils.substituteBounds(f), DescriptorUtils.substituteBounds(g), false); + return moreSpecific(BoundsSubstitutor.substituteBounds(f), BoundsSubstitutor.substituteBounds(g), false); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TaskPrioritizer.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TaskPrioritizer.java index 5166f22bd2a..63b8aa1c049 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TaskPrioritizer.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TaskPrioritizer.java @@ -38,8 +38,11 @@ import org.jetbrains.jet.lang.types.ErrorUtils; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.PackageType; 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.tasks.ExplicitReceiverKind.*; @@ -54,7 +57,7 @@ public class TaskPrioritizer { @NotNull Collection> nonlocal ) { for (ResolutionCandidate resolvedCall : allDescriptors) { - if (DescriptorUtils.isLocal(containerOfTheCurrentLocality, resolvedCall.getDescriptor())) { + if (ExpressionTypingUtils.isLocal(containerOfTheCurrentLocality, resolvedCall.getDescriptor())) { local.add(resolvedCall); } else { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/BoundsSubstitutor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/BoundsSubstitutor.java new file mode 100644 index 00000000000..c0f85a943ab --- /dev/null +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/BoundsSubstitutor.java @@ -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 PROJECTIONS_TO_TYPES = new Function() { + @Override + public JetType apply(TypeProjection projection) { + return projection.getType(); + } + }; + + private BoundsSubstitutor() { + } + + @NotNull + public static D substituteBounds(@NotNull D functionDescriptor) { + List 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 typeParameters) { + Map mutableSubstitution = new HashMap(); + 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 topologicallySortTypeParameters(@NotNull final List 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 topOrder = DFS.topologicalOrder( + typeParameters, + new DFS.Neighbors() { + @NotNull + @Override + public Iterable 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 getTypeParametersFromUpperBounds( + @NotNull TypeParameterDescriptor current, + @NotNull final List typeParameters + ) { + return DFS.dfs( + current.getUpperBounds(), + new DFS.Neighbors() { + @NotNull + @Override + public Iterable getNeighbors(JetType current) { + return Collections2.transform(current.getArguments(), PROJECTIONS_TO_TYPES); + } + }, + new DFS.NodeHandlerWithListResult() { + @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; + } + } + ); + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java index edf331d8c97..976d1b5ab19 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java @@ -498,7 +498,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { JetType type = components.reflectionTypes.getKFunctionType( Annotations.EMPTY, receiverType, - DescriptorUtils.getValueParametersTypes(descriptor.getValueParameters()), + getValueParametersTypes(descriptor.getValueParameters()), descriptor.getReturnType(), receiverParameter != null ); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ClosureExpressionsTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ClosureExpressionsTypingVisitor.java index 73331a549fb..4053ecc3467 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ClosureExpressionsTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ClosureExpressionsTypingVisitor.java @@ -111,7 +111,7 @@ public class ClosureExpressionsTypingVisitor extends ExpressionTypingVisitor { functionDescriptor.setReturnType(safeReturnType); JetType receiver = DescriptorUtils.getReceiverParameterType(functionDescriptor.getReceiverParameter()); - List valueParametersTypes = DescriptorUtils.getValueParametersTypes(functionDescriptor.getValueParameters()); + List valueParametersTypes = ExpressionTypingUtils.getValueParametersTypes(functionDescriptor.getValueParameters()); JetType resultType = KotlinBuiltIns.getInstance().getFunctionType( Annotations.EMPTY, receiver, valueParametersTypes, safeReturnType); if (!noExpectedType(expectedType) && KotlinBuiltIns.getInstance().isFunctionOrExtensionFunctionType(expectedType)) { @@ -187,7 +187,7 @@ public class ClosureExpressionsTypingVisitor extends ExpressionTypingVisitor { } else { if (expectedValueParameters != null && declaredValueParameters.size() != expectedValueParameters.size()) { - List expectedParameterTypes = DescriptorUtils.getValueParametersTypes(expectedValueParameters); + List expectedParameterTypes = ExpressionTypingUtils.getValueParametersTypes(expectedValueParameters); context.trace.report(EXPECTED_PARAMETERS_NUMBER_MISMATCH.on(functionLiteral, expectedParameterTypes.size(), expectedParameterTypes)); } for (int i = 0; i < declaredValueParameters.size(); i++) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java index e0ce8f2fcc5..df43995bb2e 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java @@ -370,7 +370,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { // http://youtrack.jetbrains.net/issue/KT-527 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); context.trace.report(Errors.NAME_SHADOWING.on(declaration, variableDescriptor.getName().asString())); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingServices.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingServices.java index e6885543fc2..9d53a508a8b 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingServices.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingServices.java @@ -395,7 +395,7 @@ public class ExpressionTypingServices { JetExpression defaultValue = jetParameter.getDefaultValue(); if (defaultValue != null) { 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()); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java index c56aee232cf..ee3202b6044 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java @@ -427,7 +427,7 @@ public class ExpressionTypingUtils { } 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); if (declaration != null) { 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) { return expression.getOperationReference().getReferencedNameElementType() == JetTokens.EXCLEXCL; } + + @NotNull + public static List getValueParametersTypes(@NotNull List valueParameters) { + List parameterTypes = new ArrayList(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; + } } diff --git a/compiler/tests/org/jetbrains/jet/codegen/TestlibTest.java b/compiler/tests/org/jetbrains/jet/codegen/TestlibTest.java index bbbbde9c4da..43d7f71df2b 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/TestlibTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/TestlibTest.java @@ -41,13 +41,15 @@ import org.jetbrains.jet.lang.psi.JetDeclaration; import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.resolve.BindingContext; 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.lang.reflect.Modifier; import java.net.URL; import java.net.URLClassLoader; +import static org.jetbrains.jet.lang.types.TypeUtils.getAllSupertypes; + @SuppressWarnings("JUnitTestCaseWithNoTests") public class TestlibTest extends UsefulTestCase { public static Test suite() { @@ -123,8 +125,8 @@ public class TestlibTest extends UsefulTestCase { BindingContext.DECLARATION_TO_DESCRIPTOR, declaration); - for (ClassDescriptor superClass : DescriptorUtils.getAllSuperClasses(descriptor)) { - if (!"junit/framework/Test".equals(typeMapper.mapClass(superClass).getInternalName())) continue; + for (JetType superType : getAllSupertypes(descriptor.getDefaultType())) { + if (!"junit/framework/Test".equals(typeMapper.mapType(superType).getInternalName())) continue; String name = typeMapper.mapClass(descriptor).getInternalName(); diff --git a/compiler/tests/org/jetbrains/jet/types/BoundsSubstitutorTest.java b/compiler/tests/org/jetbrains/jet/types/BoundsSubstitutorTest.java index 70e8ff0fd92..f348090e4f0 100644 --- a/compiler/tests/org/jetbrains/jet/types/BoundsSubstitutorTest.java +++ b/compiler/tests/org/jetbrains/jet/types/BoundsSubstitutorTest.java @@ -23,11 +23,11 @@ import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; import org.jetbrains.jet.lang.descriptors.ModuleDescriptor; import org.jetbrains.jet.lang.psi.JetFile; 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.LazyResolveTestUtil; import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.Name; +import org.jetbrains.jet.lang.types.BoundsSubstitutor; import org.jetbrains.jet.renderer.DescriptorRenderer; import java.util.Collection; @@ -76,7 +76,7 @@ public class BoundsSubstitutorTest extends KotlinTestWithEnvironment { assert functions.size() == 1 : "Many functions defined"; FunctionDescriptor function = ContainerUtil.getFirstItem(functions); - FunctionDescriptor substituted = DescriptorUtils.substituteBounds(function); + FunctionDescriptor substituted = BoundsSubstitutor.substituteBounds(function); String actual = DescriptorRenderer.COMPACT.render(substituted); assertEquals(expected, actual); } diff --git a/core/descriptors/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java b/core/descriptors/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java index fd07e32b8ca..b9c443231cb 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/resolve/DescriptorUtils.java @@ -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 substituteBounds(@NotNull D functionDescriptor) { - List 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 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 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 getValueParametersTypes(@NotNull List valueParameters) { - List 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 getAllSuperClasses(@NotNull ClassDescriptor klass) { - Set allSupertypes = TypeUtils.getAllSupertypes(klass.getDefaultType()); - Set 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; diff --git a/core/descriptors/src/org/jetbrains/jet/lang/types/DescriptorSubstitutor.java b/core/descriptors/src/org/jetbrains/jet/lang/types/DescriptorSubstitutor.java index 3615141469b..b6c3e9aa16f 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/types/DescriptorSubstitutor.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/types/DescriptorSubstitutor.java @@ -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 PROJECTIONS_TO_TYPES = new Function() { - @Override - public JetType apply(TypeProjection projection) { - return projection.getType(); - } - }; + private DescriptorSubstitutor() { + } @NotNull public static TypeSubstitutor substituteTypeParameters( @NotNull List typeParameters, @NotNull final TypeSubstitutor originalSubstitutor, @NotNull DeclarationDescriptor newContainingDeclaration, - @NotNull List result) { - final Map mutableSubstitution = Maps.newHashMap(); + @NotNull List result + ) { + final Map mutableSubstitution = new HashMap(); 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 substitutedMap = Maps.newHashMap(); + + Map substitutedMap = + new HashMap(); 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 typeParameters - ) { - Map 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 topologicallySortTypeParameters(final List 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 topOrder = DFS.topologicalOrder( - typeParameters, - new DFS.Neighbors() { - @NotNull - @Override - public Iterable 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 getTypeParametersFromUpperBounds( - TypeParameterDescriptor current, - final List typeParameters - ) { - return DFS.dfs( - current.getUpperBounds(), - new DFS.Neighbors() { - @NotNull - @Override - public Iterable getNeighbors(JetType current) { - return Collections2.transform(current.getArguments(), PROJECTIONS_TO_TYPES); - } - }, - new DFS.NodeHandlerWithListResult() { - @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; - } - } - ); - } } diff --git a/idea/src/org/jetbrains/jet/plugin/libraries/DecompiledNavigationUtils.java b/idea/src/org/jetbrains/jet/plugin/libraries/DecompiledNavigationUtils.java index 1d5023991d5..e5a8a3ffd9d 100644 --- a/idea/src/org/jetbrains/jet/plugin/libraries/DecompiledNavigationUtils.java +++ b/idea/src/org/jetbrains/jet/plugin/libraries/DecompiledNavigationUtils.java @@ -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.kotlin.VirtualFileFinder; 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.getFqNameSafe; @@ -113,7 +114,7 @@ public final class DecompiledNavigationUtils { } if (containerDescriptor instanceof ClassDescriptor) { if (containerDescriptor.getContainingDeclaration() instanceof ClassDescriptor - || DescriptorUtils.isLocal(containerDescriptor.getContainingDeclaration(), containerDescriptor)) { + || ExpressionTypingUtils.isLocal(containerDescriptor.getContainingDeclaration(), containerDescriptor)) { return getContainerFqName(containerDescriptor.getContainingDeclaration()); } return getFqNameSafe(containerDescriptor);