@Override public StackValue visitLabeledExpression( @NotNull KtLabeledExpression expression, StackValue receiver) { KtExpression baseExpression = expression.getBaseExpression(); assert baseExpression != null : "Label expression should have base one: " + expression.getText(); return baseExpression.accept(this, receiver); }
@Override public void invoke(@NotNull Project project, Editor editor, KtFile file) throws IncorrectOperationException { if (getElement() instanceof KtBinaryExpressionWithTypeRHS) { KtExpression left = ((KtBinaryExpressionWithTypeRHS) getElement()).getLeft(); KtTypeReference right = ((KtBinaryExpressionWithTypeRHS) getElement()).getRight(); if (right != null) { KtExpression expression = KtPsiFactoryKt.KtPsiFactory(file) .createExpression(left.getText() + operation + right.getText()); getElement().replace(expression); } } }
@NotNull private static KtBinaryExpression createVariableAssignment(@NotNull KtProperty property) { String propertyName = property.getName(); assert propertyName != null : "Property should have a name " + property.getText(); KtBinaryExpression assignment = (KtBinaryExpression) KtPsiFactoryKt.KtPsiFactory(property).createExpression(propertyName + " = x"); KtExpression right = assignment.getRight(); assert right != null : "Created binary expression should have a right part " + assignment.getText(); KtExpression initializer = property.getInitializer(); assert initializer != null : "Initializer should exist for property " + property.getText(); right.replace(initializer); return assignment; }
@Nullable public static KtExpression getParentCallIfPresent(@NotNull KtExpression expression) { PsiElement parent = expression.getParent(); while (parent != null) { if (parent instanceof KtBinaryExpression || parent instanceof KtUnaryExpression || parent instanceof KtLabeledExpression || parent instanceof KtDotQualifiedExpression || parent instanceof KtCallExpression || parent instanceof KtArrayAccessExpression || parent instanceof KtDestructuringDeclaration) { if (parent instanceof KtLabeledExpression) { parent = parent.getParent(); continue; } // check that it's in inlineable call would be in resolve call of parent return (KtExpression) parent; } else if (parent instanceof KtParenthesizedExpression || parent instanceof KtBinaryExpressionWithTypeRHS) { parent = parent.getParent(); } else if (parent instanceof KtValueArgument || parent instanceof KtValueArgumentList) { parent = parent.getParent(); } else if (parent instanceof KtLambdaExpression || parent instanceof KtAnnotatedExpression) { parent = parent.getParent(); } else { return null; } } return null; }
@NotNull public KotlinType safeGetType( @NotNull LexicalScope scope, @NotNull KtExpression expression, @NotNull KotlinType expectedType, @NotNull DataFlowInfo dataFlowInfo, @NotNull BindingTrace trace) { KotlinType type = getType(scope, expression, expectedType, dataFlowInfo, trace); return type != null ? type : ErrorUtils.createErrorType("Type for " + expression.getText()); }
/** * Visits block statements propagating data flow information from the first to the last. * Determines block returned type and data flow information at the end of the block AND at the * nearest jump point from the block beginning. */ /*package*/ KotlinTypeInfo getBlockReturnedTypeWithWritableScope( @NotNull LexicalWritableScope scope, @NotNull List<? extends KtElement> block, @NotNull CoercionStrategy coercionStrategyForLastExpression, @NotNull ExpressionTypingContext context) { if (block.isEmpty()) { return TypeInfoFactoryKt.createTypeInfo( expressionTypingComponents.builtIns.getUnitType(), context); } ExpressionTypingInternals blockLevelVisitor = new ExpressionTypingVisitorDispatcher.ForBlock( expressionTypingComponents, annotationChecker, scope); ExpressionTypingContext newContext = context.replaceScope(scope).replaceExpectedType(NO_EXPECTED_TYPE); KotlinTypeInfo result = TypeInfoFactoryKt.noTypeInfo(context); // Jump point data flow info DataFlowInfo beforeJumpInfo = newContext.dataFlowInfo; boolean jumpOutPossible = false; for (Iterator<? extends KtElement> iterator = block.iterator(); iterator.hasNext(); ) { KtElement statement = iterator.next(); if (!(statement instanceof KtExpression)) { continue; } KtExpression statementExpression = (KtExpression) statement; if (!iterator.hasNext()) { result = getTypeOfLastExpressionInBlock( statementExpression, newContext.replaceExpectedType(context.expectedType), coercionStrategyForLastExpression, blockLevelVisitor); if (result.getType() != null && statementExpression.getParent() instanceof KtBlockExpression) { DataFlowValue lastExpressionValue = DataFlowValueFactory.createDataFlowValue( statementExpression, result.getType(), context); DataFlowValue blockExpressionValue = DataFlowValueFactory.createDataFlowValue( (KtBlockExpression) statementExpression.getParent(), result.getType(), context); result = result.replaceDataFlowInfo( result.getDataFlowInfo().assign(blockExpressionValue, lastExpressionValue)); } } else { result = blockLevelVisitor.getTypeInfo( statementExpression, newContext.replaceContextDependency(ContextDependency.INDEPENDENT), true); } DataFlowInfo newDataFlowInfo = result.getDataFlowInfo(); // If jump is not possible, we take new data flow info before jump if (!jumpOutPossible) { beforeJumpInfo = result.getJumpFlowInfo(); jumpOutPossible = result.getJumpOutPossible(); } if (newDataFlowInfo != context.dataFlowInfo) { newContext = newContext.replaceDataFlowInfo(newDataFlowInfo); // We take current data flow info if jump there is not possible } blockLevelVisitor = new ExpressionTypingVisitorDispatcher.ForBlock( expressionTypingComponents, annotationChecker, scope); } return result.replaceJumpOutPossible(jumpOutPossible).replaceJumpFlowInfo(beforeJumpInfo); }
public static boolean areParenthesesNecessary( @NotNull KtExpression innerExpression, @NotNull KtExpression currentInner, @NotNull KtElement parentElement) { if (parentElement instanceof KtParenthesizedExpression || innerExpression instanceof KtParenthesizedExpression) { return false; } if (parentElement instanceof KtPackageDirective) return false; if (parentElement instanceof KtWhenExpression || innerExpression instanceof KtWhenExpression) { return false; } if (innerExpression instanceof KtIfExpression) { if (parentElement instanceof KtQualifiedExpression) return true; PsiElement current = parentElement; while (!(current instanceof KtBlockExpression || current instanceof KtDeclaration || current instanceof KtStatementExpression || current instanceof KtFile)) { if (current.getTextRange().getEndOffset() != currentInner.getTextRange().getEndOffset()) { return !(current instanceof KtParenthesizedExpression) && !(current instanceof KtValueArgumentList); // if current expression is "guarded" by parenthesis, no // extra parenthesis is necessary } current = current.getParent(); } } if (parentElement instanceof KtCallExpression && currentInner == ((KtCallExpression) parentElement).getCalleeExpression()) { if (innerExpression instanceof KtSimpleNameExpression) return false; if (KtPsiUtilKt.getQualifiedExpressionForSelector(parentElement) != null) return true; return !(innerExpression instanceof KtThisExpression || innerExpression instanceof KtArrayAccessExpression || innerExpression instanceof KtConstantExpression || innerExpression instanceof KtStringTemplateExpression || innerExpression instanceof KtCallExpression); } if (parentElement instanceof KtValueArgument) { // a(___, d > (e + f)) => a((b < c), d > (e + f)) to prevent parsing < c, d > as type argument // list KtValueArgument nextArg = PsiTreeUtil.getNextSiblingOfType(parentElement, KtValueArgument.class); PsiElement nextExpression = nextArg != null ? nextArg.getArgumentExpression() : null; if (innerExpression instanceof KtBinaryExpression && ((KtBinaryExpression) innerExpression).getOperationToken() == KtTokens.LT && nextExpression instanceof KtBinaryExpression && ((KtBinaryExpression) nextExpression).getOperationToken() == KtTokens.GT) return true; } if (!(parentElement instanceof KtExpression)) return false; IElementType innerOperation = getOperation(innerExpression); IElementType parentOperation = getOperation((KtExpression) parentElement); // 'return (@label{...})' case if (parentElement instanceof KtReturnExpression && (innerExpression instanceof KtLabeledExpression || innerExpression instanceof KtAnnotatedExpression)) return true; // '(x: Int) < y' case if (innerExpression instanceof KtBinaryExpressionWithTypeRHS && parentOperation == KtTokens.LT) { return true; } if (parentElement instanceof KtLabeledExpression) return false; // 'x ?: ...' case if (parentElement instanceof KtBinaryExpression && parentOperation == KtTokens.ELVIS && currentInner == ((KtBinaryExpression) parentElement).getRight()) { return false; } int innerPriority = getPriority(innerExpression); int parentPriority = getPriority((KtExpression) parentElement); if (innerPriority == parentPriority) { if (parentElement instanceof KtBinaryExpression) { if (innerOperation == KtTokens.ANDAND || innerOperation == KtTokens.OROR) { return false; } return ((KtBinaryExpression) parentElement).getRight() == currentInner; } // '-(-x)' case if (parentElement instanceof KtPrefixExpression && innerExpression instanceof KtPrefixExpression) { return innerOperation == parentOperation && (innerOperation == KtTokens.PLUS || innerOperation == KtTokens.MINUS); } return false; } return innerPriority < parentPriority; }
private static boolean isBooleanConstant(@Nullable KtExpression condition) { return condition != null && condition.getNode().getElementType() == KtNodeTypes.BOOLEAN_CONSTANT; }
public static boolean isFalseConstant(@Nullable KtExpression condition) { return isBooleanConstant(condition) && condition.getNode().findChildByType(KtTokens.FALSE_KEYWORD) != null; }
public static boolean isNullConstant(@NotNull KtExpression expression) { KtExpression deparenthesized = deparenthesize(expression); return deparenthesized instanceof KtConstantExpression && deparenthesized.getNode().getElementType() == KtNodeTypes.NULL; }
public static boolean isLHSOfDot(@NotNull KtExpression expression) { PsiElement parent = expression.getParent(); if (!(parent instanceof KtQualifiedExpression)) return false; KtQualifiedExpression qualifiedParent = (KtQualifiedExpression) parent; return qualifiedParent.getReceiverExpression() == expression || isLHSOfDot(qualifiedParent); }