예제 #1
0
 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()));
       }
     }
   }
 }
예제 #2
0
  public void resolvePropertyAccessors(
      @NotNull BodiesResolveContext c,
      @NotNull JetProperty property,
      @NotNull PropertyDescriptor propertyDescriptor) {
    ObservableBindingTrace fieldAccessTrackingTrace = createFieldTrackingTrace(propertyDescriptor);

    JetPropertyAccessor getter = property.getGetter();
    PropertyGetterDescriptor getterDescriptor = propertyDescriptor.getGetter();
    if (getter != null && getterDescriptor != null) {
      LexicalScope accessorScope = makeScopeForPropertyAccessor(c, getter, propertyDescriptor);
      ForceResolveUtil.forceResolveAllContents(getterDescriptor.getAnnotations());
      resolveFunctionBody(
          c.getOuterDataFlowInfo(),
          fieldAccessTrackingTrace,
          getter,
          getterDescriptor,
          accessorScope);
    }

    JetPropertyAccessor setter = property.getSetter();
    PropertySetterDescriptor setterDescriptor = propertyDescriptor.getSetter();
    if (setter != null && setterDescriptor != null) {
      LexicalScope accessorScope = makeScopeForPropertyAccessor(c, setter, propertyDescriptor);
      ForceResolveUtil.forceResolveAllContents(setterDescriptor.getAnnotations());
      resolveFunctionBody(
          c.getOuterDataFlowInfo(),
          fieldAccessTrackingTrace,
          setter,
          setterDescriptor,
          accessorScope);
    }
  }
예제 #3
0
  private void resolveProperty(
      @NotNull BodiesResolveContext c,
      @Nullable LexicalScope parentScope,
      @NotNull JetProperty property,
      @NotNull PropertyDescriptor propertyDescriptor) {
    computeDeferredType(propertyDescriptor.getReturnType());

    JetExpression initializer = property.getInitializer();
    LexicalScope propertyScope = getScopeForProperty(c, property);
    if (parentScope == null) {
      parentScope = propertyScope;
    }
    if (initializer != null) {
      resolvePropertyInitializer(
          c.getOuterDataFlowInfo(), property, propertyDescriptor, initializer, propertyScope);
    }

    JetExpression delegateExpression = property.getDelegateExpression();
    if (delegateExpression != null) {
      assert initializer == null
          : "Initializer should be null for delegated property : " + property.getText();
      resolvePropertyDelegate(
          c.getOuterDataFlowInfo(),
          property,
          propertyDescriptor,
          delegateExpression,
          parentScope,
          propertyScope);
    }

    resolvePropertyAccessors(c, property, propertyDescriptor);
  }
  private static void forceResolvePackageDeclarations(
      @NotNull Collection<JetFile> files, @NotNull KotlinCodeAnalyzer session) {
    for (JetFile file : files) {
      // SCRIPT: not supported
      if (file.isScript()) continue;

      FqName packageFqName = file.getPackageFqName();

      // make sure we create a package descriptor
      PackageViewDescriptor packageDescriptor =
          session.getModuleDescriptor().getPackage(packageFqName);
      if (packageDescriptor.isEmpty()) {
        LOG.warn(
            "No descriptor found for package "
                + packageFqName
                + " in file "
                + file.getName()
                + "\n"
                + file.getText());
        session.forceResolveAll();
        continue;
      }

      for (JetDeclaration declaration : file.getDeclarations()) {
        if (declaration instanceof JetFunction) {
          JetFunction jetFunction = (JetFunction) declaration;
          Name name = jetFunction.getNameAsSafeName();
          Collection<FunctionDescriptor> functions =
              packageDescriptor.getMemberScope().getFunctions(name, LookupLocation.NO_LOCATION);
          for (FunctionDescriptor descriptor : functions) {
            ForceResolveUtil.forceResolveAllContents(descriptor);
          }
        } else if (declaration instanceof JetProperty) {
          JetProperty jetProperty = (JetProperty) declaration;
          Name name = jetProperty.getNameAsSafeName();
          Collection<VariableDescriptor> properties =
              packageDescriptor.getMemberScope().getProperties(name, LookupLocation.NO_LOCATION);
          for (VariableDescriptor descriptor : properties) {
            ForceResolveUtil.forceResolveAllContents(descriptor);
          }
        } else if (declaration instanceof JetClassOrObject) {
          // Do nothing: we are not interested in classes
        } else {
          LOG.error(
              "Unsupported declaration kind: "
                  + declaration
                  + " in file "
                  + file.getName()
                  + "\n"
                  + file.getText());
        }
      }
    }
  }
예제 #5
0
 @NotNull
 private static LexicalScope getScopeForProperty(
     @NotNull BodiesResolveContext c, @NotNull JetProperty property) {
   LexicalScope scope = c.getDeclaringScope(property);
   assert scope != null : "Scope for property " + property.getText() + " should exists";
   return scope;
 }
