private void generateDataClassEqualsIfNeeded(@NotNull List<PropertyDescriptor> properties) {
   FunctionDescriptor function =
       getDeclaredMember("equals", builtIns.getBoolean(), builtIns.getAny());
   if (function != null && isTrivial(function)) {
     generateEqualsMethod(function, properties);
   }
 }
Exemple #2
0
  public static boolean shouldRecordInitializerForProperty(
      @NotNull VariableDescriptor variable, @NotNull KotlinType type) {
    if (variable.isVar() || type.isError()) return false;

    if (TypeUtils.acceptsNullable(type)) return true;

    KotlinBuiltIns builtIns = getBuiltIns(variable);
    return KotlinBuiltIns.isPrimitiveType(type)
        || KotlinTypeChecker.DEFAULT.equalTypes(builtIns.getStringType(), type)
        || KotlinTypeChecker.DEFAULT.equalTypes(builtIns.getNumber().getDefaultType(), type)
        || KotlinTypeChecker.DEFAULT.equalTypes(builtIns.getAnyType(), type);
  }
 private static boolean isFromBuiltinModule(@NotNull DeclarationDescriptor originalDescriptor) {
   // TODO This is optimization only
   // It should be rewritten by checking declarationDescriptor.getSource(), when the latter returns
   // something non-trivial for builtins.
   return KotlinBuiltIns.getInstance().getBuiltInsModule()
       == DescriptorUtils.getContainingModule(originalDescriptor);
 }
  public boolean isMain(@NotNull JetNamedFunction function) {
    if (!"main".equals(function.getName())) return false;

    FunctionDescriptor functionDescriptor = getFunctionDescriptor.fun(function);
    List<ValueParameterDescriptor> parameters = functionDescriptor.getValueParameters();
    if (parameters.size() != 1) return false;

    ValueParameterDescriptor parameter = parameters.get(0);
    JetType parameterType = parameter.getType();
    if (!KotlinBuiltIns.isArray(parameterType)) return false;

    List<TypeProjection> typeArguments = parameterType.getArguments();
    if (typeArguments.size() != 1) return false;

    JetType typeArgument = typeArguments.get(0).getType();
    if (!JetTypeChecker.DEFAULT.equalTypes(
        typeArgument, getBuiltIns(functionDescriptor).getStringType())) return false;

    if (DescriptorUtils.isTopLevelDeclaration(functionDescriptor)) return true;

    DeclarationDescriptor containingDeclaration = functionDescriptor.getContainingDeclaration();
    return containingDeclaration instanceof ClassDescriptor
        && ((ClassDescriptor) containingDeclaration).getKind().isSingleton()
        && AnnotationsPackage.hasPlatformStaticAnnotation(functionDescriptor);
  }
Exemple #5
0
 private static boolean isInlinableParameter(@NotNull CallableDescriptor descriptor) {
   JetType type = descriptor.getReturnType();
   return type != null
       && KotlinBuiltIns.isExactFunctionOrExtensionFunctionType(type)
       && !type.isMarkedNullable()
       && !InlineUtil.hasNoinlineAnnotation(descriptor);
 }
Exemple #6
0
 private TypeParameterDescriptor createTypeVariable(String name) {
   return TypeParameterDescriptorImpl.createWithDefaultBound(
       builtIns.getBuiltInsModule(),
       Annotations.Companion.getEMPTY(),
       false,
       Variance.INVARIANT,
       Name.identifier(name),
       0);
 }
  private KotlinTypeInfo getTypeOfLastExpressionInBlock(
      @NotNull KtExpression statementExpression,
      @NotNull ExpressionTypingContext context,
      @NotNull CoercionStrategy coercionStrategyForLastExpression,
      @NotNull ExpressionTypingInternals blockLevelVisitor) {
    if (context.expectedType != NO_EXPECTED_TYPE) {
      KotlinType expectedType;
      if (context.expectedType == UNIT_EXPECTED_TYPE
          || // the first check is necessary to avoid invocation 'isUnit(UNIT_EXPECTED_TYPE)'
          (coercionStrategyForLastExpression == COERCION_TO_UNIT
              && KotlinBuiltIns.isUnit(context.expectedType))) {
        expectedType = UNIT_EXPECTED_TYPE;
      } else {
        expectedType = context.expectedType;
      }

      return blockLevelVisitor.getTypeInfo(
          statementExpression, context.replaceExpectedType(expectedType), true);
    }
    KotlinTypeInfo result = blockLevelVisitor.getTypeInfo(statementExpression, context, true);
    if (coercionStrategyForLastExpression == COERCION_TO_UNIT) {
      boolean mightBeUnit = false;
      if (statementExpression instanceof KtDeclaration) {
        mightBeUnit = true;
      }
      if (statementExpression instanceof KtBinaryExpression) {
        KtBinaryExpression binaryExpression = (KtBinaryExpression) statementExpression;
        IElementType operationType = binaryExpression.getOperationToken();
        //noinspection SuspiciousMethodCalls
        if (operationType == KtTokens.EQ
            || OperatorConventions.ASSIGNMENT_OPERATIONS.containsKey(operationType)) {
          mightBeUnit = true;
        }
      }
      if (mightBeUnit) {
        // ExpressionTypingVisitorForStatements should return only null or Unit for declarations and
        // assignments,
        // but (for correct assignment / initialization analysis) data flow info must be preserved
        assert result.getType() == null || KotlinBuiltIns.isUnit(result.getType());
        result = result.replaceType(expressionTypingComponents.builtIns.getUnitType());
      }
    }
    return result;
  }
  @Override
  public void setUp() throws Exception {
    super.setUp();

    builtIns = KotlinBuiltIns.getInstance();

    ContainerForTests container =
        DiPackage.createContainerForTests(getProject(), JetTestUtils.createEmptyModule());
    typeResolver = container.getTypeResolver();
    expressionTypingServices = container.getExpressionTypingServices();

    scopeWithImports = getDeclarationsScope("compiler/testData/type-checker-test.kt");
  }
