diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetBinaryExpression.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetBinaryExpression.java index 4dc29baa505..87f67b9a42e 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetBinaryExpression.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetBinaryExpression.java @@ -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 diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TracingStrategyImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TracingStrategyImpl.java index b998b2b2362..28a2d4e5ada 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TracingStrategyImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/tasks/TracingStrategyImpl.java @@ -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 { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java index 07ec68bf6dd..d1a9b385951 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java @@ -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 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 resolutionResults = - getResolutionResultsForBinaryCall(scope, name, contextWithDataFlow, binaryExpression, receiver); + + OverloadResolutionResults 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) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/DataFlowUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/DataFlowUtils.java index 9634289869e..8d074571135 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/DataFlowUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/DataFlowUtils.java @@ -73,6 +73,7 @@ public class DataFlowUtils { } else { JetExpression left = expression.getLeft(); + if (left == null) return; JetExpression right = expression.getRight(); if (right == null) return; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorDispatcher.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorDispatcher.java index a1ac70bc264..0edb86b04a5 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorDispatcher.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorDispatcher.java @@ -85,6 +85,7 @@ public class ExpressionTypingVisitorDispatcher extends JetVisitorimport a.* +} + +fun composite() { + val s = 13+~/12 +} + +fun html() { + <html></html> +} + +fun html1() { + <html></html>html +} \ No newline at end of file diff --git a/compiler/testData/psi/recovery/AbsentLeftHandSide.kt b/compiler/testData/psi/recovery/AbsentLeftHandSide.kt new file mode 100644 index 00000000000..9e16fb2243e --- /dev/null +++ b/compiler/testData/psi/recovery/AbsentLeftHandSide.kt @@ -0,0 +1,15 @@ +fun import() { + import a.* +} + +fun composite() { + val s = 13+~/12 +} + +fun html() { + +} + +fun html1() { + html +} \ No newline at end of file diff --git a/compiler/testData/psi/recovery/AbsentLeftHandSide.txt b/compiler/testData/psi/recovery/AbsentLeftHandSide.txt new file mode 100644 index 00000000000..caa4488cb55 --- /dev/null +++ b/compiler/testData/psi/recovery/AbsentLeftHandSide.txt @@ -0,0 +1,128 @@ +JetFile: AbsentLeftHandSide.kt + NAMESPACE_HEADER + + 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 + + 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 + + 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)('}') \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java index 0563bbe2250..b04566314a4 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java @@ -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); diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/ReplaceInfixCallFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/ReplaceInfixCallFix.java index fe1eecf6fcb..b4c93eb5b5c 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/ReplaceInfixCallFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/ReplaceInfixCallFix.java @@ -45,8 +45,11 @@ public class ReplaceInfixCallFix extends JetIntentionAction @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 @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); } }; diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/operation/EqualsIntrinsic.java b/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/operation/EqualsIntrinsic.java index 1495c2ff0c8..512a2807138 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/operation/EqualsIntrinsic.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/intrinsic/operation/EqualsIntrinsic.java @@ -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); } } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/operation/AssignmentTranslator.java b/js/js.translator/src/org/jetbrains/k2js/translate/operation/AssignmentTranslator.java index 8c2939eac90..ae7a53caa95 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/operation/AssignmentTranslator.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/operation/AssignmentTranslator.java @@ -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); } } diff --git a/js/js.translator/src/org/jetbrains/k2js/translate/utils/TranslationUtils.java b/js/js.translator/src/org/jetbrains/k2js/translate/utils/TranslationUtils.java index cf241c8fd38..dd0de2b2437 100644 --- a/js/js.translator/src/org/jetbrains/k2js/translate/utils/TranslationUtils.java +++ b/js/js.translator/src/org/jetbrains/k2js/translate/utils/TranslationUtils.java @@ -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