PSI getter fixed: left-hand side of a binary expression can now be null

EA-35976 - IAE: FqNameUnsafe.validateFqName
This commit is contained in:
Andrey Breslav
2013-04-18 15:48:50 +04:00
parent c69e7f059d
commit 140382e280
14 changed files with 246 additions and 31 deletions
@@ -38,11 +38,18 @@ public class JetBinaryExpression extends JetExpressionImpl implements JetOperati
return visitor.visitBinaryExpression(this, data);
}
@NotNull
@Nullable @IfNotParsed
public JetExpression getLeft() {
JetExpression left = findChildByClass(JetExpression.class);
assert left != null;
return left;
ASTNode node = getOperationReference().getNode().getTreePrev();
while (node != null) {
PsiElement psi = node.getPsi();
if (psi instanceof JetExpression) {
return (JetExpression) psi;
}
node = node.getTreePrev();
}
return null;
}
@Nullable @IfNotParsed
@@ -175,9 +175,10 @@ public class TracingStrategyImpl implements TracingStrategy {
Name.identifier(operationReference.getText()) :
OperatorConventions.getNameForOperationSymbol((JetToken) operationReference.getReferencedNameElementType());
JetExpression left = binaryExpression.getLeft();
JetExpression right = binaryExpression.getRight();
if (right != null) {
trace.report(UNSAFE_INFIX_CALL.on(reference, binaryExpression.getLeft().getText(), operationString.getName(), right.getText()));
if (left != null && right != null) {
trace.report(UNSAFE_INFIX_CALL.on(reference, left.getText(), operationString.getName(), right.getText()));
}
}
else {
@@ -36,6 +36,7 @@ import org.jetbrains.jet.lang.resolve.calls.context.ExpressionPosition;
import org.jetbrains.jet.lang.resolve.calls.context.ResolutionResultsCache;
import org.jetbrains.jet.lang.resolve.calls.context.ResolveMode;
import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults;
import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsImpl;
import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResultsUtil;
import org.jetbrains.jet.lang.resolve.calls.util.CallMaker;
import org.jetbrains.jet.lang.resolve.constants.*;
@@ -753,8 +754,13 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
JetExpression right = expression.getRight();
IElementType operationType = operationSign.getReferencedNameElementType();
JetTypeInfo leftTypeInfo = left != null
? facade.getTypeInfo(left, context)
: JetTypeInfo.create(null, context.dataFlowInfo);
JetType result = null;
DataFlowInfo dataFlowInfo = context.dataFlowInfo;
if (operationType == JetTokens.IDENTIFIER) {
Name referencedName = operationSign.getReferencedNameAsName();
JetTypeInfo typeInfo = getTypeInfoForBinaryCall(context.scope, referencedName, context, expression);
@@ -792,10 +798,10 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
else {
JetType booleanType = KotlinBuiltIns.getInstance().getBooleanType();
if (OperatorConventions.EQUALS_OPERATIONS.contains(operationType)) {
if (right != null) {
if (right != null && left != null) {
ExpressionReceiver receiver = ExpressionTypingUtils.safeGetExpressionReceiver(facade, left, context);
dataFlowInfo = facade.getTypeInfo(left, context).getDataFlowInfo();
dataFlowInfo = leftTypeInfo.getDataFlowInfo();
ExpressionTypingContext contextWithDataFlow = context.replaceDataFlowInfo(dataFlowInfo);
OverloadResolutionResults<FunctionDescriptor> resolutionResults = resolveFakeCall(
@@ -830,7 +836,6 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
}
else if (OperatorConventions.IN_OPERATIONS.contains(operationType)) {
if (right == null) {
result = ErrorUtils.createErrorType("No right argument"); // TODO
return JetTypeInfo.create(null, dataFlowInfo);
}
JetTypeInfo typeInfo = checkInExpression(expression, expression.getOperationReference(), left, right, context);
@@ -838,7 +843,6 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
result = typeInfo.getType();
}
else if (OperatorConventions.BOOLEAN_OPERATIONS.containsKey(operationType)) {
JetTypeInfo leftTypeInfo = facade.getTypeInfo(left, context);
JetType leftType = leftTypeInfo.getType();
dataFlowInfo = leftTypeInfo.getDataFlowInfo();
@@ -852,7 +856,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
JetType rightType = right == null
? null
: facade.getTypeInfo(right, context.replaceDataFlowInfo(flowInfoLeft).replaceScope(rightScope)).getType();
if (leftType != null && !isBoolean(leftType)) {
if (left != null && leftType != null && !isBoolean(leftType)) {
context.trace.report(TYPE_MISMATCH.on(left, booleanType, leftType));
}
if (rightType != null && !isBoolean(rightType)) {
@@ -861,11 +865,10 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
result = booleanType;
}
else if (operationType == JetTokens.ELVIS) {
JetTypeInfo leftTypeInfo = facade.getTypeInfo(left, context);
JetType leftType = leftTypeInfo.getType();
dataFlowInfo = leftTypeInfo.getDataFlowInfo();
if (leftType != null) {
if (left != null && leftType != null) {
if (isKnownToBeNotNull(left, leftType, context)) {
context.trace.report(USELESS_ELVIS.on(left, leftType));
}
@@ -918,6 +921,8 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
private void ensureNonemptyIntersectionOfOperandTypes(JetBinaryExpression expression, ExpressionTypingContext context) {
JetExpression left = expression.getLeft();
if (left == null) return;
JetExpression right = expression.getRight();
// TODO : duplicated effort for == and !=
@@ -994,12 +999,20 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
) {
ExpressionTypingContext context = contextWithOldScope.replaceScope(scope);
JetExpression left = binaryExpression.getLeft();
DataFlowInfo dataFlowInfo = facade.getTypeInfo(left, context).getDataFlowInfo();
ExpressionReceiver receiver = safeGetExpressionReceiver(facade, left, context);
DataFlowInfo dataFlowInfo = context.dataFlowInfo;
if (left != null) {
dataFlowInfo = facade.getTypeInfo(left, context).getDataFlowInfo();
}
ExpressionTypingContext contextWithDataFlow = context.replaceDataFlowInfo(dataFlowInfo);
OverloadResolutionResults<FunctionDescriptor> resolutionResults =
getResolutionResultsForBinaryCall(scope, name, contextWithDataFlow, binaryExpression, receiver);
OverloadResolutionResults<FunctionDescriptor> resolutionResults;
if (left != null) {
ExpressionReceiver receiver = safeGetExpressionReceiver(facade, left, context);
resolutionResults = getResolutionResultsForBinaryCall(scope, name, contextWithDataFlow, binaryExpression, receiver);
}
else {
resolutionResults = OverloadResolutionResultsImpl.nameNotFound();
}
JetExpression right = binaryExpression.getRight();
if (right != null) {
@@ -73,6 +73,7 @@ public class DataFlowUtils {
}
else {
JetExpression left = expression.getLeft();
if (left == null) return;
JetExpression right = expression.getRight();
if (right == null) return;
@@ -85,6 +85,7 @@ public class ExpressionTypingVisitorDispatcher extends JetVisitor<JetTypeInfo, E
return getTypeInfo(expression, context, this);
}
@Override
@NotNull
public final JetTypeInfo getTypeInfo(@NotNull JetExpression expression, ExpressionTypingContext context, boolean isStatement) {
if (!isStatement) return getTypeInfo(expression, context);
@@ -208,12 +208,15 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
JetSimpleNameExpression operationSign = expression.getOperationReference();
IElementType operationType = operationSign.getReferencedNameElementType();
JetTypeInfo leftInfo = facade.getTypeInfo(expression.getLeft(), context);
JetExpression leftOperand = expression.getLeft();
JetTypeInfo leftInfo = leftOperand != null
? facade.getTypeInfo(leftOperand, context)
: JetTypeInfo.create(null, context.dataFlowInfo);
JetType leftType = leftInfo.getType();
DataFlowInfo dataFlowInfo = leftInfo.getDataFlowInfo();
JetExpression right = expression.getRight();
JetExpression left = JetPsiUtil.deparenthesizeWithNoTypeResolution(expression.getLeft());
JetExpression left = leftOperand == null ? null : JetPsiUtil.deparenthesizeWithNoTypeResolution(leftOperand);
if (right == null || left == null) {
temporaryBindingTrace.commit();
return JetTypeInfo.create(null, dataFlowInfo);
@@ -271,7 +274,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
basic.resolveArrayAccessSetMethod((JetArrayAccessExpression) left, right, contextForResolve, context.trace);
}
dataFlowInfo = facade.getTypeInfo(right, context.replaceDataFlowInfo(dataFlowInfo)).getDataFlowInfo();
BasicExpressionTypingVisitor.checkLValue(context.trace, expression.getLeft());
BasicExpressionTypingVisitor.checkLValue(context.trace, leftOperand);
}
temporaryBindingTrace.commit();
return JetTypeInfo.create(checkAssignmentType(type, expression, contextWithExpectedType), dataFlowInfo);
@@ -280,7 +283,8 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
@NotNull
protected JetTypeInfo visitAssignment(JetBinaryExpression expression, ExpressionTypingContext contextWithExpectedType) {
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE).replaceScope(scope);
JetExpression left = context.expressionTypingServices.deparenthesize(expression.getLeft(), context);
JetExpression leftOperand = expression.getLeft();
JetExpression left = leftOperand == null ? null : context.expressionTypingServices.deparenthesize(leftOperand, context);
JetExpression right = expression.getRight();
if (left instanceof JetArrayAccessExpression) {
JetArrayAccessExpression arrayAccessExpression = (JetArrayAccessExpression) left;
@@ -290,15 +294,17 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
return JetTypeInfo.create(checkAssignmentType(typeInfo.getType(), expression, contextWithExpectedType),
typeInfo.getDataFlowInfo());
}
JetTypeInfo leftInfo = facade.getTypeInfo(expression.getLeft(), context);
JetTypeInfo leftInfo = leftOperand != null
? facade.getTypeInfo(leftOperand, context)
: JetTypeInfo.create(null, context.dataFlowInfo);
JetType leftType = leftInfo.getType();
DataFlowInfo dataFlowInfo = leftInfo.getDataFlowInfo();
if (right != null) {
JetTypeInfo rightInfo = facade.getTypeInfo(right, context.replaceDataFlowInfo(dataFlowInfo).replaceExpectedType(leftType));
dataFlowInfo = rightInfo.getDataFlowInfo();
}
if (leftType != null) { //if leftType == null, some another error has been generated
BasicExpressionTypingVisitor.checkLValue(context.trace, expression.getLeft());
if (leftType != null && leftOperand != null) { //if leftType == null, some other error has been generated
BasicExpressionTypingVisitor.checkLValue(context.trace, leftOperand);
}
return DataFlowUtils.checkStatementType(expression, contextWithExpectedType, dataFlowInfo);
}
@@ -0,0 +1,15 @@
fun import() {
<!FUNCTION_CALL_EXPECTED!>import<!> <!UNRESOLVED_REFERENCE!>a<!><!SYNTAX!>.<!><!DEBUG_INFO_MISSING_UNRESOLVED!>*<!><!SYNTAX!><!>
}
fun composite() {
val <!UNUSED_VARIABLE!>s<!> = 13+<!SYNTAX!>~<!><!DEBUG_INFO_MISSING_UNRESOLVED!>/<!>12
}
fun html() {
<!SYNTAX!><<!><!FUNCTION_CALL_EXPECTED!>html<!><!UNRESOLVED_REFERENCE!>><!><!SYNTAX!><<!><!DEBUG_INFO_MISSING_UNRESOLVED!>/<!><!FUNCTION_CALL_EXPECTED!>html<!><!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>><!><!SYNTAX!><!>
}
fun html1() {
<!SYNTAX!><<!><!FUNCTION_CALL_EXPECTED!>html<!><!UNRESOLVED_REFERENCE!>><!><!SYNTAX!><<!><!DEBUG_INFO_MISSING_UNRESOLVED!>/<!><!FUNCTION_CALL_EXPECTED!>html<!><!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>><!><!FUNCTION_CALL_EXPECTED!>html<!>
}
@@ -0,0 +1,15 @@
fun import() {
import a.*
}
fun composite() {
val s = 13+~/12
}
fun html() {
<html></html>
}
fun html1() {
<html></html>html
}
@@ -0,0 +1,128 @@
JetFile: AbsentLeftHandSide.kt
NAMESPACE_HEADER
<empty list>
FUN
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('import')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
BLOCK
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
BINARY_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('import')
PsiWhiteSpace(' ')
OPERATION_REFERENCE
PsiElement(IDENTIFIER)('a')
BINARY_EXPRESSION
PsiErrorElement:Expecting an element
PsiElement(DOT)('.')
OPERATION_REFERENCE
PsiElement(MUL)('*')
PsiErrorElement:Expecting an element
<empty list>
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n')
FUN
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('composite')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
BLOCK
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
PROPERTY
PsiElement(val)('val')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('s')
PsiWhiteSpace(' ')
PsiElement(EQ)('=')
PsiWhiteSpace(' ')
BINARY_EXPRESSION
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('13')
OPERATION_REFERENCE
PsiElement(PLUS)('+')
BINARY_EXPRESSION
PsiErrorElement:Expecting an element
PsiElement(BAD_CHARACTER)('~')
OPERATION_REFERENCE
PsiElement(DIV)('/')
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('12')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n')
FUN
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('html')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
BLOCK
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
PsiErrorElement:Expecting an element
PsiElement(LT)('<')
BINARY_EXPRESSION
BINARY_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('html')
OPERATION_REFERENCE
PsiElement(GT)('>')
BINARY_EXPRESSION
PsiErrorElement:Expecting an element
PsiElement(LT)('<')
OPERATION_REFERENCE
PsiElement(DIV)('/')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('html')
OPERATION_REFERENCE
PsiElement(GT)('>')
PsiErrorElement:Expecting an element
<empty list>
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n')
FUN
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('html1')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
BLOCK
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
PsiErrorElement:Expecting an element
PsiElement(LT)('<')
BINARY_EXPRESSION
BINARY_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('html')
OPERATION_REFERENCE
PsiElement(GT)('>')
BINARY_EXPRESSION
PsiErrorElement:Expecting an element
PsiElement(LT)('<')
OPERATION_REFERENCE
PsiElement(DIV)('/')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('html')
OPERATION_REFERENCE
PsiElement(GT)('>')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('html')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
@@ -33,7 +33,7 @@ import org.jetbrains.jet.checkers.AbstractDiagnosticsTestWithEagerResolve;
@InnerTestClasses({JetDiagnosticsTestGenerated.Tests.class, JetDiagnosticsTestGenerated.Script.class})
public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEagerResolve {
@TestMetadata("compiler/testData/diagnostics/tests")
@InnerTestClasses({Tests.Annotations.class, Tests.BackingField.class, Tests.Cast.class, Tests.CheckArguments.class, Tests.ControlFlowAnalysis.class, Tests.ControlStructures.class, Tests.DataClasses.class, Tests.DataFlow.class, Tests.DataFlowInfoTraversal.class, Tests.DeclarationChecks.class, Tests.Deparenthesize.class, Tests.Enum.class, Tests.Extensions.class, Tests.FunctionLiterals.class, Tests.Generics.class, Tests.IncompleteCode.class, Tests.Inference.class, Tests.Infos.class, Tests.Inner.class, Tests.J_k.class, Tests.Jdk_annotations.class, Tests.Library.class, Tests.NullabilityAndAutoCasts.class, Tests.NullableTypes.class, Tests.Objects.class, Tests.OperatorsOverloading.class, Tests.Overload.class, Tests.Override.class, Tests.Redeclarations.class, Tests.Regressions.class, Tests.Resolve.class, Tests.Scopes.class, Tests.SenselessComparison.class, Tests.Shadowing.class, Tests.SmartCasts.class, Tests.Substitutions.class, Tests.Subtyping.class, Tests.ThisAndSuper.class, Tests.Varargs.class})
@InnerTestClasses({Tests.Annotations.class, Tests.BackingField.class, Tests.Cast.class, Tests.CheckArguments.class, Tests.ControlFlowAnalysis.class, Tests.ControlStructures.class, Tests.DataClasses.class, Tests.DataFlow.class, Tests.DataFlowInfoTraversal.class, Tests.DeclarationChecks.class, Tests.Deparenthesize.class, Tests.Enum.class, Tests.Extensions.class, Tests.FunctionLiterals.class, Tests.Generics.class, Tests.IncompleteCode.class, Tests.Inference.class, Tests.Infos.class, Tests.Inner.class, Tests.J_k.class, Tests.Jdk_annotations.class, Tests.Library.class, Tests.NullabilityAndAutoCasts.class, Tests.NullableTypes.class, Tests.Objects.class, Tests.OperatorsOverloading.class, Tests.Overload.class, Tests.Override.class, Tests.Recovery.class, Tests.Redeclarations.class, Tests.Regressions.class, Tests.Resolve.class, Tests.Scopes.class, Tests.SenselessComparison.class, Tests.Shadowing.class, Tests.SmartCasts.class, Tests.Substitutions.class, Tests.Subtyping.class, Tests.ThisAndSuper.class, Tests.Varargs.class})
public static class Tests extends AbstractDiagnosticsTestWithEagerResolve {
@TestMetadata("Abstract.kt")
public void testAbstract() throws Exception {
@@ -3399,6 +3399,19 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
}
@TestMetadata("compiler/testData/diagnostics/tests/recovery")
public static class Recovery extends AbstractDiagnosticsTestWithEagerResolve {
@TestMetadata("absentLeftHandSide.kt")
public void testAbsentLeftHandSide() throws Exception {
doTest("compiler/testData/diagnostics/tests/recovery/absentLeftHandSide.kt");
}
public void testAllFilesPresentInRecovery() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/diagnostics/tests/recovery"), Pattern.compile("^(.+)\\.kt$"), true);
}
}
@TestMetadata("compiler/testData/diagnostics/tests/redeclarations")
public static class Redeclarations extends AbstractDiagnosticsTestWithEagerResolve {
public void testAllFilesPresentInRedeclarations() throws Exception {
@@ -4503,6 +4516,7 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
suite.addTestSuite(OperatorsOverloading.class);
suite.addTestSuite(Overload.class);
suite.addTestSuite(Override.class);
suite.addTestSuite(Recovery.class);
suite.addTestSuite(Redeclarations.class);
suite.addTestSuite(Regressions.class);
suite.addTestSuite(Resolve.class);
@@ -45,8 +45,11 @@ public class ReplaceInfixCallFix extends JetIntentionAction<JetBinaryExpression>
@Override
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
String newText = element.getLeft().getText() + "?." + element.getOperationReference().getText()
+ "(" + element.getRight().getText() + ")";
JetExpression left = element.getLeft();
JetExpression right = element.getRight();
assert left != null && right != null : "Preconditions checked by factory";
String newText = left.getText() + "?." + element.getOperationReference().getText()
+ "(" + right.getText() + ")";
JetQualifiedExpression newElement = (JetQualifiedExpression) JetPsiFactory.createExpression(project, newText);
element.replace(newElement);
}
@@ -61,6 +64,9 @@ public class ReplaceInfixCallFix extends JetIntentionAction<JetBinaryExpression>
@Override
public IntentionAction createAction(Diagnostic diagnostic) {
JetBinaryExpression expression = QuickFixUtil.getParentElementOfType(diagnostic, JetBinaryExpression.class);
if (expression == null) return null;
if (expression.getLeft() == null) return null;
if (expression.getRight() == null) return null;
return new ReplaceInfixCallFix(expression);
}
};
@@ -23,6 +23,7 @@ import com.google.dart.compiler.backend.js.ast.JsLiteral;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
import org.jetbrains.jet.lang.psi.JetBinaryExpression;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.types.expressions.OperatorConventions;
import org.jetbrains.jet.lexer.JetTokens;
@@ -69,7 +70,9 @@ public final class EqualsIntrinsic implements BinaryOperationIntrinsic {
}
private static boolean canUseSimpleEquals(@NotNull JetBinaryExpression expression, @NotNull TranslationContext context) {
Name typeName = JsDescriptorUtils.getNameIfStandardType(expression.getLeft(), context);
JetExpression left = expression.getLeft();
assert left != null : "No left-hand side: " + expression.getText();
Name typeName = JsDescriptorUtils.getNameIfStandardType(left, context);
return typeName != null && NamePredicate.PRIMITIVE_NUMBERS.apply(typeName);
}
}
@@ -19,6 +19,7 @@ package org.jetbrains.k2js.translate.operation;
import com.google.dart.compiler.backend.js.ast.JsExpression;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetBinaryExpression;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.types.expressions.OperatorConventions;
import org.jetbrains.jet.lexer.JetToken;
import org.jetbrains.k2js.translate.context.TranslationContext;
@@ -61,7 +62,9 @@ public abstract class AssignmentTranslator extends AbstractTranslator {
super(context);
this.expression = expression;
this.isVariableReassignment = isVariableReassignment(context.bindingContext(), expression);
this.accessTranslator = AccessTranslationUtils.getAccessTranslator(expression.getLeft(), context());
JetExpression left = expression.getLeft();
assert left != null : "No left-hand side: " + expression.getText();
this.accessTranslator = AccessTranslationUtils.getAccessTranslator(left, context());
this.right = translateRightExpression(context(), expression);
}
}
@@ -153,7 +153,9 @@ public final class TranslationUtils {
@NotNull
public static JsExpression translateLeftExpression(@NotNull TranslationContext context,
@NotNull JetBinaryExpression expression) {
return Translation.translateAsExpression(expression.getLeft(), context);
JetExpression left = expression.getLeft();
assert left != null : "Binary expression should have a left expression: " + expression.getText();
return Translation.translateAsExpression(left, context);
}
@NotNull