Exemple #9
0
  @Nullable
  public static KotlinType getDefaultPrimitiveNumberType(
      @NotNull Collection<KotlinType> supertypes) {
    if (supertypes.isEmpty()) {
      return null;
    }

    KotlinBuiltIns builtIns = supertypes.iterator().next().getConstructor().getBuiltIns();
    KotlinType doubleType = builtIns.getDoubleType();
    if (supertypes.contains(doubleType)) {
      return doubleType;
    }
    KotlinType intType = builtIns.getIntType();
    if (supertypes.contains(intType)) {
      return intType;
    }
    KotlinType longType = builtIns.getLongType();
    if (supertypes.contains(longType)) {
      return longType;
    }
    return null;
  }
  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;
  }
Exemple #11
0
 // As this method produces a warning, it must be _complete_ (not sound), i.e. every time it says
 // "cast impossible",
 // it must be really impossible
 public static boolean isCastPossible(
     @NotNull KotlinType lhsType,
     @NotNull KotlinType rhsType,
     @NotNull PlatformToKotlinClassMap platformToKotlinClassMap) {
   if (KotlinBuiltIns.isNullableNothing(lhsType) && !TypeUtils.isNullableType(rhsType))
     return false;
   if (isRelated(lhsType, rhsType, platformToKotlinClassMap)) return true;
   // This is an oversimplification (which does not render the method incomplete):
   // we consider any type parameter capable of taking any value, which may be made more precise if
   // we considered bounds
   if (TypeUtils.isTypeParameter(lhsType) || TypeUtils.isTypeParameter(rhsType)) return true;
   if (isFinal(lhsType) || isFinal(rhsType)) return false;
   if (isTrait(lhsType) || isTrait(rhsType)) return true;
   return false;
 }
  /** @return true if the member is an inherited implementation of a method from Any */
  private boolean isTrivial(@NotNull FunctionDescriptor function) {
    if (function.getKind() == CallableMemberDescriptor.Kind.DECLARATION) {
      return false;
    }

    for (CallableDescriptor overridden : OverrideResolver.getOverriddenDeclarations(function)) {
      if (overridden instanceof CallableMemberDescriptor
          && ((CallableMemberDescriptor) overridden).getKind()
              == CallableMemberDescriptor.Kind.DECLARATION
          && !overridden.getContainingDeclaration().equals(builtIns.getAny())) {
        return false;
      }
    }

    return true;
  }
Exemple #13
0
  private static boolean isInvokeOrInlineExtension(@NotNull CallableDescriptor descriptor) {
    if (!(descriptor instanceof SimpleFunctionDescriptor)) {
      return false;
    }

    DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
    boolean isInvoke =
        descriptor.getName().asString().equals("invoke")
            && containingDeclaration instanceof ClassDescriptor
            && KotlinBuiltIns.isExactFunctionOrExtensionFunctionType(
                ((ClassDescriptor) containingDeclaration).getDefaultType());

    return isInvoke
        ||
        // or inline extension
        ((SimpleFunctionDescriptor) descriptor).getInlineStrategy().isInline();
  }
  private static List<FunctionDescriptor> generateFunctionsToAdd(JetNamedFunction functionElement) {
    FunctionDescriptor functionDescriptor =
        (FunctionDescriptor) ResolvePackage.resolveToDescriptor(functionElement);

    DeclarationDescriptor containingDeclaration = functionDescriptor.getContainingDeclaration();
    if (!(containingDeclaration instanceof ClassDescriptor)) return Collections.emptyList();

    List<FunctionDescriptor> functions = Lists.newArrayList();
    ClassDescriptor classDescriptor = (ClassDescriptor) containingDeclaration;
    // TODO: filter out impossible supertypes (for example when argument's type isn't visible in a
    // superclass).
    for (ClassDescriptor supertypeDescriptor : getSupertypes(classDescriptor)) {
      if (KotlinBuiltIns.isAnyOrNullableAny(supertypeDescriptor.getDefaultType())) continue;
      functions.add(generateFunctionSignatureForType(functionDescriptor, supertypeDescriptor));
    }
    return functions;
  }
  @NotNull
  protected Collection<KotlinType> computeSupertypes() {
    if (KotlinBuiltIns.isSpecialClassWithNoSupertypes(this)) {
      return Collections.emptyList();
    }

    KtClassOrObject classOrObject =
        declarationProvider.getOwnerInfo().getCorrespondingClassOrObject();
    if (classOrObject == null) {
      return Collections.<KotlinType>singleton(c.getModuleDescriptor().getBuiltIns().getAnyType());
    }

    List<KotlinType> allSupertypes =
        c.getDescriptorResolver()
            .resolveSupertypes(
                getScopeForClassHeaderResolution(), this, classOrObject, c.getTrace());

    return Lists.newArrayList(Collections2.filter(allSupertypes, VALID_SUPERTYPE));
  }
