private void resolvePropertyInitializer( JetProperty property, PropertyDescriptor propertyDescriptor, JetExpression initializer, JetScope scope) { // JetFlowInformationProvider flowInformationProvider = // context.getDescriptorResolver().computeFlowData(property, initializer); // TODO : flow JET-15 JetType expectedTypeForInitializer = property.getPropertyTypeRef() != null ? propertyDescriptor.getType() : NO_EXPECTED_TYPE; JetType type = expressionTypingServices.getType( descriptorResolver.getPropertyDeclarationInnerScope( scope, propertyDescriptor, propertyDescriptor.getTypeParameters(), propertyDescriptor.getReceiverParameter(), trace), initializer, expectedTypeForInitializer, trace); // // JetType expectedType = propertyDescriptor.getInType(); // if (expectedType == null) { // expectedType = propertyDescriptor.getType(); // } // if (type != null && expectedType != null // && !context.getSemanticServices().getTypeChecker().isSubtypeOf(type, // expectedType)) { //// trace.report(TYPE_MISMATCH.on(initializer, expectedType, type)); // } }
private void checkPropertyGetter( @NotNull PropertyDescriptor descriptor, @NotNull JetExpression expression) { PropertyGetterDescriptor getter = descriptor.getGetter(); if (getter != null) { checkPropertyAccessor(getter, expression, descriptor.isVar()); } }
private void generateDefaultGetter(JetProperty p) { final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) state.getBindingContext().get(BindingContext.VARIABLE, p); int flags = JetTypeMapper.getAccessModifiers(propertyDescriptor, 0) | (propertyDescriptor.getModality() == Modality.ABSTRACT ? Opcodes.ACC_ABSTRACT : 0); generateDefaultGetter(propertyDescriptor, flags, p); }
private void generateDefaultSetter(JetProperty p) { final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) state.getBindingContext().get(BindingContext.VARIABLE, p); assert propertyDescriptor != null; int modifiers = JetTypeMapper.getAccessModifiers(propertyDescriptor, 0); PropertySetterDescriptor setter = propertyDescriptor.getSetter(); int flags = setter == null ? modifiers : JetTypeMapper.getAccessModifiers(setter, modifiers); generateDefaultSetter(propertyDescriptor, flags, p); }
private void resolvePropertyDeclarationBodies() { // Member properties Set<JetProperty> processed = Sets.newHashSet(); for (Map.Entry<JetClass, MutableClassDescriptor> entry : context.getClasses().entrySet()) { JetClass jetClass = entry.getKey(); if (!context.completeAnalysisNeeded(jetClass)) continue; MutableClassDescriptor classDescriptor = entry.getValue(); for (JetProperty property : jetClass.getProperties()) { final PropertyDescriptor propertyDescriptor = this.context.getProperties().get(property); assert propertyDescriptor != null; computeDeferredType(propertyDescriptor.getReturnType()); JetExpression initializer = property.getInitializer(); if (initializer != null) { ConstructorDescriptor primaryConstructor = classDescriptor.getUnsubstitutedPrimaryConstructor(); if (primaryConstructor != null) { JetScope declaringScopeForPropertyInitializer = this.context.getDeclaringScopes().get(property); resolvePropertyInitializer( property, propertyDescriptor, initializer, declaringScopeForPropertyInitializer); } } resolvePropertyAccessors(property, propertyDescriptor); processed.add(property); } } // Top-level properties & properties of objects for (Map.Entry<JetProperty, PropertyDescriptor> entry : this.context.getProperties().entrySet()) { JetProperty property = entry.getKey(); if (!context.completeAnalysisNeeded(property)) continue; if (processed.contains(property)) continue; final PropertyDescriptor propertyDescriptor = entry.getValue(); computeDeferredType(propertyDescriptor.getReturnType()); JetScope declaringScope = this.context.getDeclaringScopes().get(property); JetExpression initializer = property.getInitializer(); if (initializer != null) { resolvePropertyInitializer(property, propertyDescriptor, initializer, declaringScope); } resolvePropertyAccessors(property, propertyDescriptor); } }
private void checkPropertySetter( @NotNull PropertyDescriptor descriptor, @NotNull JetExpression expression) { PropertySetterDescriptor setter = descriptor.getSetter(); if (setter != null) { checkPropertyAccessor(setter, expression, true); } }
public void genDelegate( PropertyDescriptor declaration, PropertyDescriptor overriddenDescriptor, StackValue field) { JvmPropertyAccessorSignature jvmPropertyAccessorSignature = state .getInjector() .getJetTypeMapper() .mapGetterSignature(declaration, OwnerKind.IMPLEMENTATION); functionCodegen.genDelegate( declaration, overriddenDescriptor, field, jvmPropertyAccessorSignature.getJvmMethodSignature()); if (declaration.isVar()) { jvmPropertyAccessorSignature = state .getInjector() .getJetTypeMapper() .mapSetterSignature(declaration, OwnerKind.IMPLEMENTATION); functionCodegen.genDelegate( declaration, overriddenDescriptor, field, jvmPropertyAccessorSignature.getJvmMethodSignature()); } }
private void checkPropertyDescriptor( @NotNull JetExpression expression, @NotNull PropertyDescriptor propertyDescriptor) { // Deprecated for Property if (reportAnnotationIfNeeded(expression, propertyDescriptor, propertyDescriptor.isVar())) { return; } // Deprecated for Getter (val, var), Setter (var) if (!propertyDescriptor.isVar()) { checkPropertyGetter(propertyDescriptor, expression); } else { IElementType operation = null; JetBinaryExpression binaryExpression = PsiTreeUtil.getParentOfType(expression, JetBinaryExpression.class); if (binaryExpression != null) { JetExpression left = binaryExpression.getLeft(); if (left == expression) { operation = binaryExpression.getOperationToken(); } else { JetReferenceExpression[] jetReferenceExpressions = PsiTreeUtil.getChildrenOfType(left, JetReferenceExpression.class); if (jetReferenceExpressions != null) { for (JetReferenceExpression expr : jetReferenceExpressions) { if (expr == expression) { operation = binaryExpression.getOperationToken(); break; } } } } } else { JetUnaryExpression unaryExpression = PsiTreeUtil.getParentOfType(expression, JetUnaryExpression.class); if (unaryExpression != null) { operation = unaryExpression.getOperationReference().getReferencedNameElementType(); } } if (operation != null && PROPERTY_SET_OPERATIONS.contains(operation)) { checkPropertySetter(propertyDescriptor, expression); } else { checkPropertyGetter(propertyDescriptor, expression); } } }
private void resolvePropertyAccessors( JetProperty property, PropertyDescriptor propertyDescriptor) { ObservableBindingTrace fieldAccessTrackingTrace = createFieldTrackingTrace(propertyDescriptor); JetPropertyAccessor getter = property.getGetter(); PropertyGetterDescriptor getterDescriptor = propertyDescriptor.getGetter(); if (getter != null && getterDescriptor != null) { JetScope accessorScope = makeScopeForPropertyAccessor(getter, propertyDescriptor); resolveFunctionBody(fieldAccessTrackingTrace, getter, getterDescriptor, accessorScope); } JetPropertyAccessor setter = property.getSetter(); PropertySetterDescriptor setterDescriptor = propertyDescriptor.getSetter(); if (setter != null && setterDescriptor != null) { JetScope accessorScope = makeScopeForPropertyAccessor(setter, propertyDescriptor); resolveFunctionBody(fieldAccessTrackingTrace, setter, setterDescriptor, accessorScope); } }
private boolean shouldInitializeProperty(@NotNull JetProperty property) { JetExpression initializer = property.getDelegateExpressionOrInitializer(); if (initializer == null) return false; PropertyDescriptor propertyDescriptor = (PropertyDescriptor) bindingContext.get(VARIABLE, property); assert propertyDescriptor != null; CompileTimeConstant<?> compileTimeValue = propertyDescriptor.getCompileTimeInitializer(); if (compileTimeValue == null) return true; // TODO: OPTIMIZATION: don't initialize static final fields Object value = compileTimeValue.getValue(); JetType jetType = getPropertyOrDelegateType(property, propertyDescriptor); Type type = typeMapper.mapType(jetType); return !skipDefaultValue(propertyDescriptor, value, type); }
public void gen(JetProperty p) { final VariableDescriptor descriptor = state.getBindingContext().get(BindingContext.VARIABLE, p); if (!(descriptor instanceof PropertyDescriptor)) { throw new UnsupportedOperationException("expect a property to have a property descriptor"); } final PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor; if (kind == OwnerKind.NAMESPACE || kind == OwnerKind.IMPLEMENTATION || kind == OwnerKind.TRAIT_IMPL) { if (kind != OwnerKind.TRAIT_IMPL) generateBackingField(p, propertyDescriptor); generateGetter(p, propertyDescriptor); generateSetter(p, propertyDescriptor); } else if (kind instanceof OwnerKind.DelegateKind) { generateDefaultGetter(propertyDescriptor, Opcodes.ACC_PUBLIC, p); if (propertyDescriptor.isVar()) { generateDefaultSetter(propertyDescriptor, Opcodes.ACC_PUBLIC, p); } } }
@NotNull private JetType getPropertyOrDelegateType( @NotNull JetProperty property, @NotNull PropertyDescriptor descriptor) { JetExpression delegateExpression = property.getDelegateExpression(); if (delegateExpression != null) { JetType delegateType = bindingContext.get(BindingContext.EXPRESSION_TYPE, delegateExpression); assert delegateType != null : "Type of delegate expression should be recorded"; return delegateType; } return descriptor.getType(); }
private void generateSetter(JetProperty p, PropertyDescriptor propertyDescriptor) { final JetPropertyAccessor setter = p.getSetter(); if (setter != null) { if (setter.getBodyExpression() != null) { final PropertySetterDescriptor setterDescriptor = propertyDescriptor.getSetter(); assert setterDescriptor != null; JvmPropertyAccessorSignature signature = state.getInjector().getJetTypeMapper().mapSetterSignature(propertyDescriptor, kind); functionCodegen.generateMethod( setter, signature.getJvmMethodSignature(), true, signature.getPropertyTypeKotlinSignature(), setterDescriptor); } else if (isExternallyAccessible(propertyDescriptor)) { generateDefaultSetter(p); } } else if (isExternallyAccessible(propertyDescriptor) && propertyDescriptor.isVar()) { generateDefaultSetter(p); } }
private JetScope makeScopeForPropertyAccessor( @NotNull JetPropertyAccessor accessor, PropertyDescriptor propertyDescriptor) { JetScope declaringScope = context.getDeclaringScopes().get(accessor); JetScope propertyDeclarationInnerScope = descriptorResolver.getPropertyDeclarationInnerScope( declaringScope, propertyDescriptor, propertyDescriptor.getTypeParameters(), propertyDescriptor.getReceiverParameter(), trace); WritableScope accessorScope = new WritableScopeImpl( propertyDeclarationInnerScope, declaringScope.getContainingDeclaration(), new TraceBasedRedeclarationHandler(trace)) .setDebugName("Accessor scope"); accessorScope.changeLockLevel(WritableScope.LockLevel.READING); return accessorScope; }
private void generateBackingField(JetProperty p, PropertyDescriptor propertyDescriptor) { if (state.getBindingContext().get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor)) { DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration(); if (CodegenUtil.isInterface(containingDeclaration)) return; Object value = null; final JetExpression initializer = p.getInitializer(); if (initializer != null) { if (initializer instanceof JetConstantExpression) { CompileTimeConstant<?> compileTimeValue = state.getBindingContext().get(BindingContext.COMPILE_TIME_VALUE, initializer); value = compileTimeValue != null ? compileTimeValue.getValue() : null; } } int modifiers; if (kind == OwnerKind.NAMESPACE) { int access = JetTypeMapper.getAccessModifiers(propertyDescriptor, 0); modifiers = access | Opcodes.ACC_STATIC; } else { modifiers = JetTypeMapper.getAccessModifiers(propertyDescriptor, 0); } if (!propertyDescriptor.isVar()) { modifiers |= Opcodes.ACC_FINAL; } if (state.getInjector().getJetStandardLibrary().isVolatile(propertyDescriptor)) { modifiers |= Opcodes.ACC_VOLATILE; } Type type = state .getInjector() .getJetTypeMapper() .mapType(propertyDescriptor.getType(), MapTypeMode.VALUE); FieldVisitor fieldVisitor = v.newField(p, modifiers, p.getName(), type.getDescriptor(), null, value); AnnotationCodegen.forField(fieldVisitor, state.getInjector().getJetTypeMapper()) .genAnnotations(propertyDescriptor); } }
@Override public Boolean computeValue( SlicedMap map, PropertyDescriptor propertyDescriptor, Boolean backingFieldRequired, boolean valueNotFound) { if (propertyDescriptor.getKind() != CallableMemberDescriptor.Kind.DECLARATION) { return false; } backingFieldRequired = valueNotFound ? false : backingFieldRequired; assert backingFieldRequired != null; // TODO: user BindingContextAccessors PsiElement declarationPsiElement = map.get(BindingContextUtils.DESCRIPTOR_TO_DECLARATION, propertyDescriptor); if (declarationPsiElement instanceof JetParameter) { JetParameter jetParameter = (JetParameter) declarationPsiElement; return jetParameter.getValOrVarNode() != null || backingFieldRequired; // this part is unused because we do not allow access to // constructor parameters in member bodies } if (propertyDescriptor.getModality() == Modality.ABSTRACT) return false; PropertyGetterDescriptor getter = propertyDescriptor.getGetter(); PropertySetterDescriptor setter = propertyDescriptor.getSetter(); if (getter == null) { return true; } else if (propertyDescriptor.isVar() && setter == null) { return true; } else if (setter != null && !setter.hasBody() && setter.getModality() != Modality.ABSTRACT) { return true; } else if (!getter.hasBody() && getter.getModality() != Modality.ABSTRACT) { return true; } return backingFieldRequired; }
private void generateGetter(JetProperty p, PropertyDescriptor propertyDescriptor) { final JetPropertyAccessor getter = p.getGetter(); if (getter != null) { if (getter.getBodyExpression() != null) { JvmPropertyAccessorSignature signature = state.getInjector().getJetTypeMapper().mapGetterSignature(propertyDescriptor, kind); functionCodegen.generateMethod( getter, signature.getJvmMethodSignature(), true, signature.getPropertyTypeKotlinSignature(), propertyDescriptor.getGetter()); } else if (isExternallyAccessible(propertyDescriptor)) { generateDefaultGetter(p); } } else if (isExternallyAccessible(propertyDescriptor)) { generateDefaultGetter(p); } }
private static boolean skipDefaultValue( @NotNull PropertyDescriptor propertyDescriptor, Object value, @NotNull Type type) { if (isPrimitive(type)) { if (!propertyDescriptor.getType().isNullable() && value instanceof Number) { if (type == Type.INT_TYPE && ((Number) value).intValue() == 0) { return true; } if (type == Type.BYTE_TYPE && ((Number) value).byteValue() == 0) { return true; } if (type == Type.LONG_TYPE && ((Number) value).longValue() == 0L) { return true; } if (type == Type.SHORT_TYPE && ((Number) value).shortValue() == 0) { return true; } if (type == Type.DOUBLE_TYPE && ((Number) value).doubleValue() == 0d) { return true; } if (type == Type.FLOAT_TYPE && ((Number) value).floatValue() == 0f) { return true; } } if (type == Type.BOOLEAN_TYPE && value instanceof Boolean && !((Boolean) value)) { return true; } if (type == Type.CHAR_TYPE && value instanceof Character && ((Character) value) == 0) { return true; } } else { if (value == null) { return true; } } return false; }
private static boolean isExternallyAccessible(PropertyDescriptor p) { return p.getVisibility() != Visibilities.PRIVATE || CodegenUtil.isClassObject(p.getContainingDeclaration()); }
public void generateDefaultSetter( PropertyDescriptor propertyDescriptor, int flags, PsiElement origin) { if (propertyDescriptor.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) { throw new IllegalStateException("must not generate code for fake overrides"); } if (kind == OwnerKind.TRAIT_IMPL) { return; } if (kind == OwnerKind.NAMESPACE) { flags |= Opcodes.ACC_STATIC; } PsiElement psiElement = state .getBindingContext() .get( BindingContext.DESCRIPTOR_TO_DECLARATION, propertyDescriptor.getContainingDeclaration()); boolean isTrait = psiElement instanceof JetClass && ((JetClass) psiElement).isTrait(); if (isTrait && !(kind instanceof OwnerKind.DelegateKind)) flags |= Opcodes.ACC_ABSTRACT; if (propertyDescriptor.getModality() == Modality.FINAL) { flags |= Opcodes.ACC_FINAL; } JvmPropertyAccessorSignature signature = state.getInjector().getJetTypeMapper().mapSetterSignature(propertyDescriptor, kind); final String descriptor = signature.getJvmMethodSignature().getAsmMethod().getDescriptor(); MethodVisitor mv = v.newMethod( origin, flags, setterName(propertyDescriptor.getName()), descriptor, null, null); generateJetPropertyAnnotation( mv, signature.getPropertyTypeKotlinSignature(), signature.getJvmMethodSignature().getKotlinTypeParameter()); if (propertyDescriptor.getSetter() != null) { assert !propertyDescriptor.getSetter().hasBody(); AnnotationCodegen.forMethod(mv, state.getInjector().getJetTypeMapper()) .genAnnotations(propertyDescriptor.getSetter()); } if (v.generateCode() != ClassBuilder.Mode.SIGNATURES && (!isTrait || kind instanceof OwnerKind.DelegateKind)) { if (propertyDescriptor.getModality() != Modality.ABSTRACT) { mv.visitCode(); if (v.generateCode() == ClassBuilder.Mode.STUBS) { StubCodegen.generateStubThrow(mv); } else { InstructionAdapter iv = new InstructionAdapter(mv); final Type type = state .getInjector() .getJetTypeMapper() .mapType(propertyDescriptor.getType(), MapTypeMode.VALUE); int paramCode = 0; if (kind != OwnerKind.NAMESPACE) { iv.load(0, JetTypeMapper.TYPE_OBJECT); paramCode = 1; } if ((kind instanceof OwnerKind.DelegateKind) != (propertyDescriptor.getKind() == FunctionDescriptor.Kind.DELEGATION)) { throw new IllegalStateException("mismatching kind in " + propertyDescriptor); } if (kind instanceof OwnerKind.DelegateKind) { OwnerKind.DelegateKind dk = (OwnerKind.DelegateKind) kind; iv.load(0, JetTypeMapper.TYPE_OBJECT); dk.getDelegate().put(JetTypeMapper.TYPE_OBJECT, iv); iv.load(paramCode, type); iv.invokeinterface( dk.getOwnerClass(), setterName(propertyDescriptor.getName()), descriptor); } else { iv.load(paramCode, type); iv.visitFieldInsn( kind == OwnerKind.NAMESPACE ? Opcodes.PUTSTATIC : Opcodes.PUTFIELD, state.getInjector().getJetTypeMapper().getOwner(propertyDescriptor, kind), propertyDescriptor.getName(), type.getDescriptor()); } iv.visitInsn(Opcodes.RETURN); } } FunctionCodegen.endVisit(mv, "setter", origin); } }