Search in sources :

Example 76 with IElementType

use of com.intellij.psi.tree.IElementType in project kotlin by JetBrains.

the class BasicExpressionTypingVisitor method visitConstantExpression.

@Override
public KotlinTypeInfo visitConstantExpression(@NotNull KtConstantExpression expression, ExpressionTypingContext context) {
    IElementType elementType = expression.getNode().getElementType();
    if (elementType == KtNodeTypes.CHARACTER_CONSTANT || elementType == KtNodeTypes.INTEGER_CONSTANT || elementType == KtNodeTypes.FLOAT_CONSTANT) {
        checkLiteralPrefixAndSuffix(expression, context);
    }
    if (elementType == KtNodeTypes.INTEGER_CONSTANT || elementType == KtNodeTypes.FLOAT_CONSTANT) {
        checkUnderscores(expression, elementType, context);
    }
    CompileTimeConstant<?> compileTimeConstant = components.constantExpressionEvaluator.evaluateExpression(expression, context.trace, context.expectedType);
    if (!(compileTimeConstant instanceof IntegerValueTypeConstant)) {
        CompileTimeConstantChecker constantChecker = new CompileTimeConstantChecker(context, components.builtIns, false);
        ConstantValue constantValue = compileTimeConstant != null ? ((TypedCompileTimeConstant) compileTimeConstant).getConstantValue() : null;
        boolean hasError = constantChecker.checkConstantExpressionType(constantValue, expression, context.expectedType);
        if (hasError) {
            return TypeInfoFactoryKt.createTypeInfo(constantValue != null ? constantValue.getType() : getDefaultType(elementType), context);
        }
    }
    assert compileTimeConstant != null : "CompileTimeConstant should be evaluated for constant expression or an error should be recorded " + expression.getText();
    return components.dataFlowAnalyzer.createCompileTimeConstantTypeInfo(compileTimeConstant, expression, context);
}
Also used : IElementType(com.intellij.psi.tree.IElementType)

Example 77 with IElementType

use of com.intellij.psi.tree.IElementType in project kotlin by JetBrains.

the class BasicExpressionTypingVisitor method establishSubtypingForTypeRHS.

@NotNull
private static DataFlowInfo establishSubtypingForTypeRHS(@NotNull KtBinaryExpressionWithTypeRHS left, @NotNull DataFlowInfo dataFlowInfo, @NotNull ExpressionTypingContext context, @NotNull LanguageVersionSettings languageVersionSettings) {
    IElementType operationType = left.getOperationReference().getReferencedNameElementType();
    if (operationType == AS_SAFE) {
        KtExpression underSafeAs = left.getLeft();
        KotlinType underSafeAsType = context.trace.getType(underSafeAs);
        if (underSafeAsType != null) {
            DataFlowValue underSafeAsValue = createDataFlowValue(underSafeAs, underSafeAsType, context);
            KotlinType targetType = context.trace.get(BindingContext.TYPE, left.getRight());
            if (targetType != null) {
                return dataFlowInfo.establishSubtyping(underSafeAsValue, targetType, languageVersionSettings);
            }
        }
    }
    return dataFlowInfo;
}
Also used : IElementType(com.intellij.psi.tree.IElementType) DataFlowValue(org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue) DataFlowValueFactory.createDataFlowValue(org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory.createDataFlowValue) NotNull(org.jetbrains.annotations.NotNull)

Example 78 with IElementType

use of com.intellij.psi.tree.IElementType in project kotlin by JetBrains.

the class BasicExpressionTypingVisitor method checkLValue.

/**
     * @return {@code true} iff expression can be assigned to
     */