예제 #6
0
  public void resolvePropertyDelegate(
      @NotNull DataFlowInfo outerDataFlowInfo,
      @NotNull JetProperty jetProperty,
      @NotNull PropertyDescriptor propertyDescriptor,
      @NotNull JetExpression delegateExpression,
      @NotNull LexicalScope parentScopeForAccessor,
      @NotNull LexicalScope propertyScope) {
    JetPropertyAccessor getter = jetProperty.getGetter();
    if (getter != null && getter.hasBody()) {
      trace.report(ACCESSOR_FOR_DELEGATED_PROPERTY.on(getter));
    }

    JetPropertyAccessor setter = jetProperty.getSetter();
    if (setter != null && setter.hasBody()) {
      trace.report(ACCESSOR_FOR_DELEGATED_PROPERTY.on(setter));
    }

    LexicalScope propertyDeclarationInnerScope =
        JetScopeUtils.getPropertyDeclarationInnerScopeForInitializer(
            propertyDescriptor, propertyScope, propertyDescriptor.getTypeParameters(), null, trace);
    LexicalScope accessorScope =
        JetScopeUtils.makeScopeForPropertyAccessor(
            propertyDescriptor, parentScopeForAccessor, trace);

    JetType delegateType =
        delegatedPropertyResolver.resolveDelegateExpression(
            delegateExpression,
            jetProperty,
            propertyDescriptor,
            propertyDeclarationInnerScope,
            accessorScope,
            trace,
            outerDataFlowInfo);

    delegatedPropertyResolver.resolveDelegatedPropertyGetMethod(
        propertyDescriptor, delegateExpression, delegateType, trace, accessorScope);

    if (jetProperty.isVar()) {
      delegatedPropertyResolver.resolveDelegatedPropertySetMethod(
          propertyDescriptor, delegateExpression, delegateType, trace, accessorScope);
    }

    delegatedPropertyResolver.resolveDelegatedPropertyPDMethod(
        propertyDescriptor, delegateExpression, delegateType, trace, accessorScope);
  }
예제 #7
0
 public void resolvePropertyInitializer(
     @NotNull DataFlowInfo outerDataFlowInfo,
     @NotNull JetProperty property,
     @NotNull PropertyDescriptor propertyDescriptor,
     @NotNull JetExpression initializer,
     @NotNull LexicalScope scope) {
   LexicalScope propertyDeclarationInnerScope =
       JetScopeUtils.getPropertyDeclarationInnerScopeForInitializer(
           propertyDescriptor, scope, propertyDescriptor.getTypeParameters(), null, trace);
   JetType expectedTypeForInitializer =
       property.getTypeReference() != null ? propertyDescriptor.getType() : NO_EXPECTED_TYPE;
   if (propertyDescriptor.getCompileTimeInitializer() == null) {
     expressionTypingServices.getType(
         propertyDeclarationInnerScope,
         initializer,
         expectedTypeForInitializer,
         outerDataFlowInfo,
         trace);
   }
 }
예제 #8
0
  private void checkPropertyAbstractness(
      @NotNull JetProperty property,
      @NotNull PropertyDescriptor propertyDescriptor,
      @NotNull ClassDescriptor classDescriptor) {
    JetPropertyAccessor getter = property.getGetter();
    JetPropertyAccessor setter = property.getSetter();
    JetModifierList modifierList = property.getModifierList();
    ASTNode abstractNode =
        modifierList != null ? modifierList.getModifierNode(JetTokens.ABSTRACT_KEYWORD) : null;

    if (abstractNode != null) { // has abstract modifier
      if (!classCanHaveAbstractMembers(classDescriptor)) {
        String name = property.getName();
        trace.report(
            ABSTRACT_PROPERTY_IN_NON_ABSTRACT_CLASS.on(
                property, name != null ? name : "", classDescriptor));
        return;
      }
      if (classDescriptor.getKind() == ClassKind.INTERFACE) {
        trace.report(ABSTRACT_MODIFIER_IN_TRAIT.on(property));
      }
    }

    if (propertyDescriptor.getModality() == Modality.ABSTRACT) {
      JetExpression initializer = property.getInitializer();
      if (initializer != null) {
        trace.report(ABSTRACT_PROPERTY_WITH_INITIALIZER.on(initializer));
      }
      JetPropertyDelegate delegate = property.getDelegate();
      if (delegate != null) {
        trace.report(ABSTRACT_DELEGATED_PROPERTY.on(delegate));
      }
      if (getter != null && getter.hasBody()) {
        trace.report(ABSTRACT_PROPERTY_WITH_GETTER.on(getter));
      }
      if (setter != null && setter.hasBody()) {
        trace.report(ABSTRACT_PROPERTY_WITH_SETTER.on(setter));
      }
    }
  }