Exemple #16
0
 private static synchronized void initialize() {
   if (instance == null) {
     if (initializationFailed != null) {
       throw new RuntimeException(
           "builtin library initialization failed previously: " + initializationFailed,
           initializationFailed);
     }
     if (initializing) {
       throw new IllegalStateException("builtin library initialization loop");
     }
     initializing = true;
     try {
       instance = new KotlinBuiltIns();
       instance.doInitialize();
     } catch (Throwable e) {
       initializationFailed = e;
       throw new RuntimeException("builtin library initialization failed: " + e, e);
     } finally {
       initializing = false;
     }
   }
 }
 @NotNull
 private KotlinTypeInfo getTypeInfoWhenOnlyOneBranchIsPresent(
     @NotNull KtExpression presentBranch,
     @NotNull LexicalWritableScope presentScope,
     @NotNull DataFlowInfo presentInfo,
     @NotNull DataFlowInfo otherInfo,
     @NotNull ExpressionTypingContext context,
     @NotNull KtIfExpression ifExpression,
     boolean isStatement) {
   ExpressionTypingContext newContext =
       context
           .replaceDataFlowInfo(presentInfo)
           .replaceExpectedType(NO_EXPECTED_TYPE)
           .replaceContextDependency(INDEPENDENT);
   KotlinTypeInfo typeInfo =
       components.expressionTypingServices.getBlockReturnedTypeWithWritableScope(
           presentScope,
           Collections.singletonList(presentBranch),
           CoercionStrategy.NO_COERCION,
           newContext);
   KotlinType type = typeInfo.getType();
   DataFlowInfo dataFlowInfo;
   if (type != null && KotlinBuiltIns.isNothing(type)) {
     dataFlowInfo = otherInfo;
   } else {
     dataFlowInfo = typeInfo.getDataFlowInfo().or(otherInfo);
   }
   return components
       .dataFlowAnalyzer
       .checkImplicitCast(
           components.dataFlowAnalyzer.checkType(
               typeInfo.replaceType(components.builtIns.getUnitType()), ifExpression, context),
           ifExpression,
           context,
           isStatement)
       .replaceDataFlowInfo(dataFlowInfo);
 }
  @NotNull
  private TypeProjection unsafeSubstitute(
      @NotNull TypeProjection originalProjection, int recursionDepth) throws SubstitutionException {
    assertRecursionDepth(recursionDepth, originalProjection, substitution);

    if (originalProjection.isStarProjection()) return originalProjection;

    // The type is within the substitution range, i.e. T or T?
    JetType type = originalProjection.getType();
    TypeProjection replacement = substitution.get(type);
    Variance originalProjectionKind = originalProjection.getProjectionKind();
    if (replacement == null
        && FlexibleTypesKt.isFlexible(type)
        && !TypeCapabilitiesKt.isCustomTypeVariable(type)) {
      Flexibility flexibility = FlexibleTypesKt.flexibility(type);
      TypeProjection substitutedLower =
          unsafeSubstitute(
              new TypeProjectionImpl(originalProjectionKind, flexibility.getLowerBound()),
              recursionDepth + 1);
      TypeProjection substitutedUpper =
          unsafeSubstitute(
              new TypeProjectionImpl(originalProjectionKind, flexibility.getUpperBound()),
              recursionDepth + 1);

      Variance substitutedProjectionKind = substitutedLower.getProjectionKind();
      assert (substitutedProjectionKind == substitutedUpper.getProjectionKind())
                  && originalProjectionKind == Variance.INVARIANT
              || originalProjectionKind == substitutedProjectionKind
          : "Unexpected substituted projection kind: "
              + substitutedProjectionKind
              + "; original: "
              + originalProjectionKind;

      JetType substitutedFlexibleType =
          DelegatingFlexibleType.create(
              substitutedLower.getType(),
              substitutedUpper.getType(),
              flexibility.getExtraCapabilities());
      return new TypeProjectionImpl(substitutedProjectionKind, substitutedFlexibleType);
    }

    if (KotlinBuiltIns.isNothing(type) || type.isError()) return originalProjection;

    if (replacement != null) {
      VarianceConflictType varianceConflict =
          conflictType(originalProjectionKind, replacement.getProjectionKind());

      // Captured type might be substituted in an opposite projection:
      // out 'Captured (in Int)' = out Int
      // in 'Captured (out Int)' = in Int
      boolean allowVarianceConflict = CapturedTypeConstructorKt.isCaptured(type);
      if (!allowVarianceConflict) {
        //noinspection EnumSwitchStatementWhichMissesCases
        switch (varianceConflict) {
          case OUT_IN_IN_POSITION:
            throw new SubstitutionException("Out-projection in in-position");
          case IN_IN_OUT_POSITION:
            // todo use the right type parameter variance and upper bound
            return new TypeProjectionImpl(
                Variance.OUT_VARIANCE, type.getConstructor().getBuiltIns().getNullableAnyType());
        }
      }
      JetType substitutedType;
      CustomTypeVariable typeVariable = TypeCapabilitiesKt.getCustomTypeVariable(type);
      if (replacement.isStarProjection()) {
        return replacement;
      } else if (typeVariable != null) {
        substitutedType = typeVariable.substitutionResult(replacement.getType());
      } else {
        // this is a simple type T or T?: if it's T, we should just take replacement, if T? - we
        // make replacement nullable
        substitutedType =
            TypeUtils.makeNullableIfNeeded(replacement.getType(), type.isMarkedNullable());
      }

      // substitutionType.annotations = replacement.annotations ++ type.annotations
      if (!type.getAnnotations().isEmpty()) {
        Annotations typeAnnotations = filterOutUnsafeVariance(type.getAnnotations());
        substitutedType =
            TypeUtilsKt.replaceAnnotations(
                substitutedType,
                new CompositeAnnotations(substitutedType.getAnnotations(), typeAnnotations));
      }

      Variance resultingProjectionKind =
          varianceConflict == VarianceConflictType.NO_CONFLICT
              ? combine(originalProjectionKind, replacement.getProjectionKind())
              : originalProjectionKind;
      return new TypeProjectionImpl(resultingProjectionKind, substitutedType);
    }
    // The type is not within the substitution range, i.e. Foo, Bar<T> etc.
    return substituteCompoundType(originalProjection, recursionDepth);
  }
  @NotNull
  public LineResult eval(@NotNull String line) {
    ++lineNumber;

    FqName scriptFqName = new FqName("Line" + lineNumber);
    Type scriptClassType = asmTypeByFqNameWithoutInnerClasses(scriptFqName);

    StringBuilder fullText = new StringBuilder();
    for (String prevLine : previousIncompleteLines) {
      fullText.append(prevLine).append("\n");
    }
    fullText.append(line);

    LightVirtualFile virtualFile =
        new LightVirtualFile(
            "line" + lineNumber + JetParserDefinition.STD_SCRIPT_EXT,
            JetLanguage.INSTANCE,
            fullText.toString());
    virtualFile.setCharset(CharsetToolkit.UTF8_CHARSET);
    JetFile psiFile =
        (JetFile) psiFileFactory.trySetupPsiForFile(virtualFile, JetLanguage.INSTANCE, true, false);
    assert psiFile != null : "Script file not analyzed at line " + lineNumber + ": " + fullText;

    ReplMessageCollectorWrapper errorCollector = new ReplMessageCollectorWrapper();

    AnalyzerWithCompilerReport.SyntaxErrorReport syntaxErrorReport =
        AnalyzerWithCompilerReport.reportSyntaxErrors(
            psiFile, errorCollector.getMessageCollector());

    if (syntaxErrorReport.isHasErrors() && syntaxErrorReport.isAllErrorsAtEof()) {
      previousIncompleteLines.add(line);
      return LineResult.incomplete();
    }

    previousIncompleteLines.clear();

    if (syntaxErrorReport.isHasErrors()) {
      return LineResult.error(errorCollector.getString());
    }

    prepareForTheNextReplLine(topDownAnalysisContext);
    trace.clearDiagnostics();

    //noinspection ConstantConditions
    psiFile.getScript().putUserData(ScriptPriorities.PRIORITY_KEY, lineNumber);

    ScriptDescriptor scriptDescriptor = doAnalyze(psiFile, errorCollector);
    if (scriptDescriptor == null) {
      return LineResult.error(errorCollector.getString());
    }

    List<Pair<ScriptDescriptor, Type>> earlierScripts = Lists.newArrayList();

    for (EarlierLine earlierLine : earlierLines) {
      earlierScripts.add(
          Pair.create(earlierLine.getScriptDescriptor(), earlierLine.getClassType()));
    }

    GenerationState state =
        new GenerationState(
            psiFile.getProject(),
            ClassBuilderFactories.BINARIES,
            module,
            trace.getBindingContext(),
            Collections.singletonList(psiFile));

    compileScript(
        psiFile.getScript(),
        scriptClassType,
        earlierScripts,
        state,
        CompilationErrorHandler.THROW_EXCEPTION);

    for (OutputFile outputFile : state.getFactory().asList()) {
      classLoader.addClass(
          JvmClassName.byInternalName(outputFile.getRelativePath().replaceFirst("\\.class$", "")),
          outputFile.asByteArray());
    }

    try {
      Class<?> scriptClass = classLoader.loadClass(scriptFqName.asString());

      Class<?>[] constructorParams = new Class<?>[earlierLines.size()];
      Object[] constructorArgs = new Object[earlierLines.size()];

      for (int i = 0; i < earlierLines.size(); ++i) {
        constructorParams[i] = earlierLines.get(i).getScriptClass();
        constructorArgs[i] = earlierLines.get(i).getScriptInstance();
      }

      Constructor<?> scriptInstanceConstructor = scriptClass.getConstructor(constructorParams);
      Object scriptInstance;
      try {
        scriptInstance = scriptInstanceConstructor.newInstance(constructorArgs);
      } catch (Throwable e) {
        return LineResult.error(renderStackTrace(e.getCause()));
      }
      Field rvField = scriptClass.getDeclaredField("rv");
      rvField.setAccessible(true);
      Object rv = rvField.get(scriptInstance);

      earlierLines.add(
          new EarlierLine(line, scriptDescriptor, scriptClass, scriptInstance, scriptClassType));

      JetType returnType = scriptDescriptor.getScriptCodeDescriptor().getReturnType();
      return LineResult.successful(rv, returnType != null && KotlinBuiltIns.isUnit(returnType));
    } catch (Throwable e) {
      @SuppressWarnings("UseOfSystemOutOrSystemErr")
      PrintWriter writer = new PrintWriter(System.err);
      classLoader.dumpClasses(writer);
      writer.flush();
      throw UtilsPackage.rethrow(e);
    }
  }
  @Override
  public boolean processUsage(JetChangeInfo changeInfo, PsiElement element) {
    JetParameterList parameterList;

    JetPsiFactory psiFactory = JetPsiFactory(element.getProject());
    if (element instanceof JetFunction) {
      JetFunction function = (JetFunction) element;
      parameterList = function.getValueParameterList();

      if (changeInfo.isNameChanged()) {
        PsiElement identifier = function.getNameIdentifier();

        if (identifier != null) {
          identifier.replace(psiFactory.createIdentifier(changeInfo.getNewName()));
        }
      }

      boolean returnTypeIsNeeded =
          (changeInfo.isRefactoringTarget(originalFunctionDescriptor)
                  || !(function instanceof JetFunctionLiteral)
                  || function.getTypeReference() != null)
              && !(function instanceof JetSecondaryConstructor);
      if (changeInfo.isReturnTypeChanged() && returnTypeIsNeeded) {
        function.setTypeReference(null);
        String returnTypeText =
            changeInfo.renderReturnType((JetFunctionDefinitionUsage<PsiElement>) this);

        // TODO use ChangeFunctionReturnTypeFix.invoke when JetTypeCodeFragment.getType() is ready
        if (!KotlinBuiltIns.getInstance().getUnitType().toString().equals(returnTypeText)) {
          ShortenPackage.addToShorteningWaitSet(
              function.setTypeReference(JetPsiFactory(function).createType(returnTypeText)),
              Options.DEFAULT);
        }
      }
    } else {
      parameterList = ((JetClass) element).getPrimaryConstructorParameterList();
    }

    if (changeInfo.isParameterSetOrOrderChanged()) {
      processParameterListWithStructuralChanges(changeInfo, element, parameterList, psiFactory);
    } else if (parameterList != null) {
      int paramIndex = 0;

      for (JetParameter parameter : parameterList.getParameters()) {
        JetParameterInfo parameterInfo = changeInfo.getNewParameters()[paramIndex];
        changeParameter(paramIndex, parameter, parameterInfo);
        paramIndex++;
      }

      ShortenPackage.addToShorteningWaitSet(parameterList, Options.DEFAULT);
    }

    if (element instanceof JetFunction && changeInfo.isReceiverTypeChanged()) {
      //noinspection unchecked
      String receiverTypeText =
          changeInfo.renderReceiverType((JetFunctionDefinitionUsage<PsiElement>) this);
      JetTypeReference receiverTypeRef =
          receiverTypeText != null ? psiFactory.createType(receiverTypeText) : null;
      JetTypeReference newReceiverTypeRef =
          TypeRefHelpersPackage.setReceiverTypeReference((JetFunction) element, receiverTypeRef);
      if (newReceiverTypeRef != null) {
        ShortenPackage.addToShorteningWaitSet(
            newReceiverTypeRef, ShortenReferences.Options.DEFAULT);
      }
    }

    if (changeInfo.isVisibilityChanged() && !JetPsiUtil.isLocal((JetDeclaration) element)) {
      changeVisibility(changeInfo, element);
    }

    return true;
  }
  public void testConstants() throws Exception {
    assertType("1", builtIns.getIntType());
    assertType("0x1", builtIns.getIntType());
    assertType("0X1", builtIns.getIntType());
    assertType("0b1", builtIns.getIntType());
    assertType("0B1", builtIns.getIntType());

    assertType("1.toLong()", builtIns.getLongType());

    assertType("1.0", builtIns.getDoubleType());
    assertType("1.0.toDouble()", builtIns.getDoubleType());
    assertType("0x1.fffffffffffffp1023", builtIns.getDoubleType());

    assertType("1.0.toFloat()", builtIns.getFloatType());
    assertType("0x1.fffffffffffffp1023.toFloat()", builtIns.getFloatType());

    assertType("true", builtIns.getBooleanType());
    assertType("false", builtIns.getBooleanType());

    assertType("'d'", builtIns.getCharType());

    assertType("\"d\"", builtIns.getStringType());
    assertType("\"\"\"d\"\"\"", builtIns.getStringType());

    assertType("Unit", KotlinBuiltIns.getInstance().getUnitType());

    assertType("null", KotlinBuiltIns.getInstance().getNullableNothingType());
  }
  public KotlinTypeInfo visitIfExpression(
      KtIfExpression ifExpression,
      ExpressionTypingContext contextWithExpectedType,
      boolean isStatement) {
    ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE);
    KtExpression condition = ifExpression.getCondition();
    DataFlowInfo conditionDataFlowInfo = checkCondition(context.scope, condition, context);

    KtExpression elseBranch = ifExpression.getElse();
    KtExpression thenBranch = ifExpression.getThen();

    LexicalWritableScope thenScope = newWritableScopeImpl(context, "Then scope");
    LexicalWritableScope elseScope = newWritableScopeImpl(context, "Else scope");
    DataFlowInfo thenInfo =
        components
            .dataFlowAnalyzer
            .extractDataFlowInfoFromCondition(condition, true, context)
            .and(conditionDataFlowInfo);
    DataFlowInfo elseInfo =
        components
            .dataFlowAnalyzer
            .extractDataFlowInfoFromCondition(condition, false, context)
            .and(conditionDataFlowInfo);

    if (elseBranch == null) {
      if (thenBranch != null) {
        KotlinTypeInfo result =
            getTypeInfoWhenOnlyOneBranchIsPresent(
                thenBranch,
                thenScope,
                thenInfo,
                elseInfo,
                contextWithExpectedType,
                ifExpression,
                isStatement);
        // If jump was possible, take condition check info as the jump info
        return result.getJumpOutPossible()
            ? result.replaceJumpOutPossible(true).replaceJumpFlowInfo(conditionDataFlowInfo)
            : result;
      }
      return TypeInfoFactoryKt.createTypeInfo(
          components.dataFlowAnalyzer.checkImplicitCast(
              components.builtIns.getUnitType(),
              ifExpression,
              contextWithExpectedType,
              isStatement),
          thenInfo.or(elseInfo));
    }
    if (thenBranch == null) {
      return getTypeInfoWhenOnlyOneBranchIsPresent(
          elseBranch,
          elseScope,
          elseInfo,
          thenInfo,
          contextWithExpectedType,
          ifExpression,
          isStatement);
    }
    KtPsiFactory psiFactory = KtPsiFactoryKt.KtPsiFactory(ifExpression);
    KtBlockExpression thenBlock = psiFactory.wrapInABlockWrapper(thenBranch);
    KtBlockExpression elseBlock = psiFactory.wrapInABlockWrapper(elseBranch);
    Call callForIf =
        createCallForSpecialConstruction(
            ifExpression, ifExpression, Lists.newArrayList(thenBlock, elseBlock));
    MutableDataFlowInfoForArguments dataFlowInfoForArguments =
        createDataFlowInfoForArgumentsForIfCall(callForIf, thenInfo, elseInfo);
    ResolvedCall<FunctionDescriptor> resolvedCall =
        components.controlStructureTypingUtils.resolveSpecialConstructionAsCall(
            callForIf,
            ResolveConstruct.IF,
            Lists.newArrayList("thenBranch", "elseBranch"),
            Lists.newArrayList(false, false),
            contextWithExpectedType,
            dataFlowInfoForArguments);

    BindingContext bindingContext = context.trace.getBindingContext();
    KotlinTypeInfo thenTypeInfo =
        BindingContextUtils.getRecordedTypeInfo(thenBranch, bindingContext);
    KotlinTypeInfo elseTypeInfo =
        BindingContextUtils.getRecordedTypeInfo(elseBranch, bindingContext);
    assert thenTypeInfo != null
        : "'Then' branch of if expression  was not processed: " + ifExpression;
    assert elseTypeInfo != null
        : "'Else' branch of if expression  was not processed: " + ifExpression;
    boolean loopBreakContinuePossible =
        thenTypeInfo.getJumpOutPossible() || elseTypeInfo.getJumpOutPossible();

    KotlinType thenType = thenTypeInfo.getType();
    KotlinType elseType = elseTypeInfo.getType();
    DataFlowInfo thenDataFlowInfo = thenTypeInfo.getDataFlowInfo();
    DataFlowInfo elseDataFlowInfo = elseTypeInfo.getDataFlowInfo();

    boolean jumpInThen = thenType != null && KotlinBuiltIns.isNothing(thenType);
    boolean jumpInElse = elseType != null && KotlinBuiltIns.isNothing(elseType);

    DataFlowInfo resultDataFlowInfo;
    if (thenType == null && elseType == null) {
      resultDataFlowInfo = thenDataFlowInfo.or(elseDataFlowInfo);
    } else if (thenType == null || (jumpInThen && !jumpInElse)) {
      resultDataFlowInfo = elseDataFlowInfo;
    } else if (elseType == null || (jumpInElse && !jumpInThen)) {
      resultDataFlowInfo = thenDataFlowInfo;
    } else {
      resultDataFlowInfo = thenDataFlowInfo.or(elseDataFlowInfo);
    }

    KotlinType resultType = resolvedCall.getResultingDescriptor().getReturnType();
    // If break or continue was possible, take condition check info as the jump info
    return TypeInfoFactoryKt.createTypeInfo(
        components.dataFlowAnalyzer.checkImplicitCast(
            resultType, ifExpression, contextWithExpectedType, isStatement),
        resultDataFlowInfo,
        loopBreakContinuePossible,
        conditionDataFlowInfo);
  }
 public void testJumps() throws Exception {
   assertType("throw java.lang.Exception()", KotlinBuiltIns.getInstance().getNothingType());
   assertType("continue", KotlinBuiltIns.getInstance().getNothingType());
   assertType("break", KotlinBuiltIns.getInstance().getNothingType());
 }
 private void generateDataClassHashCodeIfNeeded(@NotNull List<PropertyDescriptor> properties) {
   FunctionDescriptor function = getDeclaredMember("hashCode", builtIns.getInt());
   if (function != null && isTrivial(function)) {
     generateHashCodeMethod(function, properties);
   }
 }
  @Override
  public KotlinTypeInfo visitReturnExpression(
      @NotNull KtReturnExpression expression, ExpressionTypingContext context) {
    KtElement labelTargetElement = LabelResolver.INSTANCE.resolveControlLabel(expression, context);

    KtExpression returnedExpression = expression.getReturnedExpression();

    KotlinType expectedType = NO_EXPECTED_TYPE;
    KotlinType resultType = components.builtIns.getNothingType();
    KtDeclaration parentDeclaration = PsiTreeUtil.getParentOfType(expression, KtDeclaration.class);

    if (parentDeclaration instanceof KtParameter) {
      // In a default value for parameter
      context.trace.report(RETURN_NOT_ALLOWED.on(expression));
    }

    if (expression.getTargetLabel() == null) {
      while (parentDeclaration instanceof KtMultiDeclaration) {
        // TODO: It's hacking fix for KT-5100: Strange "Return is not allowed here" for
        // multi-declaration initializer with elvis expression
        parentDeclaration = PsiTreeUtil.getParentOfType(parentDeclaration, KtDeclaration.class);
      }

      assert parentDeclaration != null
          : "Can't find parent declaration for " + expression.getText();
      DeclarationDescriptor declarationDescriptor =
          context.trace.get(DECLARATION_TO_DESCRIPTOR, parentDeclaration);
      Pair<FunctionDescriptor, PsiElement> containingFunInfo =
          BindingContextUtils.getContainingFunctionSkipFunctionLiterals(
              declarationDescriptor, false);
      FunctionDescriptor containingFunctionDescriptor = containingFunInfo.getFirst();

      if (containingFunctionDescriptor != null) {
        if (!InlineUtil.checkNonLocalReturnUsage(
                containingFunctionDescriptor, expression, context.trace)
            || isClassInitializer(containingFunInfo)) {
          // Unqualified, in a function literal
          context.trace.report(RETURN_NOT_ALLOWED.on(expression));
          resultType = ErrorUtils.createErrorType(RETURN_NOT_ALLOWED_MESSAGE);
        }

        expectedType =
            getFunctionExpectedReturnType(
                containingFunctionDescriptor, (KtElement) containingFunInfo.getSecond(), context);
      } else {
        // Outside a function
        context.trace.report(RETURN_NOT_ALLOWED.on(expression));
        resultType = ErrorUtils.createErrorType(RETURN_NOT_ALLOWED_MESSAGE);
      }
    } else if (labelTargetElement != null) {
      SimpleFunctionDescriptor functionDescriptor = context.trace.get(FUNCTION, labelTargetElement);
      if (functionDescriptor != null) {
        expectedType =
            getFunctionExpectedReturnType(functionDescriptor, labelTargetElement, context);
        if (!InlineUtil.checkNonLocalReturnUsage(functionDescriptor, expression, context.trace)) {
          // Qualified, non-local
          context.trace.report(RETURN_NOT_ALLOWED.on(expression));
          resultType = ErrorUtils.createErrorType(RETURN_NOT_ALLOWED_MESSAGE);
        }
      } else {
        context.trace.report(NOT_A_RETURN_LABEL.on(expression, expression.getLabelName()));
      }
    }
    if (returnedExpression != null) {
      facade.getTypeInfo(
          returnedExpression,
          context
              .replaceExpectedType(expectedType)
              .replaceScope(context.scope)
              .replaceContextDependency(INDEPENDENT));
    } else {
      if (expectedType != null
          && !noExpectedType(expectedType)
          && !KotlinBuiltIns.isUnit(expectedType)
          && !isDontCarePlaceholder(expectedType)) // for lambda with implicit return type Unit
      {
        context.trace.report(RETURN_TYPE_MISMATCH.on(expression, expectedType));
      }
    }
    return components.dataFlowAnalyzer.createCheckedTypeInfo(resultType, context, expression);
  }
  @Nullable
  public KotlinType checkIterableConvention(
      @NotNull ExpressionReceiver loopRange, ExpressionTypingContext context) {
    KtExpression loopRangeExpression = loopRange.getExpression();

    // Make a fake call loopRange.iterator(), and try to resolve it
    Name iterator = Name.identifier("iterator");
    Pair<Call, OverloadResolutionResults<FunctionDescriptor>> calls =
        fakeCallResolver.makeAndResolveFakeCall(
            loopRange,
            context,
            Collections.<KtExpression>emptyList(),
            iterator,
            loopRangeExpression,
            FakeCallKind.ITERATOR,
            loopRangeExpression);
    OverloadResolutionResults<FunctionDescriptor> iteratorResolutionResults = calls.getSecond();

    if (iteratorResolutionResults.isSuccess()) {
      ResolvedCall<FunctionDescriptor> iteratorResolvedCall =
          iteratorResolutionResults.getResultingCall();
      context.trace.record(
          LOOP_RANGE_ITERATOR_RESOLVED_CALL, loopRangeExpression, iteratorResolvedCall);
      FunctionDescriptor iteratorFunction = iteratorResolvedCall.getResultingDescriptor();

      checkIfOperatorModifierPresent(loopRangeExpression, iteratorFunction, context.trace);

      symbolUsageValidator.validateCall(
          iteratorResolvedCall, iteratorFunction, context.trace, loopRangeExpression);

      KotlinType iteratorType = iteratorFunction.getReturnType();
      KotlinType hasNextType =
          checkConventionForIterator(
              context,
              loopRangeExpression,
              iteratorType,
              "hasNext",
              HAS_NEXT_FUNCTION_AMBIGUITY,
              HAS_NEXT_MISSING,
              HAS_NEXT_FUNCTION_NONE_APPLICABLE,
              LOOP_RANGE_HAS_NEXT_RESOLVED_CALL);
      if (hasNextType != null && !builtIns.isBooleanOrSubtype(hasNextType)) {
        context.trace.report(HAS_NEXT_FUNCTION_TYPE_MISMATCH.on(loopRangeExpression, hasNextType));
      }
      return checkConventionForIterator(
          context,
          loopRangeExpression,
          iteratorType,
          "next",
          NEXT_AMBIGUITY,
          NEXT_MISSING,
          NEXT_NONE_APPLICABLE,
          LOOP_RANGE_NEXT_RESOLVED_CALL);
    } else {
      if (iteratorResolutionResults.isAmbiguity()) {
        context.trace.report(
            ITERATOR_AMBIGUITY.on(
                loopRangeExpression, iteratorResolutionResults.getResultingCalls()));
      } else {
        context.trace.report(ITERATOR_MISSING.on(loopRangeExpression));
      }
    }
    return null;
  }