public boolean checkLValue(@NotNull BindingTrace trace, @NotNull ExpressionTypingContext context, @NotNull KtExpression expressionWithParenthesis, @Nullable KtExpression rightHandSide, @NotNull KtOperationExpression operationExpression) {
    KtExpression expression = KtPsiUtil.deparenthesize(expressionWithParenthesis);
    if (expression instanceof KtArrayAccessExpression) {
        KtArrayAccessExpression arrayAccessExpression = (KtArrayAccessExpression) expression;
        KtExpression arrayExpression = arrayAccessExpression.getArrayExpression();
        if (arrayExpression == null || rightHandSide == null)
            return false;
        TemporaryBindingTrace ignoreReportsTrace = TemporaryBindingTrace.create(trace, "Trace for checking set function");
        ExpressionTypingContext findSetterContext = context.replaceBindingTrace(ignoreReportsTrace);
        KotlinTypeInfo info = resolveArrayAccessSetMethod(arrayAccessExpression, rightHandSide, findSetterContext, ignoreReportsTrace);
        IElementType operationType = operationExpression.getOperationReference().getReferencedNameElementType();
        if (KtTokens.AUGMENTED_ASSIGNMENTS.contains(operationType) || operationType == KtTokens.PLUSPLUS || operationType == KtTokens.MINUSMINUS) {
            ResolvedCall<?> resolvedCall = ignoreReportsTrace.get(INDEXED_LVALUE_SET, expression);
            if (resolvedCall != null && trace.wantsDiagnostics()) {
                // Call must be validated with the actual, not temporary trace in order to report operator diagnostic
                // Only unary assignment expressions (++, --) and +=/... must be checked, normal assignments have the proper trace
                CallCheckerContext callCheckerContext = new CallCheckerContext(context, trace, components.languageVersionSettings);
                for (CallChecker checker : components.callCheckers) {
                    checker.check(resolvedCall, expression, callCheckerContext);
                }
            }
        }
        return info.getType() != null;
    }
    VariableDescriptor variable = BindingContextUtils.extractVariableDescriptorFromReference(trace.getBindingContext(), expression);
    boolean result = true;
    KtExpression reportOn = expression != null ? expression : expressionWithParenthesis;
    if (reportOn instanceof KtQualifiedExpression) {
        KtExpression selector = ((KtQualifiedExpression) reportOn).getSelectorExpression();
        if (selector != null)
            reportOn = selector;
    }
    if (variable instanceof PropertyDescriptor) {
        PropertyDescriptor propertyDescriptor = (PropertyDescriptor) variable;
        PropertySetterDescriptor setter = propertyDescriptor.getSetter();
        if (propertyDescriptor.isSetterProjectedOut()) {
            trace.report(SETTER_PROJECTED_OUT.on(reportOn, propertyDescriptor));
            result = false;
        } else if (setter != null) {
            ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCall(expressionWithParenthesis, context.trace.getBindingContext());
            assert resolvedCall != null : "Call is not resolved for property setter: " + PsiUtilsKt.getElementTextWithContext(expressionWithParenthesis);
            checkPropertySetterCall(context.replaceBindingTrace(trace), setter, resolvedCall, reportOn);
        }
    }
    if (variable == null) {
        trace.report(VARIABLE_EXPECTED.on(reportOn));
        result = false;
    } else if (!variable.isVar()) {
        result = false;
    }
    return result;
}
Also used : IElementType(com.intellij.psi.tree.IElementType) ResolvedCall(org.jetbrains.kotlin.resolve.calls.model.ResolvedCall)

Example 79 with IElementType

use of com.intellij.psi.tree.IElementType in project kotlin by JetBrains.

the class BasicExpressionTypingVisitor method visitUnaryExpression.

