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);
}
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;
}
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;
}
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()));
}
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);
}
Aggregations