PSI getter fixed: left-hand side of a binary expression can now be null
EA-35976 - IAE: FqNameUnsafe.validateFqName
This commit is contained in:
@@ -38,11 +38,18 @@ public class JetBinaryExpression extends JetExpressionImpl implements JetOperati
|
|||||||
return visitor.visitBinaryExpression(this, data);
|
return visitor.visitBinaryExpression(this, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@Nullable @IfNotParsed
|
||||||
public JetExpression getLeft() {
|
public JetExpression getLeft() {
|
||||||
JetExpression left = findChildByClass(JetExpression.class);
|
ASTNode node = getOperationReference().getNode().getTreePrev();
|
||||||
assert left != null;
|
while (node != null) {
|
||||||
return left;
|
PsiElement psi = node.getPsi();
|
||||||
|
if (psi instanceof JetExpression) {
|
||||||
|
return (JetExpression) psi;
|
||||||
|
}
|
||||||
|
node = node.getTreePrev();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable @IfNotParsed
|
@Nullable @IfNotParsed
|
||||||
|
|||||||
+3
-2
@@ -175,9 +175,10 @@ public class TracingStrategyImpl implements TracingStrategy {
|
|||||||
Name.identifier(operationReference.getText()) :
|
Name.identifier(operationReference.getText()) :
|
||||||
OperatorConventions.getNameForOperationSymbol((JetToken) operationReference.getReferencedNameElementType());
|
OperatorConventions.getNameForOperationSymbol((JetToken) operationReference.getReferencedNameElementType());
|
||||||
|
|
||||||
|
JetExpression left = binaryExpression.getLeft();
|
||||||
JetExpression right = binaryExpression.getRight();
|
JetExpression right = binaryExpression.getRight();
|
||||||
if (right != null) {
|
if (left != null && right != null) {
|
||||||
trace.report(UNSAFE_INFIX_CALL.on(reference, binaryExpression.getLeft().getText(), operationString.getName(), right.getText()));
|
trace.report(UNSAFE_INFIX_CALL.on(reference, left.getText(), operationString.getName(), right.getText()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
+25
-12
@@ -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.ResolutionResultsCache;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.context.ResolveMode;
|
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.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.results.OverloadResolutionResultsUtil;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.util.CallMaker;
|
import org.jetbrains.jet.lang.resolve.calls.util.CallMaker;
|
||||||
import org.jetbrains.jet.lang.resolve.constants.*;
|
import org.jetbrains.jet.lang.resolve.constants.*;
|
||||||
@@ -753,8 +754,13 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
JetExpression right = expression.getRight();
|
JetExpression right = expression.getRight();
|
||||||
IElementType operationType = operationSign.getReferencedNameElementType();
|
IElementType operationType = operationSign.getReferencedNameElementType();
|
||||||
|
|
||||||
|
JetTypeInfo leftTypeInfo = left != null
|
||||||
|
? facade.getTypeInfo(left, context)
|
||||||
|
: JetTypeInfo.create(null, context.dataFlowInfo);
|
||||||
|
|
||||||
JetType result = null;
|
JetType result = null;
|
||||||
DataFlowInfo dataFlowInfo = context.dataFlowInfo;
|
DataFlowInfo dataFlowInfo = context.dataFlowInfo;
|
||||||
|
|
||||||
if (operationType == JetTokens.IDENTIFIER) {
|
if (operationType == JetTokens.IDENTIFIER) {
|
||||||
Name referencedName = operationSign.getReferencedNameAsName();
|
Name referencedName = operationSign.getReferencedNameAsName();
|
||||||
JetTypeInfo typeInfo = getTypeInfoForBinaryCall(context.scope, referencedName, context, expression);
|
JetTypeInfo typeInfo = getTypeInfoForBinaryCall(context.scope, referencedName, context, expression);
|
||||||
@@ -792,10 +798,10 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
else {
|
else {
|
||||||
JetType booleanType = KotlinBuiltIns.getInstance().getBooleanType();
|
JetType booleanType = KotlinBuiltIns.getInstance().getBooleanType();
|
||||||
if (OperatorConventions.EQUALS_OPERATIONS.contains(operationType)) {
|
if (OperatorConventions.EQUALS_OPERATIONS.contains(operationType)) {
|
||||||
if (right != null) {
|
if (right != null && left != null) {
|
||||||
ExpressionReceiver receiver = ExpressionTypingUtils.safeGetExpressionReceiver(facade, left, context);
|
ExpressionReceiver receiver = ExpressionTypingUtils.safeGetExpressionReceiver(facade, left, context);
|
||||||
|
|
||||||
dataFlowInfo = facade.getTypeInfo(left, context).getDataFlowInfo();
|
dataFlowInfo = leftTypeInfo.getDataFlowInfo();
|
||||||
ExpressionTypingContext contextWithDataFlow = context.replaceDataFlowInfo(dataFlowInfo);
|
ExpressionTypingContext contextWithDataFlow = context.replaceDataFlowInfo(dataFlowInfo);
|
||||||
|
|
||||||
OverloadResolutionResults<FunctionDescriptor> resolutionResults = resolveFakeCall(
|
OverloadResolutionResults<FunctionDescriptor> resolutionResults = resolveFakeCall(
|
||||||
@@ -830,7 +836,6 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
}
|
}
|
||||||
else if (OperatorConventions.IN_OPERATIONS.contains(operationType)) {
|
else if (OperatorConventions.IN_OPERATIONS.contains(operationType)) {
|
||||||
if (right == null) {
|
if (right == null) {
|
||||||
result = ErrorUtils.createErrorType("No right argument"); // TODO
|
|
||||||
return JetTypeInfo.create(null, dataFlowInfo);
|
return JetTypeInfo.create(null, dataFlowInfo);
|
||||||
}
|
}
|
||||||
JetTypeInfo typeInfo = checkInExpression(expression, expression.getOperationReference(), left, right, context);
|
JetTypeInfo typeInfo = checkInExpression(expression, expression.getOperationReference(), left, right, context);
|
||||||
@@ -838,7 +843,6 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
result = typeInfo.getType();
|
result = typeInfo.getType();
|
||||||
}
|
}
|
||||||
else if (OperatorConventions.BOOLEAN_OPERATIONS.containsKey(operationType)) {
|
else if (OperatorConventions.BOOLEAN_OPERATIONS.containsKey(operationType)) {
|
||||||
JetTypeInfo leftTypeInfo = facade.getTypeInfo(left, context);
|
|
||||||
JetType leftType = leftTypeInfo.getType();
|
JetType leftType = leftTypeInfo.getType();
|
||||||
dataFlowInfo = leftTypeInfo.getDataFlowInfo();
|
dataFlowInfo = leftTypeInfo.getDataFlowInfo();
|
||||||
|
|
||||||
@@ -852,7 +856,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
JetType rightType = right == null
|
JetType rightType = right == null
|
||||||
? null
|
? null
|
||||||
: facade.getTypeInfo(right, context.replaceDataFlowInfo(flowInfoLeft).replaceScope(rightScope)).getType();
|
: 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));
|
context.trace.report(TYPE_MISMATCH.on(left, booleanType, leftType));
|
||||||
}
|
}
|
||||||
if (rightType != null && !isBoolean(rightType)) {
|
if (rightType != null && !isBoolean(rightType)) {
|
||||||
@@ -861,11 +865,10 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
result = booleanType;
|
result = booleanType;
|
||||||
}
|
}
|
||||||
else if (operationType == JetTokens.ELVIS) {
|
else if (operationType == JetTokens.ELVIS) {
|
||||||
JetTypeInfo leftTypeInfo = facade.getTypeInfo(left, context);
|
|
||||||
JetType leftType = leftTypeInfo.getType();
|
JetType leftType = leftTypeInfo.getType();
|
||||||
dataFlowInfo = leftTypeInfo.getDataFlowInfo();
|
dataFlowInfo = leftTypeInfo.getDataFlowInfo();
|
||||||
|
|
||||||
if (leftType != null) {
|
if (left != null && leftType != null) {
|
||||||
if (isKnownToBeNotNull(left, leftType, context)) {
|
if (isKnownToBeNotNull(left, leftType, context)) {
|
||||||
context.trace.report(USELESS_ELVIS.on(left, leftType));
|
context.trace.report(USELESS_ELVIS.on(left, leftType));
|
||||||
}
|
}
|
||||||
@@ -918,6 +921,8 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
|
|
||||||
private void ensureNonemptyIntersectionOfOperandTypes(JetBinaryExpression expression, ExpressionTypingContext context) {
|
private void ensureNonemptyIntersectionOfOperandTypes(JetBinaryExpression expression, ExpressionTypingContext context) {
|
||||||
JetExpression left = expression.getLeft();
|
JetExpression left = expression.getLeft();
|
||||||
|
if (left == null) return;
|
||||||
|
|
||||||
JetExpression right = expression.getRight();
|
JetExpression right = expression.getRight();
|
||||||
|
|
||||||
// TODO : duplicated effort for == and !=
|
// TODO : duplicated effort for == and !=
|
||||||
@@ -994,12 +999,20 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
) {
|
) {
|
||||||
ExpressionTypingContext context = contextWithOldScope.replaceScope(scope);
|
ExpressionTypingContext context = contextWithOldScope.replaceScope(scope);
|
||||||
JetExpression left = binaryExpression.getLeft();
|
JetExpression left = binaryExpression.getLeft();
|
||||||
DataFlowInfo dataFlowInfo = facade.getTypeInfo(left, context).getDataFlowInfo();
|
DataFlowInfo dataFlowInfo = context.dataFlowInfo;
|
||||||
|
if (left != null) {
|
||||||
ExpressionReceiver receiver = safeGetExpressionReceiver(facade, left, context);
|
dataFlowInfo = facade.getTypeInfo(left, context).getDataFlowInfo();
|
||||||
|
}
|
||||||
ExpressionTypingContext contextWithDataFlow = context.replaceDataFlowInfo(dataFlowInfo);
|
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();
|
JetExpression right = binaryExpression.getRight();
|
||||||
if (right != null) {
|
if (right != null) {
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ public class DataFlowUtils {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
JetExpression left = expression.getLeft();
|
JetExpression left = expression.getLeft();
|
||||||
|
if (left == null) return;
|
||||||
JetExpression right = expression.getRight();
|
JetExpression right = expression.getRight();
|
||||||
if (right == null) return;
|
if (right == null) return;
|
||||||
|
|
||||||
|
|||||||
+1
@@ -85,6 +85,7 @@ public class ExpressionTypingVisitorDispatcher extends JetVisitor<JetTypeInfo, E
|
|||||||
return getTypeInfo(expression, context, this);
|
return getTypeInfo(expression, context, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
public final JetTypeInfo getTypeInfo(@NotNull JetExpression expression, ExpressionTypingContext context, boolean isStatement) {
|
public final JetTypeInfo getTypeInfo(@NotNull JetExpression expression, ExpressionTypingContext context, boolean isStatement) {
|
||||||
if (!isStatement) return getTypeInfo(expression, context);
|
if (!isStatement) return getTypeInfo(expression, context);
|
||||||
|
|||||||
+13
-7
@@ -208,12 +208,15 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
|||||||
|
|
||||||
JetSimpleNameExpression operationSign = expression.getOperationReference();
|
JetSimpleNameExpression operationSign = expression.getOperationReference();
|
||||||
IElementType operationType = operationSign.getReferencedNameElementType();
|
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();
|
JetType leftType = leftInfo.getType();
|
||||||
DataFlowInfo dataFlowInfo = leftInfo.getDataFlowInfo();
|
DataFlowInfo dataFlowInfo = leftInfo.getDataFlowInfo();
|
||||||
|
|
||||||
JetExpression right = expression.getRight();
|
JetExpression right = expression.getRight();
|
||||||
JetExpression left = JetPsiUtil.deparenthesizeWithNoTypeResolution(expression.getLeft());
|
JetExpression left = leftOperand == null ? null : JetPsiUtil.deparenthesizeWithNoTypeResolution(leftOperand);
|
||||||
if (right == null || left == null) {
|
if (right == null || left == null) {
|
||||||
temporaryBindingTrace.commit();
|
temporaryBindingTrace.commit();
|
||||||
return JetTypeInfo.create(null, dataFlowInfo);
|
return JetTypeInfo.create(null, dataFlowInfo);
|
||||||
@@ -271,7 +274,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
|||||||
basic.resolveArrayAccessSetMethod((JetArrayAccessExpression) left, right, contextForResolve, context.trace);
|
basic.resolveArrayAccessSetMethod((JetArrayAccessExpression) left, right, contextForResolve, context.trace);
|
||||||
}
|
}
|
||||||
dataFlowInfo = facade.getTypeInfo(right, context.replaceDataFlowInfo(dataFlowInfo)).getDataFlowInfo();
|
dataFlowInfo = facade.getTypeInfo(right, context.replaceDataFlowInfo(dataFlowInfo)).getDataFlowInfo();
|
||||||
BasicExpressionTypingVisitor.checkLValue(context.trace, expression.getLeft());
|
BasicExpressionTypingVisitor.checkLValue(context.trace, leftOperand);
|
||||||
}
|
}
|
||||||
temporaryBindingTrace.commit();
|
temporaryBindingTrace.commit();
|
||||||
return JetTypeInfo.create(checkAssignmentType(type, expression, contextWithExpectedType), dataFlowInfo);
|
return JetTypeInfo.create(checkAssignmentType(type, expression, contextWithExpectedType), dataFlowInfo);
|
||||||
@@ -280,7 +283,8 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
|||||||
@NotNull
|
@NotNull
|
||||||
protected JetTypeInfo visitAssignment(JetBinaryExpression expression, ExpressionTypingContext contextWithExpectedType) {
|
protected JetTypeInfo visitAssignment(JetBinaryExpression expression, ExpressionTypingContext contextWithExpectedType) {
|
||||||
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE).replaceScope(scope);
|
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();
|
JetExpression right = expression.getRight();
|
||||||
if (left instanceof JetArrayAccessExpression) {
|
if (left instanceof JetArrayAccessExpression) {
|
||||||
JetArrayAccessExpression arrayAccessExpression = (JetArrayAccessExpression) left;
|
JetArrayAccessExpression arrayAccessExpression = (JetArrayAccessExpression) left;
|
||||||
@@ -290,15 +294,17 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
|||||||
return JetTypeInfo.create(checkAssignmentType(typeInfo.getType(), expression, contextWithExpectedType),
|
return JetTypeInfo.create(checkAssignmentType(typeInfo.getType(), expression, contextWithExpectedType),
|
||||||
typeInfo.getDataFlowInfo());
|
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();
|
JetType leftType = leftInfo.getType();
|
||||||
DataFlowInfo dataFlowInfo = leftInfo.getDataFlowInfo();
|
DataFlowInfo dataFlowInfo = leftInfo.getDataFlowInfo();
|
||||||
if (right != null) {
|
if (right != null) {
|
||||||
JetTypeInfo rightInfo = facade.getTypeInfo(right, context.replaceDataFlowInfo(dataFlowInfo).replaceExpectedType(leftType));
|
JetTypeInfo rightInfo = facade.getTypeInfo(right, context.replaceDataFlowInfo(dataFlowInfo).replaceExpectedType(leftType));
|
||||||
dataFlowInfo = rightInfo.getDataFlowInfo();
|
dataFlowInfo = rightInfo.getDataFlowInfo();
|
||||||
}
|
}
|
||||||
if (leftType != null) { //if leftType == null, some another error has been generated
|
if (leftType != null && leftOperand != null) { //if leftType == null, some other error has been generated
|
||||||
BasicExpressionTypingVisitor.checkLValue(context.trace, expression.getLeft());
|
BasicExpressionTypingVisitor.checkLValue(context.trace, leftOperand);
|
||||||
}
|
}
|
||||||
return DataFlowUtils.checkStatementType(expression, contextWithExpectedType, dataFlowInfo);
|
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})
|
@InnerTestClasses({JetDiagnosticsTestGenerated.Tests.class, JetDiagnosticsTestGenerated.Script.class})
|
||||||
public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEagerResolve {
|
public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEagerResolve {
|
||||||
@TestMetadata("compiler/testData/diagnostics/tests")
|
@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 {
|
public static class Tests extends AbstractDiagnosticsTestWithEagerResolve {
|
||||||
@TestMetadata("Abstract.kt")
|
@TestMetadata("Abstract.kt")
|
||||||
public void testAbstract() throws Exception {
|
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")
|
@TestMetadata("compiler/testData/diagnostics/tests/redeclarations")
|
||||||
public static class Redeclarations extends AbstractDiagnosticsTestWithEagerResolve {
|
public static class Redeclarations extends AbstractDiagnosticsTestWithEagerResolve {
|
||||||
public void testAllFilesPresentInRedeclarations() throws Exception {
|
public void testAllFilesPresentInRedeclarations() throws Exception {
|
||||||
@@ -4503,6 +4516,7 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage
|
|||||||
suite.addTestSuite(OperatorsOverloading.class);
|
suite.addTestSuite(OperatorsOverloading.class);
|
||||||
suite.addTestSuite(Overload.class);
|
suite.addTestSuite(Overload.class);
|
||||||
suite.addTestSuite(Override.class);
|
suite.addTestSuite(Override.class);
|
||||||
|
suite.addTestSuite(Recovery.class);
|
||||||
suite.addTestSuite(Redeclarations.class);
|
suite.addTestSuite(Redeclarations.class);
|
||||||
suite.addTestSuite(Regressions.class);
|
suite.addTestSuite(Regressions.class);
|
||||||
suite.addTestSuite(Resolve.class);
|
suite.addTestSuite(Resolve.class);
|
||||||
|
|||||||
@@ -45,8 +45,11 @@ public class ReplaceInfixCallFix extends JetIntentionAction<JetBinaryExpression>
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
|
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
|
||||||
String newText = element.getLeft().getText() + "?." + element.getOperationReference().getText()
|
JetExpression left = element.getLeft();
|
||||||
+ "(" + element.getRight().getText() + ")";
|
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);
|
JetQualifiedExpression newElement = (JetQualifiedExpression) JetPsiFactory.createExpression(project, newText);
|
||||||
element.replace(newElement);
|
element.replace(newElement);
|
||||||
}
|
}
|
||||||
@@ -61,6 +64,9 @@ public class ReplaceInfixCallFix extends JetIntentionAction<JetBinaryExpression>
|
|||||||
@Override
|
@Override
|
||||||
public IntentionAction createAction(Diagnostic diagnostic) {
|
public IntentionAction createAction(Diagnostic diagnostic) {
|
||||||
JetBinaryExpression expression = QuickFixUtil.getParentElementOfType(diagnostic, JetBinaryExpression.class);
|
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);
|
return new ReplaceInfixCallFix(expression);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
+4
-1
@@ -23,6 +23,7 @@ import com.google.dart.compiler.backend.js.ast.JsLiteral;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||||
import org.jetbrains.jet.lang.psi.JetBinaryExpression;
|
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.resolve.name.Name;
|
||||||
import org.jetbrains.jet.lang.types.expressions.OperatorConventions;
|
import org.jetbrains.jet.lang.types.expressions.OperatorConventions;
|
||||||
import org.jetbrains.jet.lexer.JetTokens;
|
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) {
|
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);
|
return typeName != null && NamePredicate.PRIMITIVE_NUMBERS.apply(typeName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-1
@@ -19,6 +19,7 @@ package org.jetbrains.k2js.translate.operation;
|
|||||||
import com.google.dart.compiler.backend.js.ast.JsExpression;
|
import com.google.dart.compiler.backend.js.ast.JsExpression;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.jet.lang.psi.JetBinaryExpression;
|
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.lang.types.expressions.OperatorConventions;
|
||||||
import org.jetbrains.jet.lexer.JetToken;
|
import org.jetbrains.jet.lexer.JetToken;
|
||||||
import org.jetbrains.k2js.translate.context.TranslationContext;
|
import org.jetbrains.k2js.translate.context.TranslationContext;
|
||||||
@@ -61,7 +62,9 @@ public abstract class AssignmentTranslator extends AbstractTranslator {
|
|||||||
super(context);
|
super(context);
|
||||||
this.expression = expression;
|
this.expression = expression;
|
||||||
this.isVariableReassignment = isVariableReassignment(context.bindingContext(), 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);
|
this.right = translateRightExpression(context(), expression);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -153,7 +153,9 @@ public final class TranslationUtils {
|
|||||||
@NotNull
|
@NotNull
|
||||||
public static JsExpression translateLeftExpression(@NotNull TranslationContext context,
|
public static JsExpression translateLeftExpression(@NotNull TranslationContext context,
|
||||||
@NotNull JetBinaryExpression expression) {
|
@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
|
@NotNull
|
||||||
|
|||||||
Reference in New Issue
Block a user