@Override
public KotlinTypeInfo visitUnaryExpression(@NotNull KtUnaryExpression expression, ExpressionTypingContext contextWithExpectedType) {
    ExpressionTypingContext context = isUnaryExpressionDependentOnExpectedType(expression) ? contextWithExpectedType : contextWithExpectedType.replaceContextDependency(INDEPENDENT).replaceExpectedType(NO_EXPECTED_TYPE);
    KtExpression baseExpression = expression.getBaseExpression();
    if (baseExpression == null)
        return TypeInfoFactoryKt.noTypeInfo(context);
    KtSimpleNameExpression operationSign = expression.getOperationReference();
    IElementType operationType = operationSign.getReferencedNameElementType();
    // Special case for expr!!
    if (operationType == KtTokens.EXCLEXCL) {
        return visitExclExclExpression(expression, context);
    }
    // Type check the base expression
    KotlinTypeInfo typeInfo = facade.safeGetTypeInfo(baseExpression, context);
    KotlinType type = ExpressionTypingUtils.safeGetType(typeInfo);
    ExpressionReceiver receiver = ExpressionReceiver.Companion.create(baseExpression, type, context.trace.getBindingContext());
    Call call = CallMaker.makeCall(receiver, expression);
    // Conventions for unary operations
    Name name = OperatorConventions.UNARY_OPERATION_NAMES.get(operationType);
    if (name == null) {
        context.trace.report(UNSUPPORTED.on(operationSign, "visitUnaryExpression"));
        return typeInfo.clearType();
    }
    // a[i]++/-- takes special treatment because it is actually let j = i, arr = a in arr.set(j, a.get(j).inc())
    if ((operationType == KtTokens.PLUSPLUS || operationType == KtTokens.MINUSMINUS) && baseExpression instanceof KtArrayAccessExpression) {
        KtExpression stubExpression = ExpressionTypingUtils.createFakeExpressionOfType(baseExpression.getProject(), context.trace, "e", type);
        TemporaryBindingTrace temporaryBindingTrace = TemporaryBindingTrace.create(context.trace, "trace to resolve array access set method for unary expression", expression);
        ExpressionTypingContext newContext = context.replaceBindingTrace(temporaryBindingTrace);
        resolveImplicitArrayAccessSetMethod((KtArrayAccessExpression) baseExpression, stubExpression, newContext, context.trace);
    }
    // Resolve the operation reference
    OverloadResolutionResults<FunctionDescriptor> resolutionResults = components.callResolver.resolveCallWithGivenName(context, call, expression.getOperationReference(), name);
    if (!resolutionResults.isSuccess()) {
        return typeInfo.clearType();
    }
    // Computing the return type
    KotlinType returnType = resolutionResults.getResultingDescriptor().getReturnType();
    KotlinType result;
    if (operationType == KtTokens.PLUSPLUS || operationType == KtTokens.MINUSMINUS) {
        assert returnType != null : "returnType is null for " + resolutionResults.getResultingDescriptor();
        if (KotlinBuiltIns.isUnit(returnType)) {
            result = ErrorUtils.createErrorType(components.builtIns.getUnit().getName().asString());
            context.trace.report(INC_DEC_SHOULD_NOT_RETURN_UNIT.on(operationSign));
        } else {
            KotlinType receiverType = receiver.getType();
            if (!KotlinTypeChecker.DEFAULT.isSubtypeOf(returnType, receiverType)) {
                context.trace.report(RESULT_TYPE_MISMATCH.on(operationSign, name.asString(), receiverType, returnType));
            } else {
                context.trace.record(BindingContext.VARIABLE_REASSIGNMENT, expression);
                KtExpression stubExpression = ExpressionTypingUtils.createFakeExpressionOfType(baseExpression.getProject(), context.trace, "e", type);
                checkLValue(context.trace, context, baseExpression, stubExpression, expression);
            }
            // x++ type is x type, but ++x type is x.inc() type
            DataFlowValue receiverValue = DataFlowValueFactory.createDataFlowValue((ReceiverValue) call.getExplicitReceiver(), contextWithExpectedType);
            if (expression instanceof KtPrefixExpression) {
                result = returnType;
            } else {
                result = receiverType;
                // Also record data flow information for x++ value (= x)
                DataFlowValue returnValue = DataFlowValueFactory.createDataFlowValue(expression, receiverType, contextWithExpectedType);
                typeInfo = typeInfo.replaceDataFlowInfo(typeInfo.getDataFlowInfo().assign(returnValue, receiverValue, components.languageVersionSettings));
            }
        }
    } else {
        result = returnType;
    }
    CompileTimeConstant<?> value = components.constantExpressionEvaluator.evaluateExpression(expression, contextWithExpectedType.trace, contextWithExpectedType.expectedType);
    if (value != null) {
        return components.dataFlowAnalyzer.createCompileTimeConstantTypeInfo(value, expression, contextWithExpectedType);
    }
    return components.dataFlowAnalyzer.checkType(typeInfo.replaceType(result), expression, contextWithExpectedType.replaceDataFlowInfo(typeInfo.getDataFlowInfo()));
}
Also used : ResolvedCall(org.jetbrains.kotlin.resolve.calls.model.ResolvedCall) DataFlowValue(org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue) DataFlowValueFactory.createDataFlowValue(org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory.createDataFlowValue) Name(org.jetbrains.kotlin.name.Name) IElementType(com.intellij.psi.tree.IElementType) ExpressionReceiver(org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver)

Example 80 with IElementType

use of com.intellij.psi.tree.IElementType in project kotlin by JetBrains.

the class BasicExpressionTypingVisitor method checkBinaryWithTypeRHS.

private void checkBinaryWithTypeRHS(@NotNull KtBinaryExpressionWithTypeRHS expression, @NotNull ExpressionTypingContext context, @NotNull KotlinType targetType, @Nullable KotlinType actualType) {
    if (actualType == null)
        return;
    KtSimpleNameExpression operationSign = expression.getOperationReference();
    IElementType operationType = operationSign.getReferencedNameElementType();
    if (operationType != KtTokens.AS_KEYWORD && operationType != KtTokens.AS_SAFE) {
        context.trace.report(UNSUPPORTED.on(operationSign, "binary operation with type RHS"));
        return;
    }
    checkForCastImpossibilityOrRedundancy(expression, actualType, targetType, context);
}
Also used : IElementType(com.intellij.psi.tree.IElementType)

Aggregations

IElementType (com.intellij.psi.tree.IElementType)843 ASTNode (com.intellij.lang.ASTNode)127 PsiBuilder (com.intellij.lang.PsiBuilder)121 Nullable (org.jetbrains.annotations.Nullable)100 NotNull (org.jetbrains.annotations.NotNull)78 PsiElement (com.intellij.psi.PsiElement)77 TextRange (com.intellij.openapi.util.TextRange)43 HighlighterIterator (com.intellij.openapi.editor.highlighter.HighlighterIterator)26 ArrayList (java.util.ArrayList)22 GrExpression (org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression)22 Lexer (com.intellij.lexer.Lexer)17 GrBinaryExpression (org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrBinaryExpression)15 NonNls (org.jetbrains.annotations.NonNls)14 Document (com.intellij.openapi.editor.Document)13 PsiWhiteSpace (com.intellij.psi.PsiWhiteSpace)13 LighterASTNode (com.intellij.lang.LighterASTNode)12 BracePair (com.intellij.lang.BracePair)10 Project (com.intellij.openapi.project.Project)9 PsiFile (com.intellij.psi.PsiFile)9 IncorrectOperationException (com.intellij.util.IncorrectOperationException)9