예제 #1
0
 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());
   }
 }
예제 #3
0
 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);
 }
예제 #4
0
  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);
  }
예제 #5
0
  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);
   }
 }
예제 #7
0
  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);
      }
    }
  }
예제 #9
0
  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);
    }
  }
예제 #10
0
  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);
  }
예제 #11
0
 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);
     }
   }
 }
예제 #12
0
 @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();
 }
예제 #13
0
 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);
   }
 }
예제 #14
0
  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;
  }
예제 #15
0
  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);
    }
  }
예제 #16
0
 @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;
 }
예제 #17
0
 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);
   }
 }
예제 #18
0
 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;
 }
예제 #19
0
 private static boolean isExternallyAccessible(PropertyDescriptor p) {
   return p.getVisibility() != Visibilities.PRIVATE
       || CodegenUtil.isClassObject(p.getContainingDeclaration());
 }
예제 #20
0
  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);
    }
  }