Exemple #27
0
 private TypeProjection makeType(String typeStr) {
   return makeTypeProjection(builtIns.getBuiltInsPackageScope(), typeStr);
 }
  @Override
  public void updateUI(
      Pair<? extends FunctionDescriptor, ResolutionFacade> itemToShow,
      @NotNull ParameterInfoUIContext context) {
    // todo: when we will have ability to pass Array as vararg, implement such feature here too?
    if (context == null
        || context.getParameterOwner() == null
        || !context.getParameterOwner().isValid()) {
      context.setUIComponentEnabled(false);
      return;
    }

    PsiElement parameterOwner = context.getParameterOwner();
    if (!(parameterOwner instanceof JetValueArgumentList)) {
      context.setUIComponentEnabled(false);
      return;
    }

    JetValueArgumentList argumentList = (JetValueArgumentList) parameterOwner;

    FunctionDescriptor functionDescriptor = itemToShow.first;
    ResolutionFacade resolutionFacade = itemToShow.second;

    List<ValueParameterDescriptor> valueParameters = functionDescriptor.getValueParameters();
    List<JetValueArgument> valueArguments = argumentList.getArguments();

    int currentParameterIndex = context.getCurrentParameterIndex();
    int boldStartOffset = -1;
    int boldEndOffset = -1;
    boolean isGrey = false;
    boolean isDeprecated = KotlinBuiltIns.isDeprecated(functionDescriptor);

    boolean[] usedIndexes = new boolean[valueParameters.size()];
    Arrays.fill(usedIndexes, false);

    boolean namedMode = false;

    if (!isIndexValid(valueParameters, currentParameterIndex)) {
      isGrey = true;
    }

    StringBuilder builder = new StringBuilder();

    PsiElement owner = context.getParameterOwner();
    BindingContext bindingContext =
        resolutionFacade.analyze((JetElement) owner, BodyResolveMode.FULL);

    for (int i = 0; i < valueParameters.size(); ++i) {
      if (i != 0) {
        builder.append(", ");
      }

      boolean highlightParameter =
          i == currentParameterIndex
              || (!namedMode
                  && i < currentParameterIndex
                  && Iterables.getLast(valueParameters).getVarargElementType() != null);

      if (highlightParameter) {
        boldStartOffset = builder.length();
      }

      if (!namedMode) {
        if (valueArguments.size() > i) {
          JetValueArgument argument = valueArguments.get(i);
          if (argument.isNamed()) {
            namedMode = true;
          } else {
            ValueParameterDescriptor param = valueParameters.get(i);
            builder.append(renderParameter(param, false));
            if (i <= currentParameterIndex
                && !isArgumentTypeValid(bindingContext, argument, param)) {
              isGrey = true;
            }
            usedIndexes[i] = true;
          }
        } else {
          ValueParameterDescriptor param = valueParameters.get(i);
          builder.append(renderParameter(param, false));
        }
      }

      if (namedMode) {
        boolean takeAnyArgument = true;
        if (valueArguments.size() > i) {
          JetValueArgument argument = valueArguments.get(i);
          if (argument.isNamed()) {
            for (int j = 0; j < valueParameters.size(); ++j) {
              JetSimpleNameExpression referenceExpression =
                  argument.getArgumentName().getReferenceExpression();
              ValueParameterDescriptor param = valueParameters.get(j);
              if (referenceExpression != null
                  && !usedIndexes[j]
                  && param.getName().equals(referenceExpression.getReferencedNameAsName())) {
                takeAnyArgument = false;
                usedIndexes[j] = true;
                builder.append(renderParameter(param, true));
                if (i < currentParameterIndex
                    && !isArgumentTypeValid(bindingContext, argument, param)) {
                  isGrey = true;
                }
                break;
              }
            }
          }
        }

        if (takeAnyArgument) {
          if (i < currentParameterIndex) {
            isGrey = true;
          }

          for (int j = 0; j < valueParameters.size(); ++j) {
            ValueParameterDescriptor param = valueParameters.get(j);
            if (!usedIndexes[j]) {
              usedIndexes[j] = true;
              builder.append(renderParameter(param, true));
              break;
            }
          }
        }
      }

      if (highlightParameter) {
        boldEndOffset = builder.length();
      }
    }

    if (valueParameters.size() == 0) {
      builder.append(CodeInsightBundle.message("parameter.info.no.parameters"));
    }

    assert !builder.toString().isEmpty()
        : "A message about 'no parameters' or some parameters should be present: "
            + functionDescriptor;

    Color color =
        isResolvedToDescriptor(argumentList, functionDescriptor, bindingContext)
            ? GREEN_BACKGROUND
            : context.getDefaultParameterColor();
    context.setupUIComponentPresentation(
        builder.toString(), boldStartOffset, boldEndOffset, isGrey, isDeprecated, false, color);
  }
 private void generateDataClassToStringIfNeeded(@NotNull List<PropertyDescriptor> properties) {
   FunctionDescriptor function = getDeclaredMember("toString", builtIns.getString());
   if (function != null && isTrivial(function)) {
     generateToStringMethod(function, properties);
   }
 }