@NotNull private static Multimap<FqName, Pair<FunctionDescriptor, PsiMethod>> getSuperclassToFunctionsMultimap( @NotNull PsiMethodWrapper method, @NotNull BindingContext bindingContext, @NotNull ClassDescriptor containingClass) { Multimap<FqName, Pair<FunctionDescriptor, PsiMethod>> result = HashMultimap.create(); Name functionName = Name.identifier(method.getName()); int parameterCount = method.getParameters().size(); for (JetType supertype : TypeUtils.getAllSupertypes(containingClass.getDefaultType())) { ClassifierDescriptor klass = supertype.getConstructor().getDeclarationDescriptor(); assert klass != null; FqName fqName = DescriptorUtils.getFQName(klass).toSafe(); for (FunctionDescriptor fun : klass.getDefaultType().getMemberScope().getFunctions(functionName)) { if (fun.getKind().isReal() && fun.getValueParameters().size() == parameterCount) { PsiElement declaration = BindingContextUtils.descriptorToDeclaration(bindingContext, fun); if (declaration instanceof PsiMethod) { result.put(fqName, Pair.create(fun, (PsiMethod) declaration)); } // else declaration is null or JetNamedFunction: both cases are processed later } } } return result; }
@Nullable private static InsertHandler<LookupElement> getInsertHandler( @NotNull DeclarationDescriptor descriptor) { if (descriptor instanceof FunctionDescriptor) { FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor; if (functionDescriptor.getValueParameters().isEmpty()) { return EMPTY_FUNCTION_HANDLER; } if (functionDescriptor.getValueParameters().size() == 1 && KotlinBuiltIns.getInstance() .isFunctionOrExtensionFunctionType( functionDescriptor.getValueParameters().get(0).getType())) { return PARAMS_BRACES_FUNCTION_HANDLER; } return PARAMS_PARENTHESIS_FUNCTION_HANDLER; } if (descriptor instanceof ClassDescriptor) { return JetClassInsertHandler.INSTANCE; } return null; }
@NotNull private VarargCheckResult checkVarargInSuperFunctions( @NotNull ValueParameterDescriptor originalParam) { boolean someSupersVararg = false; boolean someSupersNotVararg = false; for (FunctionDescriptor superFunction : superFunctions) { if (superFunction.getValueParameters().get(originalParam.getIndex()).getVarargElementType() != null) { someSupersVararg = true; } else { someSupersNotVararg = true; } } JetType originalVarargElementType = originalParam.getVarargElementType(); JetType originalType = originalParam.getType(); if (someSupersVararg && someSupersNotVararg) { reportError("Incompatible super methods: some have vararg parameter, some have not"); return new VarargCheckResult(originalType, originalVarargElementType != null); } KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance(); if (someSupersVararg && originalVarargElementType == null) { // convert to vararg assert isArrayType(originalType); if (builtIns.isPrimitiveArray(originalType)) { // replace IntArray? with IntArray return new VarargCheckResult(TypeUtils.makeNotNullable(originalType), true); } // replace Array<out Foo>? with Array<Foo> JetType varargElementType = builtIns.getArrayElementType(originalType); return new VarargCheckResult(builtIns.getArrayType(INVARIANT, varargElementType), true); } else if (someSupersNotVararg && originalVarargElementType != null) { // convert to non-vararg assert isArrayType(originalType); if (builtIns.isPrimitiveArray(originalType)) { // replace IntArray with IntArray? return new VarargCheckResult(TypeUtils.makeNullable(originalType), false); } // replace Array<Foo> with Array<out Foo>? return new VarargCheckResult( TypeUtils.makeNullable( builtIns.getArrayType(Variance.OUT_VARIANCE, originalVarargElementType)), false); } return new VarargCheckResult(originalType, originalVarargElementType != null); }
@NotNull private static FunctionDescriptor substituteSuperFunction( @NotNull Map<ClassDescriptor, JetType> superclassToSupertype, @NotNull FunctionDescriptor superFun) { DeclarationDescriptor superFunContainer = superFun.getContainingDeclaration(); assert superFunContainer instanceof ClassDescriptor : superFunContainer; JetType supertype = superclassToSupertype.get(superFunContainer); assert supertype != null : "Couldn't find super type for super function: " + superFun; TypeSubstitutor supertypeSubstitutor = TypeSubstitutor.create(supertype); FunctionDescriptor substitutedSuperFun = superFun.substitute(supertypeSubstitutor); assert substitutedSuperFun != null; return substitutedSuperFun; }
private List<TypeParameterDescriptor> modifyTypeParametersAccordingToSuperMethods( List<TypeParameterDescriptor> autoTypeParameters) { List<TypeParameterDescriptor> result = Lists.newArrayList(); for (TypeParameterDescriptor autoParameter : autoTypeParameters) { int index = autoParameter.getIndex(); TypeParameterDescriptorImpl modifiedTypeParameter = autoTypeParameterToModified.get(autoParameter); List<Iterator<JetType>> upperBoundFromSuperFunctionsIterators = Lists.newArrayList(); for (FunctionDescriptor superFunction : superFunctions) { upperBoundFromSuperFunctionsIterators.add( superFunction.getTypeParameters().get(index).getUpperBounds().iterator()); } for (JetType autoUpperBound : autoParameter.getUpperBounds()) { List<TypeAndVariance> upperBoundsFromSuperFunctions = Lists.newArrayList(); for (Iterator<JetType> iterator : upperBoundFromSuperFunctionsIterators) { assert iterator.hasNext(); upperBoundsFromSuperFunctions.add(new TypeAndVariance(iterator.next(), INVARIANT)); } JetType modifiedUpperBound = modifyTypeAccordingToSuperMethods( autoUpperBound, upperBoundsFromSuperFunctions, UPPER_BOUND); modifiedTypeParameter.addUpperBound(modifiedUpperBound); } for (Iterator<JetType> iterator : upperBoundFromSuperFunctionsIterators) { assert !iterator.hasNext(); } modifiedTypeParameter.setInitialized(); result.add(modifiedTypeParameter); } return result; }
public static Map<String, DeclarationDescriptor> prepareDefaultNameToDescriptors( Project project, KotlinCoreEnvironment environment) { KotlinBuiltIns builtIns = JvmPlatform.INSTANCE.getBuiltIns(); Map<String, DeclarationDescriptor> nameToDescriptor = new HashMap<String, DeclarationDescriptor>(); nameToDescriptor.put( "kotlin::Int.plus(Int)", standardFunction(builtIns.getInt(), "plus", project, builtIns.getIntType())); FunctionDescriptor descriptorForGet = standardFunction(builtIns.getArray(), "get", project, builtIns.getIntType()); nameToDescriptor.put("kotlin::Array.get(Int)", descriptorForGet.getOriginal()); nameToDescriptor.put( "kotlin::Int.compareTo(Double)", standardFunction(builtIns.getInt(), "compareTo", project, builtIns.getDoubleType())); @NotNull FunctionDescriptor descriptorForSet = standardFunction( builtIns.getArray(), "set", project, builtIns.getIntType(), builtIns.getIntType()); nameToDescriptor.put("kotlin::Array.set(Int, Int)", descriptorForSet.getOriginal()); return nameToDescriptor; }
@NotNull public static LookupElement createLookupElement( @NotNull KotlinCodeAnalyzer analyzer, @NotNull DeclarationDescriptor descriptor, @Nullable PsiElement declaration) { if (declaration != null) { MutableLookupElement javaLookupElement = createJavaLookupElementIfPossible(declaration); if (javaLookupElement != null) { InsertHandler<LookupElement> customHandler = getInsertHandler(descriptor); if (customHandler != null) { return javaLookupElement.setInsertHandler(getInsertHandler(descriptor)); } else { return javaLookupElement; } } } LookupElementBuilder element = LookupElementBuilder.create( new JetLookupObject(descriptor, analyzer, declaration), descriptor.getName().getName()); String presentableText = descriptor.getName().getName(); String typeText = ""; String tailText = ""; boolean tailTextGrayed = true; if (descriptor instanceof FunctionDescriptor) { FunctionDescriptor functionDescriptor = (FunctionDescriptor) descriptor; JetType returnType = functionDescriptor.getReturnType(); typeText = DescriptorRenderer.TEXT.renderType(returnType); presentableText += DescriptorRenderer.TEXT.renderFunctionParameters(functionDescriptor); boolean extensionFunction = functionDescriptor.getReceiverParameter() != null; DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration(); if (containingDeclaration != null && extensionFunction) { tailText += " for " + DescriptorRenderer.TEXT.renderType( functionDescriptor.getReceiverParameter().getType()); tailText += " in " + DescriptorUtils.getFQName(containingDeclaration); } } else if (descriptor instanceof VariableDescriptor) { JetType outType = ((VariableDescriptor) descriptor).getType(); typeText = DescriptorRenderer.TEXT.renderType(outType); } else if (descriptor instanceof ClassDescriptor) { DeclarationDescriptor declaredIn = descriptor.getContainingDeclaration(); assert declaredIn != null; tailText = " (" + DescriptorUtils.getFQName(declaredIn) + ")"; tailTextGrayed = true; } else { typeText = DescriptorRenderer.TEXT.render(descriptor); } element = element.withInsertHandler(getInsertHandler(descriptor)); element = element .withTailText(tailText, tailTextGrayed) .withTypeText(typeText) .withPresentableText(presentableText); element = element.withIcon( JetDescriptorIconProvider.getIcon(descriptor, Iconable.ICON_FLAG_VISIBILITY)); element = element.withStrikeoutness(KotlinBuiltIns.getInstance().isDeprecated(descriptor)); return element; }