private void checkAccessors( @NotNull JetProperty property, @NotNull PropertyDescriptor propertyDescriptor) { for (JetPropertyAccessor accessor : property.getAccessors()) { PropertyAccessorDescriptor propertyAccessorDescriptor = accessor.isGetter() ? propertyDescriptor.getGetter() : propertyDescriptor.getSetter(); assert propertyAccessorDescriptor != null : "No property accessor descriptor for " + property.getText(); modifiersChecker.checkModifiersForDeclaration(accessor, propertyAccessorDescriptor); modifiersChecker.reportIllegalModalityModifiers(accessor); } JetPropertyAccessor getter = property.getGetter(); PropertyGetterDescriptor getterDescriptor = propertyDescriptor.getGetter(); JetModifierList getterModifierList = getter != null ? getter.getModifierList() : null; if (getterModifierList != null && getterDescriptor != null) { Map<JetModifierKeywordToken, ASTNode> nodes = ModifiersChecker.getNodesCorrespondingToModifiers( getterModifierList, Sets.newHashSet( JetTokens.PUBLIC_KEYWORD, JetTokens.PROTECTED_KEYWORD, JetTokens.PRIVATE_KEYWORD, JetTokens.INTERNAL_KEYWORD)); if (getterDescriptor.getVisibility() != propertyDescriptor.getVisibility()) { for (ASTNode node : nodes.values()) { trace.report(Errors.GETTER_VISIBILITY_DIFFERS_FROM_PROPERTY_VISIBILITY.on(node.getPsi())); } } else { for (ASTNode node : nodes.values()) { trace.report(Errors.REDUNDANT_MODIFIER_IN_GETTER.on(node.getPsi())); } } } }
@NotNull private KotlinTypeChecker createTypeChecker( @NotNull List<TypeParameterDescriptor> firstParameters, @NotNull List<TypeParameterDescriptor> secondParameters) { assert firstParameters.size() == secondParameters.size() : "Should be the same number of type parameters: " + firstParameters + " vs " + secondParameters; if (firstParameters.isEmpty()) return KotlinTypeChecker.withAxioms(equalityAxioms); final Map<TypeConstructor, TypeConstructor> matchingTypeConstructors = new HashMap<TypeConstructor, TypeConstructor>(); for (int i = 0; i < firstParameters.size(); i++) { matchingTypeConstructors.put( firstParameters.get(i).getTypeConstructor(), secondParameters.get(i).getTypeConstructor()); } return KotlinTypeChecker.withAxioms( new KotlinTypeChecker.TypeConstructorEquality() { @Override public boolean equals(@NotNull TypeConstructor a, @NotNull TypeConstructor b) { if (equalityAxioms.equals(a, b)) return true; TypeConstructor img1 = matchingTypeConstructors.get(a); TypeConstructor img2 = matchingTypeConstructors.get(b); return (img1 != null && img1.equals(b)) || (img2 != null && img2.equals(a)); } }); }
private void makePrimitive(@NotNull PrimitiveType primitiveType) { KotlinType type = getBuiltInTypeByClassName(primitiveType.getTypeName().asString()); KotlinType arrayType = getBuiltInTypeByClassName(primitiveType.getArrayTypeName().asString()); primitiveTypeToArrayKotlinType.put(primitiveType, arrayType); primitiveKotlinTypeToKotlinArrayType.put(type, arrayType); kotlinArrayTypeToPrimitiveKotlinType.put(arrayType, type); }
private void makePrimitive(@NotNull PrimitiveType primitiveType) { JetType type = getBuiltInTypeByClassName(primitiveType.getTypeName().asString()); JetType arrayType = getBuiltInTypeByClassName(primitiveType.getArrayTypeName().asString()); primitiveTypeToNullableJetType.put(primitiveType, TypeUtils.makeNullable(type)); primitiveTypeToArrayJetType.put(primitiveType, arrayType); primitiveJetTypeToJetArrayType.put(type, arrayType); jetArrayTypeToPrimitiveJetType.put(arrayType, type); }
{ fqNameToPrimitiveType = new HashMap<FqNameUnsafe, PrimitiveType>(0); arrayClassFqNameToPrimitiveType = new HashMap<FqNameUnsafe, PrimitiveType>(0); for (PrimitiveType primitiveType : PrimitiveType.values()) { fqNameToPrimitiveType.put( fqNameUnsafe(primitiveType.getTypeName().asString()), primitiveType); arrayClassFqNameToPrimitiveType.put( fqNameUnsafe(primitiveType.getArrayTypeName().asString()), primitiveType); } }
@NotNull public Map<JetModifierKeywordToken, PsiElement> getTokensCorrespondingToModifiers( @NotNull JetModifierList modifierList, @NotNull Collection<JetModifierKeywordToken> possibleModifiers) { Map<JetModifierKeywordToken, PsiElement> tokens = Maps.newHashMap(); for (JetModifierKeywordToken modifier : possibleModifiers) { if (modifierList.hasModifier(modifier)) { tokens.put(modifier, modifierList.getModifier(modifier)); } } return tokens; }
private void putClosureParametersOnStack() { for (LambdaInfo next : expressionMap.values()) { activeLambda = next; codegen.pushClosureOnStack(next.getClassDescriptor(), true, this); } activeLambda = null; }
public void rememberClosure(JetExpression expression, Type type) { JetExpression lambda = JetPsiUtil.deparenthesize(expression); assert isInlinableParameterExpression(lambda) : "Couldn't find inline expression in " + expression.getText(); LambdaInfo info = new LambdaInfo(lambda, typeMapper); ParameterInfo closureInfo = invocationParamBuilder.addNextParameter(type, true, null); closureInfo.setLambda(info); expressionMap.put(closureInfo.getIndex(), info); }
@NotNull public KotlinType getArrayElementType(@NotNull KotlinType arrayType) { if (isArray(arrayType)) { if (arrayType.getArguments().size() != 1) { throw new IllegalStateException(); } return arrayType.getArguments().get(0).getType(); } KotlinType primitiveType = kotlinArrayTypeToPrimitiveKotlinType.get(TypeUtils.makeNotNullable(arrayType)); if (primitiveType == null) { throw new IllegalStateException("not array: " + arrayType); } return primitiveType; }
public void process(@NotNull BodiesResolveContext bodiesResolveContext) { for (JetFile file : bodiesResolveContext.getFiles()) { checkModifiersAndAnnotationsInPackageDirective(file); AnnotationTargetChecker.INSTANCE$.check(file, trace); } Map<JetClassOrObject, ClassDescriptorWithResolutionScopes> classes = bodiesResolveContext.getDeclaredClasses(); for (Map.Entry<JetClassOrObject, ClassDescriptorWithResolutionScopes> entry : classes.entrySet()) { JetClassOrObject classOrObject = entry.getKey(); ClassDescriptorWithResolutionScopes classDescriptor = entry.getValue(); checkSupertypesForConsistency(classDescriptor); checkTypesInClassHeader(classOrObject); if (classOrObject instanceof JetClass) { JetClass jetClass = (JetClass) classOrObject; checkClass(bodiesResolveContext, jetClass, classDescriptor); descriptorResolver.checkNamesInConstraints( jetClass, classDescriptor, classDescriptor.getScopeForClassHeaderResolution(), trace); } else if (classOrObject instanceof JetObjectDeclaration) { checkObject((JetObjectDeclaration) classOrObject, classDescriptor); } checkPrimaryConstructor(classOrObject, classDescriptor); modifiersChecker.checkModifiersForDeclaration(classOrObject, classDescriptor); } Map<JetNamedFunction, SimpleFunctionDescriptor> functions = bodiesResolveContext.getFunctions(); for (Map.Entry<JetNamedFunction, SimpleFunctionDescriptor> entry : functions.entrySet()) { JetNamedFunction function = entry.getKey(); SimpleFunctionDescriptor functionDescriptor = entry.getValue(); checkFunction(function, functionDescriptor); modifiersChecker.checkModifiersForDeclaration(function, functionDescriptor); } Map<JetProperty, PropertyDescriptor> properties = bodiesResolveContext.getProperties(); for (Map.Entry<JetProperty, PropertyDescriptor> entry : properties.entrySet()) { JetProperty property = entry.getKey(); PropertyDescriptor propertyDescriptor = entry.getValue(); checkProperty(property, propertyDescriptor); modifiersChecker.checkModifiersForDeclaration(property, propertyDescriptor); } for (Map.Entry<JetSecondaryConstructor, ConstructorDescriptor> entry : bodiesResolveContext.getSecondaryConstructors().entrySet()) { ConstructorDescriptor constructorDescriptor = entry.getValue(); JetSecondaryConstructor declaration = entry.getKey(); checkConstructorDeclaration(constructorDescriptor, declaration); } }
@NotNull public JetType getNullablePrimitiveJetType(@NotNull PrimitiveType primitiveType) { return primitiveTypeToNullableJetType.get(primitiveType); }
private void checkSupertypeList( @NotNull ClassDescriptor supertypeOwner, @NotNull Map<JetTypeReference, JetType> supertypes, @NotNull JetClassOrObject jetClass) { Set<TypeConstructor> allowedFinalSupertypes = getAllowedFinalSupertypes(supertypeOwner, jetClass); Set<TypeConstructor> typeConstructors = Sets.newHashSet(); boolean classAppeared = false; for (Map.Entry<JetTypeReference, JetType> entry : supertypes.entrySet()) { JetTypeReference typeReference = entry.getKey(); JetType supertype = entry.getValue(); boolean addSupertype = true; ClassDescriptor classDescriptor = TypeUtils.getClassDescriptor(supertype); if (classDescriptor != null) { if (ErrorUtils.isError(classDescriptor)) continue; if (classDescriptor.getKind() != ClassKind.INTERFACE) { if (supertypeOwner.getKind() == ClassKind.ENUM_CLASS) { trace.report(CLASS_IN_SUPERTYPE_FOR_ENUM.on(typeReference)); addSupertype = false; } else if (supertypeOwner.getKind() == ClassKind.INTERFACE && !classAppeared && !TypesPackage.isDynamic(supertype) /* avoid duplicate diagnostics */) { trace.report(TRAIT_WITH_SUPERCLASS.on(typeReference)); addSupertype = false; } if (classAppeared) { trace.report(MANY_CLASSES_IN_SUPERTYPE_LIST.on(typeReference)); } else { classAppeared = true; } } } else { trace.report(SUPERTYPE_NOT_A_CLASS_OR_TRAIT.on(typeReference)); } TypeConstructor constructor = supertype.getConstructor(); if (addSupertype && !typeConstructors.add(constructor)) { trace.report(SUPERTYPE_APPEARS_TWICE.on(typeReference)); } if (DescriptorUtils.isSingleton(classDescriptor)) { trace.report(SINGLETON_IN_SUPERTYPE.on(typeReference)); } else if (constructor.isFinal() && !allowedFinalSupertypes.contains(constructor)) { if (classDescriptor.getModality() == Modality.SEALED) { DeclarationDescriptor containingDescriptor = supertypeOwner.getContainingDeclaration(); while (containingDescriptor != null && containingDescriptor != classDescriptor) { containingDescriptor = containingDescriptor.getContainingDeclaration(); } if (containingDescriptor == null) { trace.report(SEALED_SUPERTYPE.on(typeReference)); } else { trace.report(SEALED_SUPERTYPE_IN_LOCAL_CLASS.on(typeReference)); } } else { trace.report(FINAL_SUPERTYPE.on(typeReference)); } } } }
@NotNull public KotlinType getPrimitiveArrayKotlinType(@NotNull PrimitiveType primitiveType) { return primitiveTypeToArrayKotlinType.get(primitiveType); }
/** @return {@code null} if not primitive */ @Nullable public KotlinType getPrimitiveArrayKotlinTypeByPrimitiveKotlinType( @NotNull KotlinType kotlinType) { return primitiveKotlinTypeToKotlinArrayType.get(kotlinType); }
@NotNull public JetType getPrimitiveArrayJetType(@NotNull PrimitiveType primitiveType) { return primitiveTypeToArrayJetType.get(primitiveType); }
/** @return <code>null</code> if not primitive */ @Nullable public JetType getPrimitiveArrayJetTypeByPrimitiveJetType(@NotNull JetType jetType) { return primitiveJetTypeToJetArrayType.get(jetType); }
private void generateClosuresBodies() { for (LambdaInfo info : expressionMap.values()) { info.setNode(generateLambdaBody(info)); } }
@NotNull private OverrideCompatibilityInfo isOverridableBy( @NotNull CallableDescriptor superDescriptor, @NotNull CallableDescriptor subDescriptor, boolean checkReturnType) { if (superDescriptor instanceof FunctionDescriptor) { if (!(subDescriptor instanceof FunctionDescriptor)) return OverrideCompatibilityInfo.memberKindMismatch(); } else if (superDescriptor instanceof PropertyDescriptor) { if (!(subDescriptor instanceof PropertyDescriptor)) return OverrideCompatibilityInfo.memberKindMismatch(); } else { throw new IllegalArgumentException( "This type of CallableDescriptor cannot be checked for overridability: " + superDescriptor); } // TODO: check outside of this method if (!superDescriptor.getName().equals(subDescriptor.getName())) { return OverrideCompatibilityInfo.nameMismatch(); } OverrideCompatibilityInfo receiverAndParameterResult = checkReceiverAndParameterCount(superDescriptor, subDescriptor); if (receiverAndParameterResult != null) { return receiverAndParameterResult; } List<JetType> superValueParameters = compiledValueParameters(superDescriptor); List<JetType> subValueParameters = compiledValueParameters(subDescriptor); List<TypeParameterDescriptor> superTypeParameters = superDescriptor.getTypeParameters(); List<TypeParameterDescriptor> subTypeParameters = subDescriptor.getTypeParameters(); if (superTypeParameters.size() != subTypeParameters.size()) { for (int i = 0; i < superValueParameters.size(); ++i) { JetType superValueParameterType = getUpperBound(superValueParameters.get(i)); JetType subValueParameterType = getUpperBound(subValueParameters.get(i)); // TODO: compare erasure if (!JetTypeChecker.DEFAULT.equalTypes(superValueParameterType, subValueParameterType)) { return OverrideCompatibilityInfo.typeParameterNumberMismatch(); } } return OverrideCompatibilityInfo.valueParameterTypeMismatch( null, null, OverrideCompatibilityInfo.Result.CONFLICT); } final Map<TypeConstructor, TypeConstructor> matchingTypeConstructors = new HashMap<TypeConstructor, TypeConstructor>(); for (int i = 0, typeParametersSize = superTypeParameters.size(); i < typeParametersSize; i++) { TypeParameterDescriptor superTypeParameter = superTypeParameters.get(i); TypeParameterDescriptor subTypeParameter = subTypeParameters.get(i); matchingTypeConstructors.put( superTypeParameter.getTypeConstructor(), subTypeParameter.getTypeConstructor()); } JetTypeChecker.TypeConstructorEquality localEqualityAxioms = new JetTypeChecker.TypeConstructorEquality() { @Override public boolean equals(@NotNull TypeConstructor a, @NotNull TypeConstructor b) { if (equalityAxioms.equals(a, b)) return true; TypeConstructor img1 = matchingTypeConstructors.get(a); TypeConstructor img2 = matchingTypeConstructors.get(b); if (!(img1 != null && img1.equals(b)) && !(img2 != null && img2.equals(a))) { return false; } return true; } }; for (int i = 0, typeParametersSize = superTypeParameters.size(); i < typeParametersSize; i++) { TypeParameterDescriptor superTypeParameter = superTypeParameters.get(i); TypeParameterDescriptor subTypeParameter = subTypeParameters.get(i); if (!areTypesEquivalent( superTypeParameter.getUpperBoundsAsType(), subTypeParameter.getUpperBoundsAsType(), localEqualityAxioms)) { return OverrideCompatibilityInfo.boundsMismatch(superTypeParameter, subTypeParameter); } } for (int i = 0, unsubstitutedValueParametersSize = superValueParameters.size(); i < unsubstitutedValueParametersSize; i++) { JetType superValueParameter = superValueParameters.get(i); JetType subValueParameter = subValueParameters.get(i); if (!areTypesEquivalent(superValueParameter, subValueParameter, localEqualityAxioms)) { return OverrideCompatibilityInfo.valueParameterTypeMismatch( superValueParameter, subValueParameter, INCOMPATIBLE); } } if (checkReturnType) { JetType superReturnType = superDescriptor.getReturnType(); JetType subReturnType = subDescriptor.getReturnType(); if (superReturnType != null && subReturnType != null) { boolean bothErrors = subReturnType.isError() && superReturnType.isError(); if (!bothErrors && !JetTypeChecker.withAxioms(localEqualityAxioms) .isSubtypeOf(subReturnType, superReturnType)) { return OverrideCompatibilityInfo.returnTypeMismatch(superReturnType, subReturnType); } } } for (ExternalOverridabilityCondition externalCondition : EXTERNAL_CONDITIONS) { if (!externalCondition.isOverridable(superDescriptor, subDescriptor)) { return OverrideCompatibilityInfo.externalConditionFailed(externalCondition.getClass()); } } return OverrideCompatibilityInfo.success(); }
public void generateAndInsertFinallyBlocks( @NotNull MethodNode intoNode, @NotNull List<MethodInliner.PointForExternalFinallyBlocks> insertPoints, int offsetForFinallyLocalVar) { if (!codegen.hasFinallyBlocks()) return; Map<AbstractInsnNode, MethodInliner.PointForExternalFinallyBlocks> extensionPoints = new HashMap<AbstractInsnNode, MethodInliner.PointForExternalFinallyBlocks>(); for (MethodInliner.PointForExternalFinallyBlocks insertPoint : insertPoints) { extensionPoints.put(insertPoint.beforeIns, insertPoint); } DefaultProcessor processor = new DefaultProcessor(intoNode, offsetForFinallyLocalVar); int curFinallyDepth = 0; AbstractInsnNode curInstr = intoNode.instructions.getFirst(); while (curInstr != null) { processor.processInstruction(curInstr, true); if (InlineCodegenUtil.isFinallyStart(curInstr)) { // TODO depth index calc could be more precise curFinallyDepth = getConstant(curInstr.getPrevious()); } MethodInliner.PointForExternalFinallyBlocks extension = extensionPoints.get(curInstr); if (extension != null) { Label start = new Label(); MethodNode finallyNode = InlineCodegenUtil.createEmptyMethodNode(); finallyNode.visitLabel(start); ExpressionCodegen finallyCodegen = new ExpressionCodegen( finallyNode, codegen.getFrameMap(), codegen.getReturnType(), codegen.getContext(), codegen.getState(), codegen.getParentCodegen()); finallyCodegen.addBlockStackElementsForNonLocalReturns( codegen.getBlockStackElements(), curFinallyDepth); FrameMap frameMap = finallyCodegen.getFrameMap(); FrameMap.Mark mark = frameMap.mark(); while (frameMap.getCurrentSize() < processor.getNextFreeLocalIndex()) { frameMap.enterTemp(Type.INT_TYPE); } finallyCodegen.generateFinallyBlocksIfNeeded( extension.returnType, extension.finallyIntervalEnd.getLabel()); // Exception table for external try/catch/finally blocks will be generated in original // codegen after exiting this method InlineCodegenUtil.insertNodeBefore(finallyNode, intoNode, curInstr); SimpleInterval splitBy = new SimpleInterval((LabelNode) start.info, extension.finallyIntervalEnd); processor.getTryBlocksMetaInfo().splitCurrentIntervals(splitBy, true); // processor.getLocalVarsMetaInfo().splitAndRemoveIntervalsFromCurrents(splitBy); mark.dropTo(); } curInstr = curInstr.getNext(); } processor.substituteTryBlockNodes(intoNode); // processor.substituteLocalVarTable(intoNode); }