예제 #9
0
  private void checkPropertyInitializer(
      @NotNull JetProperty property, @NotNull PropertyDescriptor propertyDescriptor) {
    JetPropertyAccessor getter = property.getGetter();
    JetPropertyAccessor setter = property.getSetter();
    boolean hasAccessorImplementation =
        (getter != null && getter.hasBody()) || (setter != null && setter.hasBody());

    if (propertyDescriptor.getModality() == Modality.ABSTRACT) {
      if (!property.hasDelegateExpressionOrInitializer() && property.getTypeReference() == null) {
        trace.report(PROPERTY_WITH_NO_TYPE_NO_INITIALIZER.on(property));
      }
      return;
    }
    DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration();
    boolean inTrait =
        containingDeclaration instanceof ClassDescriptor
            && ((ClassDescriptor) containingDeclaration).getKind() == ClassKind.INTERFACE;
    JetExpression initializer = property.getInitializer();
    JetPropertyDelegate delegate = property.getDelegate();
    boolean backingFieldRequired =
        Boolean.TRUE.equals(
            trace
                .getBindingContext()
                .get(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor));

    if (inTrait && backingFieldRequired && hasAccessorImplementation) {
      trace.report(BACKING_FIELD_IN_TRAIT.on(property));
    }

    if (initializer == null && delegate == null) {
      boolean error = false;
      if (backingFieldRequired
          && !inTrait
          && Boolean.TRUE.equals(
              trace.getBindingContext().get(BindingContext.IS_UNINITIALIZED, propertyDescriptor))) {
        if (!(containingDeclaration instanceof ClassDescriptor) || hasAccessorImplementation) {
          error = true;
          trace.report(MUST_BE_INITIALIZED.on(property));
        } else {
          error = true;
          trace.report(MUST_BE_INITIALIZED_OR_BE_ABSTRACT.on(property));
        }
      }
      if (!error && property.getTypeReference() == null) {
        trace.report(PROPERTY_WITH_NO_TYPE_NO_INITIALIZER.on(property));
      }
      if (inTrait && property.hasModifier(JetTokens.FINAL_KEYWORD) && backingFieldRequired) {
        trace.report(FINAL_PROPERTY_IN_TRAIT.on(property));
      }
      return;
    }

    if (inTrait) {
      if (delegate != null) {
        trace.report(DELEGATED_PROPERTY_IN_TRAIT.on(delegate));
      } else {
        trace.report(PROPERTY_INITIALIZER_IN_TRAIT.on(initializer));
      }
    } else if (delegate == null) {
      if (!backingFieldRequired) {
        trace.report(PROPERTY_INITIALIZER_NO_BACKING_FIELD.on(initializer));
      } else if (property.getReceiverTypeReference() != null) {
        trace.report(EXTENSION_PROPERTY_WITH_BACKING_FIELD.on(initializer));
      }
    }
  }
  @NotNull
  @Override
  protected List<IntentionAction> doCreateActions(@NotNull Diagnostic diagnostic) {
    List<IntentionAction> actions = new LinkedList<IntentionAction>();

    BindingContext context = ResolutionUtils.analyzeFully((JetFile) diagnostic.getPsiFile());

    PsiElement diagnosticElement = diagnostic.getPsiElement();
    if (!(diagnosticElement instanceof JetExpression)) {
      LOG.error("Unexpected element: " + diagnosticElement.getText());
      return Collections.emptyList();
    }

    JetExpression expression = (JetExpression) diagnosticElement;

    JetType expectedType;
    JetType expressionType;
    if (diagnostic.getFactory() == Errors.TYPE_MISMATCH) {
      DiagnosticWithParameters2<JetExpression, JetType, JetType> diagnosticWithParameters =
          Errors.TYPE_MISMATCH.cast(diagnostic);
      expectedType = diagnosticWithParameters.getA();
      expressionType = diagnosticWithParameters.getB();
    } else if (diagnostic.getFactory() == Errors.NULL_FOR_NONNULL_TYPE) {
      DiagnosticWithParameters1<JetConstantExpression, JetType> diagnosticWithParameters =
          Errors.NULL_FOR_NONNULL_TYPE.cast(diagnostic);
      expectedType = diagnosticWithParameters.getA();
      expressionType = TypeUtilsKt.makeNullable(expectedType);
    } else if (diagnostic.getFactory() == Errors.CONSTANT_EXPECTED_TYPE_MISMATCH) {
      DiagnosticWithParameters2<JetConstantExpression, String, JetType> diagnosticWithParameters =
          Errors.CONSTANT_EXPECTED_TYPE_MISMATCH.cast(diagnostic);
      expectedType = diagnosticWithParameters.getB();
      expressionType = context.getType(expression);
      if (expressionType == null) {
        LOG.error("No type inferred: " + expression.getText());
        return Collections.emptyList();
      }
    } else {
      LOG.error("Unexpected diagnostic: " + DefaultErrorMessages.render(diagnostic));
      return Collections.emptyList();
    }

    // We don't want to cast a cast or type-asserted expression:
    if (!(expression instanceof JetBinaryExpressionWithTypeRHS)
        && !(expression.getParent() instanceof JetBinaryExpressionWithTypeRHS)) {
      actions.add(new CastExpressionFix(expression, expectedType));
    }

    // Property initializer type mismatch property type:
    JetProperty property = PsiTreeUtil.getParentOfType(expression, JetProperty.class);
    if (property != null) {
      JetPropertyAccessor getter = property.getGetter();
      JetExpression initializer = property.getInitializer();
      if (QuickFixUtil.canEvaluateTo(initializer, expression)
          || (getter != null
              && QuickFixUtil.canFunctionOrGetterReturnExpression(
                  property.getGetter(), expression))) {
        LexicalScope scope =
            CorePackage.getResolutionScope(
                property, context, ResolutionUtils.getResolutionFacade(property));
        JetType typeToInsert =
            TypeUtils.approximateWithResolvableType(expressionType, scope, false);
        actions.add(new ChangeVariableTypeFix(property, typeToInsert));
      }
    }

    PsiElement expressionParent = expression.getParent();

    // Mismatch in returned expression:

    JetCallableDeclaration function =
        expressionParent instanceof JetReturnExpression
            ? BindingContextUtilPackage.getTargetFunction(
                (JetReturnExpression) expressionParent, context)
            : PsiTreeUtil.getParentOfType(expression, JetFunction.class, true);
    if (function instanceof JetFunction
        && QuickFixUtil.canFunctionOrGetterReturnExpression(function, expression)) {
      LexicalScope scope =
          CorePackage.getResolutionScope(
              function, context, ResolutionUtils.getResolutionFacade(function));
      JetType typeToInsert = TypeUtils.approximateWithResolvableType(expressionType, scope, false);
      actions.add(new ChangeFunctionReturnTypeFix((JetFunction) function, typeToInsert));
    }

    // Fixing overloaded operators:
    if (expression instanceof JetOperationExpression) {
      ResolvedCall<?> resolvedCall = CallUtilPackage.getResolvedCall(expression, context);
      if (resolvedCall != null) {
        JetFunction declaration = getFunctionDeclaration(resolvedCall);
        if (declaration != null) {
          actions.add(new ChangeFunctionReturnTypeFix(declaration, expectedType));
        }
      }
    }

    // Change function return type when TYPE_MISMATCH is reported on call expression:
    if (expression instanceof JetCallExpression) {
      ResolvedCall<?> resolvedCall = CallUtilPackage.getResolvedCall(expression, context);
      if (resolvedCall != null) {
        JetFunction declaration = getFunctionDeclaration(resolvedCall);
        if (declaration != null) {
          actions.add(new ChangeFunctionReturnTypeFix(declaration, expectedType));
        }
      }
    }

    ResolvedCall<? extends CallableDescriptor> resolvedCall =
        CallUtilPackage.getParentResolvedCall(expression, context, true);
    if (resolvedCall != null) {
      // to fix 'type mismatch' on 'if' branches
      // todo: the same with 'when'
      JetExpression parentIf = QuickFixUtil.getParentIfForBranch(expression);
      JetExpression argumentExpression = (parentIf != null) ? parentIf : expression;
      ValueArgument valueArgument =
          CallUtilPackage.getValueArgumentForExpression(resolvedCall.getCall(), argumentExpression);
      if (valueArgument != null) {
        JetParameter correspondingParameter =
            QuickFixUtil.getParameterDeclarationForValueArgument(resolvedCall, valueArgument);
        JetType valueArgumentType =
            diagnostic.getFactory() == Errors.NULL_FOR_NONNULL_TYPE
                ? expressionType
                : context.getType(valueArgument.getArgumentExpression());
        if (correspondingParameter != null && valueArgumentType != null) {
          JetCallableDeclaration callable =
              PsiTreeUtil.getParentOfType(
                  correspondingParameter, JetCallableDeclaration.class, true);
          LexicalScope scope =
              callable != null
                  ? CorePackage.getResolutionScope(
                      callable, context, ResolutionUtils.getResolutionFacade(callable))
                  : null;
          JetType typeToInsert =
              TypeUtils.approximateWithResolvableType(valueArgumentType, scope, true);
          actions.add(new ChangeParameterTypeFix(correspondingParameter, typeToInsert));
        }
      }
    }
    return actions;
  }