diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetAnnotatedExpression.java b/idea/src/org/jetbrains/jet/lang/psi/JetAnnotatedExpression.java index fb2ee0a6e18..37e83bb7d3b 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetAnnotatedExpression.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetAnnotatedExpression.java @@ -17,10 +17,15 @@ public class JetAnnotatedExpression extends JetExpression { } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitAnnotatedExpression(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitAnnotatedExpression(this, data); + } + public JetExpression getBaseExpression() { return findChildByClass(JetExpression.class); } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetAnnotation.java b/idea/src/org/jetbrains/jet/lang/psi/JetAnnotation.java index 6943eebd949..1395bc548b6 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetAnnotation.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetAnnotation.java @@ -15,10 +15,15 @@ public class JetAnnotation extends JetElement { } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitAnnotation(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitAnnotation(this, data); + } + public List getEntries() { return findChildrenByType(JetNodeTypes.ANNOTATION_ENTRY); } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetAnnotationEntry.java b/idea/src/org/jetbrains/jet/lang/psi/JetAnnotationEntry.java index ad89f77c45d..932e053c4cf 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetAnnotationEntry.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetAnnotationEntry.java @@ -17,10 +17,16 @@ public class JetAnnotationEntry extends JetElement implements JetCall { } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitAnnotationEntry(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitAnnotationEntry(this, data); + } + + @Nullable @IfNotParsed public JetTypeReference getTypeReference() { return (JetTypeReference) findChildByType(JetNodeTypes.TYPE_REFERENCE); diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetArrayAccessExpression.java b/idea/src/org/jetbrains/jet/lang/psi/JetArrayAccessExpression.java index c98601ddc53..716615bf83b 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetArrayAccessExpression.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetArrayAccessExpression.java @@ -29,10 +29,15 @@ public class JetArrayAccessExpression extends JetReferenceExpression { } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitArrayAccessExpression(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitArrayAccessExpression(this, data); + } + @NotNull public JetExpression getArrayExpression() { JetExpression baseExpression = findChildByClass(JetExpression.class); diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetBinaryExpression.java b/idea/src/org/jetbrains/jet/lang/psi/JetBinaryExpression.java index 6039515ee6b..7b42b809a5f 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetBinaryExpression.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetBinaryExpression.java @@ -16,10 +16,15 @@ public class JetBinaryExpression extends JetExpression { } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitBinaryExpression(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitBinaryExpression(this, data); + } + @NotNull public JetExpression getLeft() { JetExpression left = findChildByClass(JetExpression.class); diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetBinaryExpressionWithTypeRHS.java b/idea/src/org/jetbrains/jet/lang/psi/JetBinaryExpressionWithTypeRHS.java index 24a7e80f670..11693a01248 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetBinaryExpressionWithTypeRHS.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetBinaryExpressionWithTypeRHS.java @@ -15,10 +15,15 @@ public class JetBinaryExpressionWithTypeRHS extends JetExpression { } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitBinaryWithTypeRHSExpression(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitBinaryWithTypeRHSExpression(this, data); + } + @NotNull public JetExpression getLeft() { JetExpression left = findChildByClass(JetExpression.class); diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetBindingPattern.java b/idea/src/org/jetbrains/jet/lang/psi/JetBindingPattern.java index 4b133263183..2732addd248 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetBindingPattern.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetBindingPattern.java @@ -27,4 +27,9 @@ public class JetBindingPattern extends JetPattern { public void accept(@NotNull JetVisitor visitor) { visitor.visitBindingPattern(this); } + + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitBindingPattern(this, data); + } } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetBlockExpression.java b/idea/src/org/jetbrains/jet/lang/psi/JetBlockExpression.java index 1741591cdec..9a2e63e0afb 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetBlockExpression.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetBlockExpression.java @@ -15,10 +15,15 @@ public class JetBlockExpression extends JetExpression { } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitBlockExpression(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitBlockExpression(this, data); + } + @NotNull public List getStatements() { return Arrays.asList(findChildrenByClass(JetElement.class)); diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetBlockStringTemplateEntry.java b/idea/src/org/jetbrains/jet/lang/psi/JetBlockStringTemplateEntry.java index 82536d2a4d3..de7b50ad3d4 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetBlockStringTemplateEntry.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetBlockStringTemplateEntry.java @@ -15,4 +15,9 @@ public class JetBlockStringTemplateEntry extends JetStringTemplateEntryWithExpre public void accept(@NotNull JetVisitor visitor) { visitor.visitBlockStringTemplateEntry(this); } + + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitBlockStringTemplateEntry(this, data); + } } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetBreakExpression.java b/idea/src/org/jetbrains/jet/lang/psi/JetBreakExpression.java index bc9815ac587..33f88ccd652 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetBreakExpression.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetBreakExpression.java @@ -12,7 +12,12 @@ public class JetBreakExpression extends JetLabelQualifiedExpression { } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitBreakExpression(this); } + + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitBreakExpression(this, data); + } } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetCallExpression.java b/idea/src/org/jetbrains/jet/lang/psi/JetCallExpression.java index 4d75372cc3f..cc1b738843a 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetCallExpression.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetCallExpression.java @@ -17,10 +17,15 @@ public class JetCallExpression extends JetExpression implements JetCall { } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitCallExpression(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitCallExpression(this, data); + } + @Nullable public JetExpression getCalleeExpression() { return findChildByClass(JetExpression.class); diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetCatchClause.java b/idea/src/org/jetbrains/jet/lang/psi/JetCatchClause.java index e5111042758..cd9f2c25ccd 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetCatchClause.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetCatchClause.java @@ -16,10 +16,15 @@ public class JetCatchClause extends JetElement { } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitCatchSection(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitCatchSection(this, data); + } + @Nullable @IfNotParsed public JetParameterList getParameterList() { return (JetParameterList) findChildByType(JetNodeTypes.VALUE_PARAMETER_LIST); diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetClass.java b/idea/src/org/jetbrains/jet/lang/psi/JetClass.java index a679f330fc8..37c8e92c84e 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetClass.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetClass.java @@ -38,6 +38,11 @@ public class JetClass extends JetTypeParameterListOwner implements JetClassOrObj visitor.visitClass(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitClass(this, data); + } + @Nullable public JetParameterList getPrimaryConstructorParameterList() { return (JetParameterList) findChildByType(JetNodeTypes.VALUE_PARAMETER_LIST); diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetClassBody.java b/idea/src/org/jetbrains/jet/lang/psi/JetClassBody.java index 3278c17f679..79efeaeccf9 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetClassBody.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetClassBody.java @@ -29,6 +29,11 @@ public class JetClassBody extends JetElement { visitor.visitClassBody(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitClassBody(this, data); + } + @NotNull public List getAnonymousInitializers() { return findChildrenByType(JetNodeTypes.ANONYMOUS_INITIALIZER); diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetClassInitializer.java b/idea/src/org/jetbrains/jet/lang/psi/JetClassInitializer.java index c3eeb0d3b2b..4144b33744c 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetClassInitializer.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetClassInitializer.java @@ -16,6 +16,11 @@ public class JetClassInitializer extends JetDeclaration { visitor.visitAnonymousInitializer(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitAnonymousInitializer(this, data); + } + @NotNull public JetExpression getBody() { JetExpression body = findChildByClass(JetExpression.class); diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetClassObject.java b/idea/src/org/jetbrains/jet/lang/psi/JetClassObject.java index ff08a04506b..5487061f5cc 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetClassObject.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetClassObject.java @@ -18,6 +18,11 @@ public class JetClassObject extends JetDeclaration { visitor.visitClassObject(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitClassObject(this, data); + } + @Nullable @IfNotParsed public JetObjectDeclaration getObjectDeclaration() { return (JetObjectDeclaration) findChildByType(JetNodeTypes.OBJECT_DECLARATION); diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetConstantExpression.java b/idea/src/org/jetbrains/jet/lang/psi/JetConstantExpression.java index cb4d1e0ce9f..e12629179bc 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetConstantExpression.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetConstantExpression.java @@ -12,7 +12,12 @@ public class JetConstantExpression extends JetExpression { } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitConstantExpression(this); } + + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitConstantExpression(this, data); + } } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetConstructor.java b/idea/src/org/jetbrains/jet/lang/psi/JetConstructor.java index 89158226496..0f50a730a33 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetConstructor.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetConstructor.java @@ -22,6 +22,11 @@ public class JetConstructor extends JetDeclaration implements JetDeclarationWith visitor.visitConstructor(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitConstructor(this, data); + } + @Nullable @IfNotParsed public JetParameterList getParameterList() { return (JetParameterList) findChildByType(JetNodeTypes.VALUE_PARAMETER_LIST); @@ -54,6 +59,11 @@ public class JetConstructor extends JetDeclaration implements JetDeclarationWith return findChildByType(JetTokens.EQ) == null; } + @Override + public boolean hasDeclaredReturnType() { + return true; + } + @NotNull @Override public JetElement asElement() { diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetContinueExpression.java b/idea/src/org/jetbrains/jet/lang/psi/JetContinueExpression.java index 64053f7d7f7..0c70e55c4b0 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetContinueExpression.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetContinueExpression.java @@ -12,8 +12,12 @@ public class JetContinueExpression extends JetLabelQualifiedExpression { } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitContinueExpression(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitContinueExpression(this, data); + } } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetDeclarationWithBody.java b/idea/src/org/jetbrains/jet/lang/psi/JetDeclarationWithBody.java index b6561152e36..3bce72ddf0f 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetDeclarationWithBody.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetDeclarationWithBody.java @@ -17,6 +17,8 @@ public interface JetDeclarationWithBody { boolean hasBlockBody(); + boolean hasDeclaredReturnType(); + @NotNull JetElement asElement(); } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetDecomposerPattern.java b/idea/src/org/jetbrains/jet/lang/psi/JetDecomposerPattern.java index e123ac4aeab..17868971494 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetDecomposerPattern.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetDecomposerPattern.java @@ -26,4 +26,9 @@ public class JetDecomposerPattern extends JetPattern { public void accept(@NotNull JetVisitor visitor) { visitor.visitDecomposerPattern(this); } + + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitDecomposerPattern(this, data); + } } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetDelegationSpecifier.java b/idea/src/org/jetbrains/jet/lang/psi/JetDelegationSpecifier.java index c778cd70e68..8fd359a4d79 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetDelegationSpecifier.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetDelegationSpecifier.java @@ -14,10 +14,15 @@ public class JetDelegationSpecifier extends JetElement{ } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitDelegationSpecifier(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitDelegationSpecifier(this, data); + } + @Nullable public JetTypeReference getTypeReference() { return (JetTypeReference) findChildByType(JetNodeTypes.TYPE_REFERENCE); diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetDelegationSpecifierList.java b/idea/src/org/jetbrains/jet/lang/psi/JetDelegationSpecifierList.java index 9892b1778ec..723d44a375b 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetDelegationSpecifierList.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetDelegationSpecifierList.java @@ -15,10 +15,15 @@ public class JetDelegationSpecifierList extends JetElement { } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitDelegationSpecifierList(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitDelegationSpecifierList(this, data); + } + public List getDelegationSpecifiers() { return PsiTreeUtil.getChildrenOfTypeAsList(this, JetDelegationSpecifier.class); } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetDelegatorByExpressionSpecifier.java b/idea/src/org/jetbrains/jet/lang/psi/JetDelegatorByExpressionSpecifier.java index 8e791fd8c5b..276c880309a 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetDelegatorByExpressionSpecifier.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetDelegatorByExpressionSpecifier.java @@ -13,10 +13,15 @@ public class JetDelegatorByExpressionSpecifier extends JetDelegationSpecifier { } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitDelegationByExpressionSpecifier(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitDelegationByExpressionSpecifier(this, data); + } + @Nullable @IfNotParsed public JetExpression getDelegateExpression() { return findChildByClass(JetExpression.class); diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetDelegatorToSuperCall.java b/idea/src/org/jetbrains/jet/lang/psi/JetDelegatorToSuperCall.java index 8e7074ab888..0fb8e63ea70 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetDelegatorToSuperCall.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetDelegatorToSuperCall.java @@ -17,10 +17,15 @@ public class JetDelegatorToSuperCall extends JetDelegationSpecifier implements J } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitDelegationToSuperCallSpecifier(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitDelegationToSuperCallSpecifier(this, data); + } + @Nullable public JetValueArgumentList getValueArgumentList() { return (JetValueArgumentList) findChildByType(JetNodeTypes.VALUE_ARGUMENT_LIST); diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetDelegatorToSuperClass.java b/idea/src/org/jetbrains/jet/lang/psi/JetDelegatorToSuperClass.java index 3977f6594e7..ca57c10bca9 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetDelegatorToSuperClass.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetDelegatorToSuperClass.java @@ -12,7 +12,12 @@ public class JetDelegatorToSuperClass extends JetDelegationSpecifier { } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitDelegationToSuperClassSpecifier(this); } + + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitDelegationToSuperClassSpecifier(this, data); + } } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetDelegatorToThisCall.java b/idea/src/org/jetbrains/jet/lang/psi/JetDelegatorToThisCall.java index 9584c906795..e64449782e0 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetDelegatorToThisCall.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetDelegatorToThisCall.java @@ -18,10 +18,15 @@ public class JetDelegatorToThisCall extends JetDelegationSpecifier implements Je } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitDelegationToThisCall(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitDelegationToThisCall(this, data); + } + @Nullable public JetValueArgumentList getValueArgumentList() { return (JetValueArgumentList) findChildByType(JetNodeTypes.VALUE_ARGUMENT_LIST); diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetDoWhileExpression.java b/idea/src/org/jetbrains/jet/lang/psi/JetDoWhileExpression.java index a7aedd2a3ca..70260e42c53 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetDoWhileExpression.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetDoWhileExpression.java @@ -14,10 +14,15 @@ public class JetDoWhileExpression extends JetLoopExpression { } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitDoWhileExpression(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitDoWhileExpression(this, data); + } + @Nullable @IfNotParsed public JetExpression getCondition() { return findExpressionUnder(JetNodeTypes.CONDITION); diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetDotQualifiedExpression.java b/idea/src/org/jetbrains/jet/lang/psi/JetDotQualifiedExpression.java index bc84003bb95..6705b33c8a4 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetDotQualifiedExpression.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetDotQualifiedExpression.java @@ -12,7 +12,12 @@ public class JetDotQualifiedExpression extends JetQualifiedExpression { } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitDotQualifiedExpression(this); } + + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitDotQualifiedExpression(this, data); + } } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetElement.java b/idea/src/org/jetbrains/jet/lang/psi/JetElement.java index 53c979e19ef..55d06eeb59e 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetElement.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetElement.java @@ -51,4 +51,8 @@ public class JetElement extends ASTWrapperPsiElement { public void accept(@NotNull JetVisitor visitor) { visitor.visitJetElement(this); } + + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitJetElement(this, data); + } } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetEnumEntry.java b/idea/src/org/jetbrains/jet/lang/psi/JetEnumEntry.java index 3cf2c29d08b..1ab95f34f5b 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetEnumEntry.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetEnumEntry.java @@ -50,4 +50,9 @@ public class JetEnumEntry extends JetClass { public void accept(@NotNull JetVisitor visitor) { visitor.visitEnumEntry(this); } + + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitEnumEntry(this, data); + } } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetEscapeStringTemplateEntry.java b/idea/src/org/jetbrains/jet/lang/psi/JetEscapeStringTemplateEntry.java index aedd7c26d93..c6215bbfd93 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetEscapeStringTemplateEntry.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetEscapeStringTemplateEntry.java @@ -17,6 +17,11 @@ public class JetEscapeStringTemplateEntry extends JetStringTemplateEntry { visitor.visitEscapeStringTemplateEntry(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitEscapeStringTemplateEntry(this, data); + } + public String getUnescapedValue() { return StringUtil.unescapeStringCharacters(getText()); } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetExpression.java b/idea/src/org/jetbrains/jet/lang/psi/JetExpression.java index fd4aff0f2ea..3c316106777 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetExpression.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetExpression.java @@ -13,10 +13,15 @@ public class JetExpression extends JetElement { } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitExpression(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitExpression(this, data); + } + protected JetExpression findExpressionUnder(JetNodeType type) { JetContainerNode containerNode = (JetContainerNode) findChildByType(type); if (containerNode == null) return null; diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetExpressionPattern.java b/idea/src/org/jetbrains/jet/lang/psi/JetExpressionPattern.java index 669a4b00f3f..c5a1ecd48d6 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetExpressionPattern.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetExpressionPattern.java @@ -21,4 +21,9 @@ public class JetExpressionPattern extends JetPattern { public void accept(@NotNull JetVisitor visitor) { visitor.visitExpressionPattern(this); } + + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitExpressionPattern(this, data); + } } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetExtendedVisitor.java b/idea/src/org/jetbrains/jet/lang/psi/JetExtendedVisitor.java new file mode 100644 index 00000000000..276bd8856e3 --- /dev/null +++ b/idea/src/org/jetbrains/jet/lang/psi/JetExtendedVisitor.java @@ -0,0 +1,422 @@ +package org.jetbrains.jet.lang.psi; + +import com.intellij.psi.PsiElementVisitor; + +/** + * @author svtk + */ +public class JetExtendedVisitor extends PsiElementVisitor { + public R visitJetElement(JetElement element, D data) { + visitElement(element); + return null; + } + + public R visitDeclaration(JetDeclaration dcl, D data) { + return visitExpression(dcl, data); + } + + public R visitNamespace(JetNamespace namespace, D data) { + return visitDeclaration(namespace, data); + } + + public R visitClass(JetClass klass, D data) { + return visitNamedDeclaration(klass, data); + } + + public R visitClassObject(JetClassObject classObject, D data) { + return visitDeclaration(classObject, data); + } + + public R visitConstructor(JetConstructor constructor, D data) { + return visitDeclaration(constructor, data); + } + + public R visitNamedFunction(JetNamedFunction function, D data) { + return visitNamedDeclaration(function, data); + } + + public R visitProperty(JetProperty property, D data) { + return visitNamedDeclaration(property, data); + } + + public R visitTypedef(JetTypedef typedef, D data) { + return visitNamedDeclaration(typedef, data); + } + + public R visitJetFile(JetFile file, D data) { + visitFile(file); + return null; + } + + public R visitImportDirective(JetImportDirective importDirective, D data) { + return visitJetElement(importDirective, data); + } + + public R visitClassBody(JetClassBody classBody, D data) { + return visitJetElement(classBody, data); + } + + public R visitNamespaceBody(JetNamespaceBody body, D data) { + return visitJetElement(body, data); + } + + public R visitModifierList(JetModifierList list, D data) { + return visitJetElement(list, data); + } + + public R visitAnnotation(JetAnnotation annotation, D data) { + return visitJetElement(annotation, data); + } + + public R visitAnnotationEntry(JetAnnotationEntry annotationEntry, D data) { + return visitJetElement(annotationEntry, data); + } + + public R visitTypeParameterList(JetTypeParameterList list, D data) { + return visitJetElement(list, data); + } + + public R visitTypeParameter(JetTypeParameter parameter, D data) { + return visitNamedDeclaration(parameter, data); + } + + public R visitEnumEntry(JetEnumEntry enumEntry, D data) { + return visitClass(enumEntry, data); + } + + public R visitParameterList(JetParameterList list, D data) { + return visitJetElement(list, data); + } + + public R visitParameter(JetParameter parameter, D data) { + return visitNamedDeclaration(parameter, data); + } + + public R visitDelegationSpecifierList(JetDelegationSpecifierList list, D data) { + return visitJetElement(list, data); + } + + public R visitDelegationSpecifier(JetDelegationSpecifier specifier, D data) { + return visitJetElement(specifier, data); + } + + public R visitDelegationByExpressionSpecifier(JetDelegatorByExpressionSpecifier specifier, D data) { + return visitDelegationSpecifier(specifier, data); + } + + public R visitDelegationToSuperCallSpecifier(JetDelegatorToSuperCall call, D data) { + return visitDelegationSpecifier(call, data); + } + + public R visitDelegationToSuperClassSpecifier(JetDelegatorToSuperClass specifier, D data) { + return visitDelegationSpecifier(specifier, data); + } + + public R visitDelegationToThisCall(JetDelegatorToThisCall thisCall, D data) { + return visitDelegationSpecifier(thisCall, data); + } + + public R visitTypeReference(JetTypeReference typeReference, D data) { + return visitJetElement(typeReference, data); + } + + public R visitValueArgumentList(JetValueArgumentList list, D data) { + return visitJetElement(list, data); + } + + public R visitArgument(JetValueArgument argument, D data) { + return visitJetElement(argument, data); + } + + public R visitExpression(JetExpression expression, D data) { + return visitJetElement(expression, data); + } + + public R visitLoopExpression(JetLoopExpression loopExpression, D data) { + return visitExpression(loopExpression, data); + } + + public R visitConstantExpression(JetConstantExpression expression, D data) { + return visitExpression(expression, data); + } + + public R visitSimpleNameExpression(JetSimpleNameExpression expression, D data) { + return visitReferenceExpression(expression, data); + } + + public R visitReferenceExpression(JetReferenceExpression expression, D data) { + return visitExpression(expression, data); + } + + public R visitTupleExpression(JetTupleExpression expression, D data) { + return visitExpression(expression, data); + } + + public R visitPrefixExpression(JetPrefixExpression expression, D data) { + return visitUnaryExpression(expression, data); + } + + public R visitPostfixExpression(JetPostfixExpression expression, D data) { + return visitUnaryExpression(expression, data); + } + + public R visitUnaryExpression(JetUnaryExpression expression, D data) { + return visitExpression(expression, data); + } + + public R visitBinaryExpression(JetBinaryExpression expression, D data) { + return visitExpression(expression, data); + } + +// public R visitNewExpression(JetNewExpression expression, D data) { +// return visitExpression(expression, data); +// } +// + public R visitReturnExpression(JetReturnExpression expression, D data) { + return visitLabelQualifiedExpression(expression, data); + } + + public R visitLabelQualifiedExpression(JetLabelQualifiedExpression expression, D data) { + return visitExpression(expression, data); + } + + public R visitThrowExpression(JetThrowExpression expression, D data) { + return visitExpression(expression, data); + } + + public R visitBreakExpression(JetBreakExpression expression, D data) { + return visitLabelQualifiedExpression(expression, data); + } + + public R visitContinueExpression(JetContinueExpression expression, D data) { + return visitLabelQualifiedExpression(expression, data); + } + + public R visitIfExpression(JetIfExpression expression, D data) { + return visitExpression(expression, data); + } + + public R visitWhenExpression(JetWhenExpression expression, D data) { + return visitExpression(expression, data); + } + + public R visitTryExpression(JetTryExpression expression, D data) { + return visitExpression(expression, data); + } + + public R visitForExpression(JetForExpression expression, D data) { + return visitLoopExpression(expression, data); + } + + public R visitWhileExpression(JetWhileExpression expression, D data) { + return visitLoopExpression(expression, data); + } + + public R visitDoWhileExpression(JetDoWhileExpression expression, D data) { + return visitLoopExpression(expression, data); + } + + public R visitFunctionLiteralExpression(JetFunctionLiteralExpression expression, D data) { + return visitExpression(expression, data); + } + + public R visitAnnotatedExpression(JetAnnotatedExpression expression, D data) { + return visitExpression(expression, data); + } + + public R visitCallExpression(JetCallExpression expression, D data) { + return visitExpression(expression, data); + } + + public R visitArrayAccessExpression(JetArrayAccessExpression expression, D data) { + return visitReferenceExpression(expression, data); + } + + public R visitQualifiedExpression(JetQualifiedExpression expression, D data) { + return visitExpression(expression, data); + } + + public R visitHashQualifiedExpression(JetHashQualifiedExpression expression, D data) { + return visitQualifiedExpression(expression, data); + } + + public R visitDotQualifiedExpression(JetDotQualifiedExpression expression, D data) { + return visitQualifiedExpression(expression, data); + } + + public R visitPredicateExpression(JetPredicateExpression expression, D data) { + return visitQualifiedExpression(expression, data); + } + + public R visitSafeQualifiedExpression(JetSafeQualifiedExpression expression, D data) { + return visitQualifiedExpression(expression, data); + } + + public R visitObjectLiteralExpression(JetObjectLiteralExpression expression, D data) { + return visitExpression(expression, data); + } + + public R visitRootNamespaceExpression(JetRootNamespaceExpression expression, D data) { + return visitExpression(expression, data); + } + + public R visitBlockExpression(JetBlockExpression expression, D data) { + return visitExpression(expression, data); + } + + public R visitCatchSection(JetCatchClause catchClause, D data) { + return visitJetElement(catchClause, data); + } + + public R visitFinallySection(JetFinallySection finallySection, D data) { + return visitJetElement(finallySection, data); + } + + public R visitTypeArgumentList(JetTypeArgumentList typeArgumentList, D data) { + return visitJetElement(typeArgumentList, data); + } + + public R visitThisExpression(JetThisExpression expression, D data) { + return visitLabelQualifiedExpression(expression, data); + } + + public R visitParenthesizedExpression(JetParenthesizedExpression expression, D data) { + return visitExpression(expression, data); + } + + public R visitInitializerList(JetInitializerList list, D data) { + return visitJetElement(list, data); + } + + public R visitAnonymousInitializer(JetClassInitializer initializer, D data) { + return visitDeclaration(initializer, data); + } + + public R visitPropertyAccessor(JetPropertyAccessor accessor, D data) { + return visitDeclaration(accessor, data); + } + + public R visitTypeConstraintList(JetTypeConstraintList list, D data) { + return visitJetElement(list, data); + } + + public R visitTypeConstraint(JetTypeConstraint constraint, D data) { + return visitJetElement(constraint, data); + } + + private R visitTypeElement(JetTypeElement type, D data) { + return visitJetElement(type, data); + } + + public R visitUserType(JetUserType type, D data) { + return visitTypeElement(type, data); + } + + public R visitTupleType(JetTupleType type, D data) { + return visitTypeElement(type, data); + } + + public R visitFunctionType(JetFunctionType type, D data) { + return visitTypeElement(type, data); + } + + public R visitSelfType(JetSelfType type, D data) { + return visitTypeElement(type, data); + } + + public R visitBinaryWithTypeRHSExpression(JetBinaryExpressionWithTypeRHS expression, D data) { + return visitExpression(expression, data); + } + + public R visitStringTemplateExpression(JetStringTemplateExpression expression, D data) { + return visitExpression(expression, data); + } + + public R visitNamedDeclaration(JetNamedDeclaration declaration, D data) { + return visitDeclaration(declaration, data); + } + + public R visitNullableType(JetNullableType nullableType, D data) { + return visitTypeElement(nullableType, data); + } + + public R visitTypeProjection(JetTypeProjection typeProjection, D data) { + return visitJetElement(typeProjection, data); + } + + public R visitWhenEntry(JetWhenEntry jetWhenEntry, D data) { + return visitJetElement(jetWhenEntry, data); + } + + public R visitIsExpression(JetIsExpression expression, D data) { + return visitExpression(expression, data); + } + + public R visitWhenConditionCall(JetWhenConditionCall condition, D data) { + return visitJetElement(condition, data); + } + + public R visitWhenConditionIsPattern(JetWhenConditionIsPattern condition, D data) { + return visitJetElement(condition, data); + } + + public R visitWhenConditionInRange(JetWhenConditionInRange condition, D data) { + return visitJetElement(condition, data); + } + + public R visitTypePattern(JetTypePattern pattern, D data) { + return visitPattern(pattern, data); + } + + public R visitWildcardPattern(JetWildcardPattern pattern, D data) { + return visitPattern(pattern, data); + } + + public R visitExpressionPattern(JetExpressionPattern pattern, D data) { + return visitPattern(pattern, data); + } + + public R visitTuplePattern(JetTuplePattern pattern, D data) { + return visitPattern(pattern, data); + } + + private R visitPattern(JetPattern pattern, D data) { + return visitJetElement(pattern, data); + } + + public R visitDecomposerPattern(JetDecomposerPattern pattern, D data) { + return visitPattern(pattern, data); + } + + public R visitObjectDeclaration(JetObjectDeclaration declaration, D data) { + return visitNamedDeclaration(declaration, data); + } + + public R visitBindingPattern(JetBindingPattern pattern, D data) { + return visitPattern(pattern, data); + } + + public R visitStringTemplateEntry(JetStringTemplateEntry entry, D data) { + return visitJetElement(entry, data); + } + + public R visitStringTemplateEntryWithExpression(JetStringTemplateEntryWithExpression entry, D data) { + return visitStringTemplateEntry(entry, data); + } + + public R visitBlockStringTemplateEntry(JetBlockStringTemplateEntry entry, D data) { + return visitStringTemplateEntryWithExpression(entry, data); + } + + public R visitSimpleNameStringTemplateEntry(JetSimpleNameStringTemplateEntry entry, D data) { + return visitStringTemplateEntryWithExpression(entry, data); + } + + public R visitLiteralStringTemplateEntry(JetLiteralStringTemplateEntry entry, D data) { + return visitStringTemplateEntry(entry, data); + } + + public R visitEscapeStringTemplateEntry(JetEscapeStringTemplateEntry entry, D data) { + return visitStringTemplateEntry(entry, data); + } +} diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetFinallySection.java b/idea/src/org/jetbrains/jet/lang/psi/JetFinallySection.java index b35cc6c623f..0b61633e56e 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetFinallySection.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetFinallySection.java @@ -13,10 +13,15 @@ public class JetFinallySection extends JetElement { } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitFinallySection(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitFinallySection(this, data); + } + public JetBlockExpression getFinalExpression() { return (JetBlockExpression) findChildByType(JetNodeTypes.BLOCK); } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetForExpression.java b/idea/src/org/jetbrains/jet/lang/psi/JetForExpression.java index e6a6585fe2c..eca792f6a55 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetForExpression.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetForExpression.java @@ -14,10 +14,15 @@ public class JetForExpression extends JetLoopExpression { } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitForExpression(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitForExpression(this, data); + } + @Nullable @IfNotParsed public JetParameter getLoopParameter() { return (JetParameter) findChildByType(JetNodeTypes.LOOP_PARAMETER); diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetFunction.java b/idea/src/org/jetbrains/jet/lang/psi/JetFunction.java index 761555df925..10f03300dca 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetFunction.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetFunction.java @@ -36,6 +36,11 @@ abstract public class JetFunction extends JetTypeParameterListOwner implements J return findChildByClass(JetExpression.class); } + @Override + public boolean hasDeclaredReturnType() { + return getReturnTypeRef() != null; + } + @Nullable public JetTypeReference getReceiverTypeRef() { PsiElement child = getFirstChild(); diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetFunctionLiteralExpression.java b/idea/src/org/jetbrains/jet/lang/psi/JetFunctionLiteralExpression.java index 90d1f4e2fdf..9edf8b69842 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetFunctionLiteralExpression.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetFunctionLiteralExpression.java @@ -13,10 +13,15 @@ public class JetFunctionLiteralExpression extends JetExpression implements JetDe } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitFunctionLiteralExpression(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitFunctionLiteralExpression(this, data); + } + @NotNull public JetFunctionLiteral getFunctionLiteral() { return (JetFunctionLiteral) findChildByType(JetNodeTypes.FUNCTION_LITERAL); @@ -89,6 +94,11 @@ public class JetFunctionLiteralExpression extends JetExpression implements JetDe return getFunctionLiteral().hasBlockBody(); } + @Override + public boolean hasDeclaredReturnType() { + return getFunctionLiteral().getReturnTypeRef() != null; + } + @NotNull @Override public JetElement asElement() { diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetFunctionType.java b/idea/src/org/jetbrains/jet/lang/psi/JetFunctionType.java index f891dc22835..5ca6c2f8611 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetFunctionType.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetFunctionType.java @@ -40,10 +40,15 @@ public class JetFunctionType extends JetTypeElement { } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitFunctionType(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitFunctionType(this, data); + } + @Nullable public JetParameterList getParameterList() { return (JetParameterList) findChildByType(JetNodeTypes.VALUE_PARAMETER_LIST); diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetHashQualifiedExpression.java b/idea/src/org/jetbrains/jet/lang/psi/JetHashQualifiedExpression.java index 8d57cb07fbf..b0810b91e60 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetHashQualifiedExpression.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetHashQualifiedExpression.java @@ -12,7 +12,12 @@ public class JetHashQualifiedExpression extends JetQualifiedExpression { } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitHashQualifiedExpression(this); } + + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitHashQualifiedExpression(this, data); + } } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetIfExpression.java b/idea/src/org/jetbrains/jet/lang/psi/JetIfExpression.java index d9bed419521..fc101f3d9d7 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetIfExpression.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetIfExpression.java @@ -14,10 +14,15 @@ public class JetIfExpression extends JetExpression { } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitIfExpression(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitIfExpression(this, data); + } + @Nullable @IfNotParsed public JetExpression getCondition() { return findExpressionUnder(JetNodeTypes.CONDITION); diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetImportDirective.java b/idea/src/org/jetbrains/jet/lang/psi/JetImportDirective.java index 70dec29467c..ea17d84371c 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetImportDirective.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetImportDirective.java @@ -19,6 +19,11 @@ public class JetImportDirective extends JetElement { visitor.visitImportDirective(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitImportDirective(this, data); + } + public boolean isAbsoluteInRootNamespace() { return findChildByType(JetTokens.NAMESPACE_KEYWORD) != null; } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetInitializerList.java b/idea/src/org/jetbrains/jet/lang/psi/JetInitializerList.java index 0ea640057bf..3b3e10fcd78 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetInitializerList.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetInitializerList.java @@ -15,10 +15,15 @@ public class JetInitializerList extends JetElement { } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitInitializerList(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitInitializerList(this, data); + } + @NotNull public List getInitializers() { return PsiTreeUtil.getChildrenOfTypeAsList(this, JetDelegationSpecifier.class); diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetIsExpression.java b/idea/src/org/jetbrains/jet/lang/psi/JetIsExpression.java index cec1562d18c..2ec6bf10630 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetIsExpression.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetIsExpression.java @@ -15,10 +15,15 @@ public class JetIsExpression extends JetExpression { } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitIsExpression(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitIsExpression(this, data); + } + @NotNull public JetExpression getLeftHandSide() { return findChildByClass(JetExpression.class); diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetLiteralStringTemplateEntry.java b/idea/src/org/jetbrains/jet/lang/psi/JetLiteralStringTemplateEntry.java index d3f921042e4..ef108e98441 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetLiteralStringTemplateEntry.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetLiteralStringTemplateEntry.java @@ -15,4 +15,9 @@ public class JetLiteralStringTemplateEntry extends JetStringTemplateEntry { public void accept(@NotNull JetVisitor visitor) { visitor.visitLiteralStringTemplateEntry(this); } + + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitLiteralStringTemplateEntry(this, data); + } } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetModifierList.java b/idea/src/org/jetbrains/jet/lang/psi/JetModifierList.java index 9b2f81651bd..a1adbcf0abc 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetModifierList.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetModifierList.java @@ -23,6 +23,11 @@ public class JetModifierList extends JetElement { visitor.visitModifierList(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitModifierList(this, data); + } + @NotNull public List getAnnotations() { return findChildrenByType(JetNodeTypes.ANNOTATION); diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetNamedFunction.java b/idea/src/org/jetbrains/jet/lang/psi/JetNamedFunction.java index 9daafe12660..c8e91a2bdf7 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetNamedFunction.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetNamedFunction.java @@ -18,6 +18,11 @@ public class JetNamedFunction extends JetFunction { visitor.visitNamedFunction(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitNamedFunction(this, data); + } + public boolean hasTypeParameterListBeforeFunctionName() { JetTypeParameterList typeParameterList = getTypeParameterList(); if (typeParameterList == null) { diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetNamespace.java b/idea/src/org/jetbrains/jet/lang/psi/JetNamespace.java index 178b05bd771..4a485ec1ea0 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetNamespace.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetNamespace.java @@ -23,6 +23,11 @@ public class JetNamespace extends JetNamedDeclaration { visitor.visitNamespace(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitNamespace(this, data); + } + public List getDeclarations() { PsiElement body = findChildByType(JetNodeTypes.NAMESPACE_BODY); return PsiTreeUtil.getChildrenOfTypeAsList(body != null ? body : this, JetDeclaration.class); diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetNamespaceBody.java b/idea/src/org/jetbrains/jet/lang/psi/JetNamespaceBody.java index ee3a9ed4d48..e94052eff29 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetNamespaceBody.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetNamespaceBody.java @@ -22,4 +22,9 @@ public class JetNamespaceBody extends JetElement { public void accept(@NotNull JetVisitor visitor) { visitor.visitNamespaceBody(this); } + + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitNamespaceBody(this, data); + } } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetNullableType.java b/idea/src/org/jetbrains/jet/lang/psi/JetNullableType.java index 02eccd4d634..6d99b922fac 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetNullableType.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetNullableType.java @@ -20,10 +20,15 @@ public class JetNullableType extends JetTypeElement { } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitNullableType(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitNullableType(this, data); + } + @NotNull public JetTypeElement getInnerType() { return findChildByClass(JetTypeElement.class); diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetObjectDeclaration.java b/idea/src/org/jetbrains/jet/lang/psi/JetObjectDeclaration.java index 8b4401af2a4..7e6f1399451 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetObjectDeclaration.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetObjectDeclaration.java @@ -79,10 +79,15 @@ public class JetObjectDeclaration extends JetNamedDeclaration implements JetClas } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitObjectDeclaration(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitObjectDeclaration(this, data); + } + public boolean isObjectLiteral() { return getNameAsDeclaration() == null; } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetObjectLiteralExpression.java b/idea/src/org/jetbrains/jet/lang/psi/JetObjectLiteralExpression.java index bf371443e1c..0ea4211d465 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetObjectLiteralExpression.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetObjectLiteralExpression.java @@ -13,10 +13,15 @@ public class JetObjectLiteralExpression extends JetExpression { } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitObjectLiteralExpression(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitObjectLiteralExpression(this, data); + } + @NotNull public JetObjectDeclaration getObjectDeclaration() { return (JetObjectDeclaration) findChildByType(JetNodeTypes.OBJECT_DECLARATION); diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetParameter.java b/idea/src/org/jetbrains/jet/lang/psi/JetParameter.java index 31262d052dc..172d9dfc8f9 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetParameter.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetParameter.java @@ -15,10 +15,15 @@ public class JetParameter extends JetNamedDeclaration { } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitParameter(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitParameter(this, data); + } + @Nullable public JetTypeReference getTypeReference() { return (JetTypeReference) findChildByType(JetNodeTypes.TYPE_REFERENCE); diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetParameterList.java b/idea/src/org/jetbrains/jet/lang/psi/JetParameterList.java index c8d3d215602..1f814c3aae7 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetParameterList.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetParameterList.java @@ -15,10 +15,15 @@ public class JetParameterList extends JetElement { } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitParameterList(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitParameterList(this, data); + } + public List getParameters() { return findChildrenByType(JetNodeTypes.VALUE_PARAMETER); } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetParenthesizedExpression.java b/idea/src/org/jetbrains/jet/lang/psi/JetParenthesizedExpression.java index 903f4ef40ba..6111b67e938 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetParenthesizedExpression.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetParenthesizedExpression.java @@ -13,10 +13,15 @@ public class JetParenthesizedExpression extends JetExpression { } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitParenthesizedExpression(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitParenthesizedExpression(this, data); + } + @Nullable @IfNotParsed public JetExpression getExpression() { return findChildByClass(JetExpression.class); diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetPostfixExpression.java b/idea/src/org/jetbrains/jet/lang/psi/JetPostfixExpression.java index 0c8c1c3bb50..ebe92d5bc2a 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetPostfixExpression.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetPostfixExpression.java @@ -19,8 +19,12 @@ public class JetPostfixExpression extends JetUnaryExpression { } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitPostfixExpression(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitPostfixExpression(this, data); + } } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetPredicateExpression.java b/idea/src/org/jetbrains/jet/lang/psi/JetPredicateExpression.java index 63d73e4dd10..6d05c4dd76b 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetPredicateExpression.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetPredicateExpression.java @@ -12,7 +12,12 @@ public class JetPredicateExpression extends JetQualifiedExpression { } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitPredicateExpression(this); } + + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitPredicateExpression(this, data); + } } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetPrefixExpression.java b/idea/src/org/jetbrains/jet/lang/psi/JetPrefixExpression.java index 4d9e0986e43..b81f119e382 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetPrefixExpression.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetPrefixExpression.java @@ -14,10 +14,15 @@ public class JetPrefixExpression extends JetUnaryExpression { } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitPrefixExpression(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitPrefixExpression(this, data); + } + @Nullable @IfNotParsed public JetExpression getBaseExpression() { PsiElement expression = getOperationSign().getNextSibling(); diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetProperty.java b/idea/src/org/jetbrains/jet/lang/psi/JetProperty.java index 5882e24fde0..13345dffe19 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetProperty.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetProperty.java @@ -24,6 +24,11 @@ public class JetProperty extends JetTypeParameterListOwner { visitor.visitProperty(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitProperty(this, data); + } + public boolean isVar() { return getNode().findChildByType(JetTokens.VAR_KEYWORD) != null; } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetPropertyAccessor.java b/idea/src/org/jetbrains/jet/lang/psi/JetPropertyAccessor.java index 0fe670224a6..de4f54f23b6 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetPropertyAccessor.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetPropertyAccessor.java @@ -17,10 +17,15 @@ public class JetPropertyAccessor extends JetDeclaration implements JetDeclaratio } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitPropertyAccessor(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitPropertyAccessor(this, data); + } + public boolean isSetter() { return findChildByType(JetTokens.SET_KEYWORD) != null; } @@ -49,6 +54,11 @@ public class JetPropertyAccessor extends JetDeclaration implements JetDeclaratio return findChildByType(JetTokens.EQ) == null; } + @Override + public boolean hasDeclaredReturnType() { + return false; + } + @NotNull @Override public JetElement asElement() { diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetReturnExpression.java b/idea/src/org/jetbrains/jet/lang/psi/JetReturnExpression.java index 2982b819992..1f24184413d 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetReturnExpression.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetReturnExpression.java @@ -13,10 +13,15 @@ public class JetReturnExpression extends JetLabelQualifiedExpression { } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitReturnExpression(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitReturnExpression(this, data); + } + @Nullable public JetExpression getReturnedExpression() { return findChildByClass(JetExpression.class); diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetRootNamespaceExpression.java b/idea/src/org/jetbrains/jet/lang/psi/JetRootNamespaceExpression.java index 7a6ad148bc9..b77cbe71344 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetRootNamespaceExpression.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetRootNamespaceExpression.java @@ -12,7 +12,12 @@ public class JetRootNamespaceExpression extends JetExpression { } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitRootNamespaceExpression(this); } + + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitRootNamespaceExpression(this, data); + } } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetSafeQualifiedExpression.java b/idea/src/org/jetbrains/jet/lang/psi/JetSafeQualifiedExpression.java index a83d09e5e36..6056522a065 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetSafeQualifiedExpression.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetSafeQualifiedExpression.java @@ -12,7 +12,12 @@ public class JetSafeQualifiedExpression extends JetQualifiedExpression { } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitSafeQualifiedExpression(this); } + + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitSafeQualifiedExpression(this, data); + } } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetSelfType.java b/idea/src/org/jetbrains/jet/lang/psi/JetSelfType.java index a234ce55ece..f71e3b39c32 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetSelfType.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetSelfType.java @@ -21,7 +21,12 @@ public class JetSelfType extends JetTypeElement { } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitSelfType(this); } + + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitSelfType(this, data); + } } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetSimpleNameExpression.java b/idea/src/org/jetbrains/jet/lang/psi/JetSimpleNameExpression.java index 26d06be9093..03ebff7e8a6 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetSimpleNameExpression.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetSimpleNameExpression.java @@ -157,8 +157,12 @@ public class JetSimpleNameExpression extends JetReferenceExpression { } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitSimpleNameExpression(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitSimpleNameExpression(this, data); + } } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetSimpleNameStringTemplateEntry.java b/idea/src/org/jetbrains/jet/lang/psi/JetSimpleNameStringTemplateEntry.java index b126b050107..a974ef16f1d 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetSimpleNameStringTemplateEntry.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetSimpleNameStringTemplateEntry.java @@ -17,4 +17,9 @@ public class JetSimpleNameStringTemplateEntry extends JetStringTemplateEntryWith public void accept(@NotNull JetVisitor visitor) { visitor.visitSimpleNameStringTemplateEntry(this); } + + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitSimpleNameStringTemplateEntry(this, data); + } } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetStringTemplateEntryWithExpression.java b/idea/src/org/jetbrains/jet/lang/psi/JetStringTemplateEntryWithExpression.java index 9114f373c87..1557131ebc1 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetStringTemplateEntryWithExpression.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetStringTemplateEntryWithExpression.java @@ -15,4 +15,9 @@ public abstract class JetStringTemplateEntryWithExpression extends JetStringTemp public void accept(@NotNull JetVisitor visitor) { visitor.visitStringTemplateEntryWithExpression(this); } + + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitStringTemplateEntryWithExpression(this, data); + } } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetStringTemplateExpression.java b/idea/src/org/jetbrains/jet/lang/psi/JetStringTemplateExpression.java index 9f935a0cdab..be6f55d2899 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetStringTemplateExpression.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetStringTemplateExpression.java @@ -12,10 +12,15 @@ public class JetStringTemplateExpression extends JetExpression { } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitStringTemplateExpression(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitStringTemplateExpression(this, data); + } + @NotNull public JetStringTemplateEntry[] getEntries() { return findChildrenByClass(JetStringTemplateEntry.class); diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetThisExpression.java b/idea/src/org/jetbrains/jet/lang/psi/JetThisExpression.java index 630f5e01c98..099b27d22b8 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetThisExpression.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetThisExpression.java @@ -15,10 +15,15 @@ public class JetThisExpression extends JetLabelQualifiedExpression { } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitThisExpression(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitThisExpression(this, data); + } + /** * class A : B, C { * override fun foo() { diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetThrowExpression.java b/idea/src/org/jetbrains/jet/lang/psi/JetThrowExpression.java index 4f61ea81d0e..3d3108b0111 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetThrowExpression.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetThrowExpression.java @@ -13,10 +13,15 @@ public class JetThrowExpression extends JetExpression { } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitThrowExpression(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitThrowExpression(this, data); + } + @Nullable @IfNotParsed public JetExpression getThrownExpression() { return findChildByClass(JetExpression.class); diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetTryExpression.java b/idea/src/org/jetbrains/jet/lang/psi/JetTryExpression.java index 4589f94ec69..27bc8668f87 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetTryExpression.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetTryExpression.java @@ -16,10 +16,15 @@ public class JetTryExpression extends JetExpression { } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitTryExpression(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitTryExpression(this, data); + } + @NotNull public JetBlockExpression getTryBlock() { return (JetBlockExpression) findChildByType(JetNodeTypes.BLOCK); diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetTupleExpression.java b/idea/src/org/jetbrains/jet/lang/psi/JetTupleExpression.java index b707e3c7a42..fbbe6086bf2 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetTupleExpression.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetTupleExpression.java @@ -15,10 +15,15 @@ public class JetTupleExpression extends JetExpression { } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitTupleExpression(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitTupleExpression(this, data); + } + public List getEntries() { return PsiTreeUtil.getChildrenOfTypeAsList(this, JetExpression.class); } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetTuplePattern.java b/idea/src/org/jetbrains/jet/lang/psi/JetTuplePattern.java index f887ef54183..3ea50bf4ba1 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetTuplePattern.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetTuplePattern.java @@ -19,6 +19,11 @@ public class JetTuplePattern extends JetPattern { visitor.visitTuplePattern(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitTuplePattern(this, data); + } + @NotNull public List getEntries() { return findChildrenByType(JetNodeTypes.TUPLE_PATTERN_ENTRY); diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetTupleType.java b/idea/src/org/jetbrains/jet/lang/psi/JetTupleType.java index 90dba74bcf5..9b1248b5175 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetTupleType.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetTupleType.java @@ -21,10 +21,15 @@ public class JetTupleType extends JetTypeElement { } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitTupleType(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitTupleType(this, data); + } + @NotNull public List getComponentTypeRefs() { return findChildrenByType(JetNodeTypes.TYPE_REFERENCE); diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetTypeArgumentList.java b/idea/src/org/jetbrains/jet/lang/psi/JetTypeArgumentList.java index 29b76a938e5..9e58f3cd658 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetTypeArgumentList.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetTypeArgumentList.java @@ -15,10 +15,15 @@ public class JetTypeArgumentList extends JetElement { } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitTypeArgumentList(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitTypeArgumentList(this, data); + } + public List getArguments() { return findChildrenByType(JetNodeTypes.TYPE_PROJECTION); } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetTypeConstraint.java b/idea/src/org/jetbrains/jet/lang/psi/JetTypeConstraint.java index 2e6fcacf5d6..088b42a0764 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetTypeConstraint.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetTypeConstraint.java @@ -16,10 +16,15 @@ public class JetTypeConstraint extends JetElement { } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitTypeConstraint(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitTypeConstraint(this, data); + } + public boolean isClassObjectContraint() { return findChildByType(JetTokens.CLASS_KEYWORD) != null && findChildByType(JetTokens.OBJECT_KEYWORD) != null; diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetTypeConstraintList.java b/idea/src/org/jetbrains/jet/lang/psi/JetTypeConstraintList.java index 4ad8ebf2d93..671519cb696 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetTypeConstraintList.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetTypeConstraintList.java @@ -15,10 +15,15 @@ public class JetTypeConstraintList extends JetElement { } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitTypeConstraintList(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitTypeConstraintList(this, data); + } + @NotNull public List getConstraints() { return findChildrenByType(JetNodeTypes.TYPE_CONSTRAINT); diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetTypeParameter.java b/idea/src/org/jetbrains/jet/lang/psi/JetTypeParameter.java index 9cc8409ccb7..a8cf0998c14 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetTypeParameter.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetTypeParameter.java @@ -16,10 +16,15 @@ public class JetTypeParameter extends JetNamedDeclaration { } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitTypeParameter(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitTypeParameter(this, data); + } + @NotNull public Variance getVariance() { JetModifierList modifierList = getModifierList(); diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetTypeParameterList.java b/idea/src/org/jetbrains/jet/lang/psi/JetTypeParameterList.java index 8f32e66e2ae..032d0fc4ff4 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetTypeParameterList.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetTypeParameterList.java @@ -19,7 +19,12 @@ public class JetTypeParameterList extends JetElement { } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitTypeParameterList(this); } + + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitTypeParameterList(this, data); + } } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetTypePattern.java b/idea/src/org/jetbrains/jet/lang/psi/JetTypePattern.java index 08bb92a47cd..f041419e4e2 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetTypePattern.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetTypePattern.java @@ -21,4 +21,9 @@ public class JetTypePattern extends JetPattern { public void accept(@NotNull JetVisitor visitor) { visitor.visitTypePattern(this); } + + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitTypePattern(this, data); + } } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetTypeProjection.java b/idea/src/org/jetbrains/jet/lang/psi/JetTypeProjection.java index ac860e5a351..e88eebe74f4 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetTypeProjection.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetTypeProjection.java @@ -32,6 +32,11 @@ public class JetTypeProjection extends JetDeclaration { visitor.visitTypeProjection(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitTypeProjection(this, data); + } + @Nullable public JetTypeReference getTypeReference() { return (JetTypeReference) findChildByType(JetNodeTypes.TYPE_REFERENCE); diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetTypeReference.java b/idea/src/org/jetbrains/jet/lang/psi/JetTypeReference.java index 86d6b1491dd..fe29c5300d8 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetTypeReference.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetTypeReference.java @@ -18,10 +18,15 @@ public class JetTypeReference extends JetElement { } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitTypeReference(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitTypeReference(this, data); + } + public List getAttributeAnnotations() { return findChildrenByType(JetNodeTypes.ANNOTATION); } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetTypedef.java b/idea/src/org/jetbrains/jet/lang/psi/JetTypedef.java index e738af0bd11..5b5f88ee346 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetTypedef.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetTypedef.java @@ -18,6 +18,11 @@ public class JetTypedef extends JetTypeParameterListOwner { visitor.visitTypedef(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitTypedef(this, data); + } + @Nullable @IfNotParsed public JetTypeReference getTypeReference() { return (JetTypeReference) findChildByType(JetNodeTypes.TYPE_REFERENCE); diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetUserType.java b/idea/src/org/jetbrains/jet/lang/psi/JetUserType.java index 22885044cb3..08450e7a092 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetUserType.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetUserType.java @@ -27,6 +27,11 @@ public class JetUserType extends JetTypeElement { visitor.visitUserType(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitUserType(this, data); + } + public JetTypeArgumentList getTypeArgumentList() { return (JetTypeArgumentList) findChildByType(JetNodeTypes.TYPE_ARGUMENT_LIST); } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetValueArgument.java b/idea/src/org/jetbrains/jet/lang/psi/JetValueArgument.java index e0a1bb009d8..497d61c18e6 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetValueArgument.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetValueArgument.java @@ -18,6 +18,11 @@ public class JetValueArgument extends JetElement implements ValueArgumentPsi { visitor.visitArgument(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitArgument(this, data); + } + @Nullable @IfNotParsed public JetExpression getArgumentExpression() { return findChildByClass(JetExpression.class); diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetValueArgumentList.java b/idea/src/org/jetbrains/jet/lang/psi/JetValueArgumentList.java index 1a00cf166d9..f46029eba2b 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetValueArgumentList.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetValueArgumentList.java @@ -15,10 +15,15 @@ public class JetValueArgumentList extends JetElement { } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitValueArgumentList(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitValueArgumentList(this, data); + } + public List getArguments() { return findChildrenByType(JetNodeTypes.VALUE_ARGUMENT); } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetWhenConditionCall.java b/idea/src/org/jetbrains/jet/lang/psi/JetWhenConditionCall.java index 490398f47bd..a4661e4e12d 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetWhenConditionCall.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetWhenConditionCall.java @@ -32,4 +32,9 @@ public class JetWhenConditionCall extends JetWhenCondition { public void accept(@NotNull JetVisitor visitor) { visitor.visitWhenConditionCall(this); } + + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitWhenConditionCall(this, data); + } } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetWhenConditionInRange.java b/idea/src/org/jetbrains/jet/lang/psi/JetWhenConditionInRange.java index 10bb6239a97..8a3efc12527 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetWhenConditionInRange.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetWhenConditionInRange.java @@ -39,6 +39,11 @@ public class JetWhenConditionInRange extends JetWhenCondition { visitor.visitWhenConditionInRange(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitWhenConditionInRange(this, data); + } + public JetSimpleNameExpression getOperationReference() { return (JetSimpleNameExpression) findChildByType(JetNodeTypes.OPERATION_REFERENCE); } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetWhenConditionIsPattern.java b/idea/src/org/jetbrains/jet/lang/psi/JetWhenConditionIsPattern.java index 55c0aacf85d..b1ccf6220fc 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetWhenConditionIsPattern.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetWhenConditionIsPattern.java @@ -26,4 +26,9 @@ public class JetWhenConditionIsPattern extends JetWhenCondition { public void accept(@NotNull JetVisitor visitor) { visitor.visitWhenConditionIsPattern(this); } + + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitWhenConditionIsPattern(this, data); + } } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetWhenEntry.java b/idea/src/org/jetbrains/jet/lang/psi/JetWhenEntry.java index da16d7b4cc5..ba298f990b0 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetWhenEntry.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetWhenEntry.java @@ -27,6 +27,11 @@ public class JetWhenEntry extends JetElement { visitor.visitWhenEntry(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitWhenEntry(this, data); + } + @NotNull public JetWhenCondition[] getConditions() { return findChildrenByClass(JetWhenCondition.class); diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetWhenExpression.java b/idea/src/org/jetbrains/jet/lang/psi/JetWhenExpression.java index ffa9289b922..b30c4dad652 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetWhenExpression.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetWhenExpression.java @@ -26,7 +26,12 @@ public class JetWhenExpression extends JetExpression { } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitWhenExpression(this); } + + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitWhenExpression(this, data); + } } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetWhileExpression.java b/idea/src/org/jetbrains/jet/lang/psi/JetWhileExpression.java index 23cecaa7f74..ddcce91b30d 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetWhileExpression.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetWhileExpression.java @@ -14,10 +14,15 @@ public class JetWhileExpression extends JetLoopExpression { } @Override - public void accept(JetVisitor visitor) { + public void accept(@NotNull JetVisitor visitor) { visitor.visitWhileExpression(this); } + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitWhileExpression(this, data); + } + @Nullable @IfNotParsed public JetExpression getCondition() { return findExpressionUnder(JetNodeTypes.CONDITION); diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetWildcardPattern.java b/idea/src/org/jetbrains/jet/lang/psi/JetWildcardPattern.java index dece9f0f43b..080ee5ac31e 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetWildcardPattern.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetWildcardPattern.java @@ -15,4 +15,9 @@ public class JetWildcardPattern extends JetPattern { public void accept(@NotNull JetVisitor visitor) { visitor.visitWildcardPattern(this); } + + @Override + public R visit(@NotNull JetExtendedVisitor visitor, D data) { + return visitor.visitWildcardPattern(this, data); + } } diff --git a/idea/src/org/jetbrains/jet/lang/resolve/BindingTraceContext.java b/idea/src/org/jetbrains/jet/lang/resolve/BindingTraceContext.java index ceb675124e2..b629e475a75 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/BindingTraceContext.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/BindingTraceContext.java @@ -119,7 +119,7 @@ public class BindingTraceContext implements BindingContext, BindingTrace { @Override public void recordCompileTimeValue(@NotNull JetExpression expression, @NotNull CompileTimeConstant value) { - safePut(compileTimeValues, expression, value); + safePut(compileTimeValues, expression, value, true); } @Override @@ -152,8 +152,13 @@ public class BindingTraceContext implements BindingContext, BindingTrace { } private void safePut(Map map, K key, V value) { + safePut(map, key, value, false); + } + + private void safePut(Map map, K key, V value, boolean canBeEquals) { V oldValue = map.put(key, value); - assert oldValue == null || oldValue == value : (key instanceof PsiElement ? key.toString() + " \"" + ((PsiElement) key).getText() + "\"" : key.toString()) + " -> " + oldValue + " and " + value; + assert oldValue == null || oldValue == value || (!canBeEquals || oldValue.equals(value)) : + (key instanceof PsiElement ? key.toString() + " \"" + ((PsiElement) key).getText() + "\"" : key.toString()) + " -> " + oldValue + " and " + value; } @Override diff --git a/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java b/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java index d2f20c3e008..e7fe8dabbce 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java @@ -733,7 +733,7 @@ public class TopDownAnalyzer { JetFlowInformationProvider flowInformationProvider = classDescriptorResolver.computeFlowData(declaration, bodyExpression); JetTypeInferrer.Services typeInferrer = semanticServices.getTypeInferrerServices(traceForConstructors, flowInformationProvider); - typeInferrer.checkFunctionReturnType(functionInnerScope, declaration, descriptor, JetStandardClasses.getUnitType()); + typeInferrer.checkFunctionReturnType(functionInnerScope, declaration, JetStandardClasses.getUnitType()); } } diff --git a/idea/src/org/jetbrains/jet/lang/resolve/TypeResolver.java b/idea/src/org/jetbrains/jet/lang/resolve/TypeResolver.java index 8e3ea61ce2a..97e07aa592d 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/TypeResolver.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/TypeResolver.java @@ -93,7 +93,7 @@ public class TypeResolver { String errorMessage = (expectedArgumentCount == 0 ? "No" : expectedArgumentCount) + " type arguments expected"; if (actualArgumentCount == 0) { trace.getErrorHandler().genericError(type.getNode(), errorMessage); - } else if (expectedArgumentCount == 0) { + } else { trace.getErrorHandler().genericError(type.getTypeArgumentList().getNode(), errorMessage); } } else { diff --git a/idea/src/org/jetbrains/jet/lang/resolve/constants/IntValue.java b/idea/src/org/jetbrains/jet/lang/resolve/constants/IntValue.java index d5b251d50f4..93abe0110e8 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/constants/IntValue.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/constants/IntValue.java @@ -45,4 +45,21 @@ public class IntValue implements CompileTimeConstant { public String toString() { return value + ".int"; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + IntValue intValue = (IntValue) o; + + if (value != intValue.value) return false; + + return true; + } + + @Override + public int hashCode() { + return value; + } } diff --git a/idea/src/org/jetbrains/jet/lang/resolve/constants/StringValue.java b/idea/src/org/jetbrains/jet/lang/resolve/constants/StringValue.java index b523200769f..bdb63177728 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/constants/StringValue.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/constants/StringValue.java @@ -36,4 +36,21 @@ public class StringValue implements CompileTimeConstant { public String toString() { return "\"" + value + "\""; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + StringValue that = (StringValue) o; + + if (value != null ? !value.equals(that.value) : that.value != null) return false; + + return true; + } + + @Override + public int hashCode() { + return value != null ? value.hashCode() : 0; + } } diff --git a/idea/src/org/jetbrains/jet/lang/types/DataFlowInfo.java b/idea/src/org/jetbrains/jet/lang/types/DataFlowInfo.java index 8cf34eb367a..43df5303f56 100644 --- a/idea/src/org/jetbrains/jet/lang/types/DataFlowInfo.java +++ b/idea/src/org/jetbrains/jet/lang/types/DataFlowInfo.java @@ -67,7 +67,21 @@ public class DataFlowInfo { @NotNull public List getPossibleTypes(VariableDescriptor variableDescriptor) { - return typeInfo.get(variableDescriptor); + List types = typeInfo.get(variableDescriptor); + NullabilityFlags nullabilityFlags = nullabilityInfo.get(variableDescriptor); + if (nullabilityFlags == null || nullabilityFlags.canBeNull()) { + return types; + } + List enrichedTypes = Lists.newArrayListWithCapacity(types.size()); + for (JetType type: types) { + if (type.isNullable()) { + enrichedTypes.add(TypeUtils.makeNotNullable(type)); + } + else { + enrichedTypes.add(type); + } + } + return enrichedTypes; } public DataFlowInfo equalsToNull(@NotNull VariableDescriptor variableDescriptor, boolean notNull) { @@ -76,7 +90,9 @@ public class DataFlowInfo { private ImmutableMap getEqualsToNullMap(VariableDescriptor variableDescriptor, boolean notNull) { Map builder = Maps.newHashMap(nullabilityInfo); - builder.put(variableDescriptor, new NullabilityFlags(!notNull, notNull)); + NullabilityFlags nullabilityFlags = nullabilityInfo.get(variableDescriptor); + boolean varNotNull = notNull || (nullabilityFlags != null && !nullabilityFlags.canBeNull); + builder.put(variableDescriptor, new NullabilityFlags(!varNotNull, varNotNull)); return ImmutableMap.copyOf(builder); } @@ -85,7 +101,9 @@ public class DataFlowInfo { Map builder = Maps.newHashMap(nullabilityInfo); for (VariableDescriptor variableDescriptor : variableDescriptors) { if (variableDescriptor != null) { - builder.put(variableDescriptor, new NullabilityFlags(!notNull, notNull)); + NullabilityFlags nullabilityFlags = nullabilityInfo.get(variableDescriptor); + boolean varNotNull = notNull || (nullabilityFlags != null && !nullabilityFlags.canBeNull); + builder.put(variableDescriptor, new NullabilityFlags(!varNotNull, varNotNull)); } } return ImmutableMap.copyOf(builder); diff --git a/idea/src/org/jetbrains/jet/lang/types/DeferredType.java b/idea/src/org/jetbrains/jet/lang/types/DeferredType.java index f7c55933704..fae49326ec9 100644 --- a/idea/src/org/jetbrains/jet/lang/types/DeferredType.java +++ b/idea/src/org/jetbrains/jet/lang/types/DeferredType.java @@ -55,7 +55,11 @@ public class DeferredType implements JetType { @Override public String toString() { try { - return getActualType().toString(); + if (lazyValue.isComputed()) { + return getActualType().toString(); + } else { + return ""; + } } catch (ReenteringLazyValueComputationException e) { return ""; diff --git a/idea/src/org/jetbrains/jet/lang/types/JetStandardClasses.java b/idea/src/org/jetbrains/jet/lang/types/JetStandardClasses.java index c45f0416850..99908070b95 100644 --- a/idea/src/org/jetbrains/jet/lang/types/JetStandardClasses.java +++ b/idea/src/org/jetbrains/jet/lang/types/JetStandardClasses.java @@ -104,6 +104,8 @@ public class JetStandardClasses { //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// public static final int TUPLE_COUNT = 22; + + private static final Set TUPLE_CONSTRUCTORS = Sets.newHashSet(); private static final ClassDescriptor[] TUPLE = new ClassDescriptor[TUPLE_COUNT]; static { @@ -126,6 +128,7 @@ public class JetStandardClasses { STUB, STUB_FG, null); // TODO : constructor + TUPLE_CONSTRUCTORS.add(TUPLE[i].getTypeConstructor()); } } @@ -301,6 +304,10 @@ public class JetStandardClasses { public static JetType getTupleType(JetType... arguments) { return getTupleType(Collections.emptyList(), Arrays.asList(arguments)); } + + public static boolean isTupleType(@NotNull JetType type) { + return TUPLE_CONSTRUCTORS.contains(type.getConstructor()); + } public static JetType getLabeledTupleType(List annotations, List arguments) { // TODO diff --git a/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java b/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java index 16bd14fbe77..d68fe0b66d3 100644 --- a/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java +++ b/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java @@ -131,7 +131,7 @@ public class JetTypeInferrer { private final JetFlowInformationProvider flowInformationProvider; private final Map patternsToDataFlowInfo = Maps.newHashMap(); private final Map> patternsToBoundVariableLists = Maps.newHashMap(); - + public JetTypeInferrer(@NotNull JetFlowInformationProvider flowInformationProvider, @NotNull JetSemanticServices semanticServices) { this.semanticServices = semanticServices; this.flowInformationProvider = flowInformationProvider; @@ -148,12 +148,21 @@ public class JetTypeInferrer { private final CompileTimeConstantResolver compileTimeConstantResolver; private final AnnotationResolver annotationResolver; + private final TypeInferrerVisitor typeInferrerVisitor; + private final TypeInferrerVisitorWithNamespaces typeInferrerVisitorWithNamespaces; + private Services(BindingTrace trace) { this.trace = trace; this.annotationResolver = new AnnotationResolver(semanticServices, trace); this.typeResolver = new TypeResolver(semanticServices, trace, true); this.classDescriptorResolver = semanticServices.getClassDescriptorResolver(trace); this.compileTimeConstantResolver = new CompileTimeConstantResolver(semanticServices, trace); + this.typeInferrerVisitor = new TypeInferrerVisitor(); + this.typeInferrerVisitorWithNamespaces = new TypeInferrerVisitorWithNamespaces(); + } + + public TypeInferrerVisitorWithWritableScope newTypeInferrerVisitorWithWritableScope(WritableScope scope) { + return new TypeInferrerVisitorWithWritableScope(scope); } @NotNull @@ -167,11 +176,11 @@ public class JetTypeInferrer { @Nullable public JetType getType(@NotNull final JetScope scope, @NotNull JetExpression expression, boolean preferBlock, @NotNull JetType expectedType) { - return new TypeInferrerVisitor(new TypeInferenceContext(trace, scope, preferBlock, DataFlowInfo.getEmpty(), expectedType, FORBIDDEN)).getType(expression); + return typeInferrerVisitor.getType(expression, new TypeInferenceContext(trace, scope, this, preferBlock, DataFlowInfo.getEmpty(), expectedType, FORBIDDEN)); } public JetType getTypeWithNamespaces(@NotNull final JetScope scope, @NotNull JetExpression expression, boolean preferBlock) { - return new TypeInferrerVisitorWithNamespaces(new TypeInferenceContext(trace, scope, preferBlock, DataFlowInfo.getEmpty(), NO_EXPECTED_TYPE, null)).getType(expression); + return typeInferrerVisitorWithNamespaces.getType(expression, new TypeInferenceContext(trace, scope, this, preferBlock, DataFlowInfo.getEmpty(), NO_EXPECTED_TYPE, NO_EXPECTED_TYPE)); } @Nullable @@ -351,9 +360,16 @@ public class JetTypeInferrer { } public void checkFunctionReturnType(@NotNull JetScope outerScope, @NotNull JetDeclarationWithBody function, @NotNull FunctionDescriptor functionDescriptor) { - final JetType expectedReturnType = functionDescriptor.getReturnType(); + checkFunctionReturnType(outerScope, function, functionDescriptor, DataFlowInfo.getEmpty()); + } + + private void checkFunctionReturnType(@NotNull JetScope outerScope, @NotNull JetDeclarationWithBody function, @NotNull FunctionDescriptor functionDescriptor, DataFlowInfo dataFlowInfo) { + JetType expectedReturnType = functionDescriptor.getReturnType(); + if (!function.hasBlockBody() && !function.hasDeclaredReturnType()) { + expectedReturnType = NO_EXPECTED_TYPE; + } JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(outerScope, functionDescriptor, trace); - checkFunctionReturnType(functionInnerScope, function, functionDescriptor, expectedReturnType); + checkFunctionReturnType(functionInnerScope, function, expectedReturnType, dataFlowInfo); // Map typeMap = collectReturnedExpressionsWithTypes(outerScope, function, functionDescriptor, expectedReturnType); // if (typeMap.isEmpty()) { // return; // The function returns Nothing @@ -387,18 +403,21 @@ public class JetTypeInferrer { // } } - public void checkFunctionReturnType(JetScope functionInnerScope, JetDeclarationWithBody function, FunctionDescriptor functionDescriptor, @Nullable final JetType expectedReturnType) { + public void checkFunctionReturnType(JetScope functionInnerScope, JetDeclarationWithBody function, @NotNull final JetType expectedReturnType) { + checkFunctionReturnType(functionInnerScope, function, expectedReturnType, DataFlowInfo.getEmpty()); + } + + private void checkFunctionReturnType(JetScope functionInnerScope, JetDeclarationWithBody function, @NotNull final JetType expectedReturnType, @NotNull DataFlowInfo dataFlowInfo) { JetExpression bodyExpression = function.getBodyExpression(); assert bodyExpression != null; - JetType returnedType = new TypeInferrerVisitor(new TypeInferenceContext(trace, functionInnerScope, function.hasBlockBody(), DataFlowInfo.getEmpty(), NO_EXPECTED_TYPE, expectedReturnType)).getType(bodyExpression); - + final boolean blockBody = function.hasBlockBody(); - if (!blockBody && expectedReturnType != null && returnedType != null) { - if (!semanticServices.getTypeChecker().isSubtypeOf(returnedType, expectedReturnType)) { - trace.getErrorHandler().typeMismatch(bodyExpression, expectedReturnType, returnedType); - } - } + final TypeInferenceContext context = + blockBody + ? new TypeInferenceContext(trace, functionInnerScope, this, function.hasBlockBody(), dataFlowInfo, NO_EXPECTED_TYPE, expectedReturnType) + : new TypeInferenceContext(trace, functionInnerScope, this, function.hasBlockBody(), dataFlowInfo, expectedReturnType, FORBIDDEN); + typeInferrerVisitor.getType(bodyExpression, context); List unreachableElements = Lists.newArrayList(); flowInformationProvider.collectUnreachableExpressions(function.asElement(), unreachableElements); @@ -421,7 +440,7 @@ public class JetTypeInferrer { returnedExpressions.remove(function); // This will be the only "expression" if the body is empty - if (!JetStandardClasses.isUnit(expectedReturnType) && returnedExpressions.isEmpty() && !nothingReturned) { + if (expectedReturnType != NO_EXPECTED_TYPE && !JetStandardClasses.isUnit(expectedReturnType) && returnedExpressions.isEmpty() && !nothingReturned) { trace.getErrorHandler().genericError(bodyExpression.getNode(), "This function must return a value of type " + expectedReturnType); } @@ -437,7 +456,11 @@ public class JetTypeInferrer { @Override public void visitExpression(JetExpression expression) { if (blockBody && !JetStandardClasses.isUnit(expectedReturnType) && !rootUnreachableElements.contains(expression)) { - trace.getErrorHandler().genericError(expression.getNode(), "A 'return' expression required in a function with a block body ('{...}')"); + //TODO move to pseudocode + JetType type = typeInferrerVisitor.getType(expression, context.replaceExpectedType(NO_EXPECTED_TYPE)); + if (type == null || !JetStandardClasses.isNothing(type)) { + trace.getErrorHandler().genericError(expression.getNode(), "A 'return' expression required in a function with a block body ('{...}')"); + } } } }); @@ -461,7 +484,7 @@ public class JetTypeInferrer { JetExpression bodyExpression = function.getBodyExpression(); assert bodyExpression != null; JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(outerScope, functionDescriptor, trace); - new TypeInferrerVisitor(new TypeInferenceContext(trace, functionInnerScope, function.hasBlockBody(), DataFlowInfo.getEmpty(), NO_EXPECTED_TYPE, FORBIDDEN)).getType(bodyExpression); + typeInferrerVisitor.getType(bodyExpression, new TypeInferenceContext(trace, functionInnerScope, this, function.hasBlockBody(), DataFlowInfo.getEmpty(), NO_EXPECTED_TYPE, FORBIDDEN)); Collection returnedExpressions = new ArrayList(); Collection elementsReturningUnit = new ArrayList(); flowInformationProvider.collectReturnedInformation(function.asElement(), returnedExpressions, elementsReturningUnit); @@ -479,32 +502,33 @@ public class JetTypeInferrer { return typeMap; } - private JetType getBlockReturnedTypeWithWritableScope(@NotNull WritableScope scope, @NotNull List block, DataFlowInfo dataFlowInfo, JetType extectedReturnType) { + private JetType getBlockReturnedTypeWithWritableScope(@NotNull WritableScope scope, @NotNull List block, TypeInferenceContext context) { if (block.isEmpty()) { return JetStandardClasses.getUnitType(); } - TypeInferrerVisitorWithWritableScope blockLevelVisitor = new TypeInferrerVisitorWithWritableScope(scope, new TypeInferenceContext(trace, scope, true, dataFlowInfo, NO_EXPECTED_TYPE, extectedReturnType)); + TypeInferrerVisitorWithWritableScope blockLevelVisitor = newTypeInferrerVisitorWithWritableScope(scope); + TypeInferenceContext newContext = new TypeInferenceContext(trace, scope, this, true, context.dataFlowInfo, NO_EXPECTED_TYPE, context.expectedReturnType); JetType result = null; - for (JetElement statement : block) { + for (Iterator iterator = block.iterator(); iterator.hasNext(); ) { + JetElement statement = iterator.next(); trace.recordStatement(statement); JetExpression statementExpression = (JetExpression) statement; - result = blockLevelVisitor.getType(statementExpression); + //TODO constructor assert context.expectedType != FORBIDDEN : "" + if (!iterator.hasNext() && context.expectedType != NO_EXPECTED_TYPE) { + newContext = new TypeInferenceContext(trace, scope, this, true, newContext.dataFlowInfo, context.expectedType, context.expectedReturnType); + } + + result = blockLevelVisitor.getType(statementExpression, newContext); DataFlowInfo newDataFlowInfo = blockLevelVisitor.getResultingDataFlowInfo(); if (newDataFlowInfo == null) { - newDataFlowInfo = dataFlowInfo; + newDataFlowInfo = context.dataFlowInfo; } - // WritableScope newScope = blockLevelVisitor.getResultScope(); - // if (newScope == null) { - // newScope = scope; - // } - if (newDataFlowInfo != dataFlowInfo) {// || newScope != scope) { - blockLevelVisitor = new TypeInferrerVisitorWithWritableScope(scope, new TypeInferenceContext(trace, scope, true, newDataFlowInfo, NO_EXPECTED_TYPE, extectedReturnType)); - } - else { - blockLevelVisitor.resetResult(); // TODO : maybe it's better to recreate the visitors with the same scope? + if (newDataFlowInfo != context.dataFlowInfo) { + newContext = new TypeInferenceContext(trace, scope, this, true, newDataFlowInfo, NO_EXPECTED_TYPE, context.expectedReturnType); } + blockLevelVisitor.resetResult(); // TODO : maybe it's better to recreate the visitors with the same scope? } return result; } @@ -712,6 +736,114 @@ public class JetTypeInferrer { // Automatic upcast: // result = receiverType; } + + //TODO + private JetType enrichOutType(JetExpression expression, JetType initialType, @NotNull TypeInferenceContext context) { + if (expression == null) return initialType; + VariableDescriptor variableDescriptor = getVariableDescriptorFromSimpleName(expression, context); + if (variableDescriptor != null) { + return context.dataFlowInfo.getOutType(variableDescriptor); + } + return initialType; + } + + @Nullable + private JetType checkType(@Nullable JetType expressionType, @NotNull JetExpression expression, @NotNull TypeInferenceContext context) { + if (expressionType != null && context.expectedType != null && context.expectedType != NO_EXPECTED_TYPE) { + if (!semanticServices.getTypeChecker().isSubtypeOf(expressionType, context.expectedType)) { + context.trace.getErrorHandler().typeMismatch(expression, context.expectedType, expressionType); + } + } + return expressionType; + } + +// @Nullable +// private JetType enrichType(@NotNull JetExpression expression, @Nullable JetType initialType, @NotNull TypeInferenceContext context) { +// if (initialType == null || context.expectedType == null || context.expectedType == NO_EXPECTED_TYPE) { +// return initialType; +// } +// VariableDescriptor variableDescriptor = getVariableDescriptorFromSimpleName(expression, context); +// if (variableDescriptor == null) return initialType; +// JetType enrichedType = null; +// List possibleTypes = Lists.newArrayList(context.dataFlowInfo.getPossibleTypes(variableDescriptor)); +// Collections.reverse(possibleTypes); +// for (JetType possibleType: possibleTypes) { +// if (semanticServices.getTypeChecker().isSubtypeOf(possibleType, context.expectedType)) { +// enrichedType = possibleType; +// break; +// } +// } +// if (enrichedType == null) { +// enrichedType = context.dataFlowInfo.getOutType(variableDescriptor); +// } +// if (enrichedType == null) return initialType; +// return enrichedType; +// } + + @Nullable + private JetType checkEnrichedType(@Nullable JetType expressionType, @NotNull JetExpression expression, @NotNull TypeInferenceContext context) { + if (expressionType == null || context.expectedType == null || context.expectedType == NO_EXPECTED_TYPE || + semanticServices.getTypeChecker().isSubtypeOf(expressionType, context.expectedType)) { + return expressionType; + } + VariableDescriptor variableDescriptor = getVariableDescriptorFromSimpleName(expression, context); + if (variableDescriptor == null) return expressionType; + + JetType enrichedType = null; + List possibleTypes = Lists.newArrayList(context.dataFlowInfo.getPossibleTypes(variableDescriptor)); + Collections.reverse(possibleTypes); + for (JetType possibleType: possibleTypes) { + if (semanticServices.getTypeChecker().isSubtypeOf(possibleType, context.expectedType)) { + enrichedType = possibleType; + break; + } + } + if (enrichedType == null) { + enrichedType = context.dataFlowInfo.getOutType(variableDescriptor); + } + if (enrichedType == null) { + enrichedType = expressionType; + } + + if (!semanticServices.getTypeChecker().isSubtypeOf(enrichedType, context.expectedType)) { + context.trace.getErrorHandler().typeMismatch(expression, context.expectedType, expressionType); + } else { + context.trace.recordAutoCast(expression, enrichedType); + } + return enrichedType; + } + + @NotNull + private List checkArgumentTypes(@NotNull List argumentTypes, @NotNull List arguments, @NotNull List expectedArgumentTypes, @NotNull TypeInferenceContext context) { + if (arguments.size() == 0 || argumentTypes.size() != arguments.size() || expectedArgumentTypes.size() != arguments.size()) { + return argumentTypes; + } + List result = Lists.newArrayListWithCapacity(arguments.size()); + for (int i = 0, argumentTypesSize = argumentTypes.size(); i < argumentTypesSize; i++) { + result.add(checkEnrichedType(argumentTypes.get(i), arguments.get(i), context.replaceExpectedType(expectedArgumentTypes.get(i).getType()))); + } + return result; + } + + @Nullable + private VariableDescriptor getVariableDescriptorFromSimpleName(@NotNull JetExpression receiverExpression, @NotNull TypeInferenceContext context) { + if (receiverExpression instanceof JetBinaryExpressionWithTypeRHS) { + JetBinaryExpressionWithTypeRHS expression = (JetBinaryExpressionWithTypeRHS) receiverExpression; + if (expression.getOperationSign().getReferencedNameElementType() == JetTokens.COLON) { + return getVariableDescriptorFromSimpleName(expression.getLeft(), context); + } + } + VariableDescriptor variableDescriptor = null; + if (receiverExpression instanceof JetSimpleNameExpression) { + JetSimpleNameExpression nameExpression = (JetSimpleNameExpression) receiverExpression; + DeclarationDescriptor declarationDescriptor = context.trace.getBindingContext().resolveReferenceExpression(nameExpression); + if (declarationDescriptor instanceof VariableDescriptor) { + variableDescriptor = (VariableDescriptor) declarationDescriptor; + } + } + return variableDescriptor; + } + } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -722,6 +854,7 @@ public class JetTypeInferrer { public final ClassDescriptorResolver classDescriptorResolver; public final JetScope scope; + public final Services services; public final boolean preferBlock; public final DataFlowInfo dataFlowInfo; @@ -731,80 +864,64 @@ public class JetTypeInferrer { private TypeInferenceContext( @NotNull BindingTrace trace, @NotNull JetScope scope, + @NotNull Services services, boolean preferBlock, @NotNull DataFlowInfo dataFlowInfo, @NotNull JetType expectedType, - @Nullable JetType expectedReturnType) { + @NotNull JetType expectedReturnType) { this.trace = trace; this.typeResolver = new TypeResolver(semanticServices, trace, true); this.classDescriptorResolver = semanticServices.getClassDescriptorResolver(trace); this.scope = scope; + this.services = services; this.preferBlock = preferBlock; this.dataFlowInfo = dataFlowInfo; this.expectedType = expectedType; this.expectedReturnType = expectedReturnType; + } public TypeInferenceContext replaceDataFlowInfo(DataFlowInfo newDataFlowInfo) { - return new TypeInferenceContext(trace, scope, preferBlock, newDataFlowInfo, expectedType, expectedReturnType); + return new TypeInferenceContext(trace, scope, services, preferBlock, newDataFlowInfo, expectedType, expectedReturnType); + } + + public TypeInferenceContext replaceExpectedType(@NotNull JetType newExpectedType) { + if (expectedType == newExpectedType) return this; + return new TypeInferenceContext(trace, scope, services, preferBlock, dataFlowInfo, newExpectedType, expectedReturnType); + } + + public TypeInferenceContext replaceExpectedReturnType(@NotNull JetType newExpectedReturnType) { + if (expectedReturnType == newExpectedReturnType) return this; + return new TypeInferenceContext(trace, scope, services, preferBlock, dataFlowInfo, expectedType, newExpectedReturnType); } } - private class TypeInferrerVisitor extends JetVisitor { + private class TypeInferrerVisitor extends JetExtendedVisitor { - protected final TypeInferenceContext context; - protected final Services services; - - protected JetType result; protected DataFlowInfo resultDataFlowInfo; - - private TypeInferrerVisitor(@NotNull TypeInferenceContext context) { - this.context = context; - this.services = new Services(context.trace); - } - - @NotNull - public TypeInferrerVisitor createNew(@NotNull TypeInferenceContext context) { - return new TypeInferrerVisitor(context); - } - @Nullable public DataFlowInfo getResultingDataFlowInfo() { return resultDataFlowInfo; } @Nullable - public JetType getType(@NotNull JetScope scope, @NotNull JetExpression expression, boolean preferBlock) { - return getTypeWithNewContext(expression, new TypeInferenceContext(context.trace, scope, preferBlock, context.dataFlowInfo, context.expectedType, context.expectedReturnType)); + public JetType getType(@NotNull JetScope scope, @NotNull JetExpression expression, boolean preferBlock, TypeInferenceContext context) { + return getType(expression, new TypeInferenceContext(context.trace, scope, context.services, preferBlock, context.dataFlowInfo, context.expectedType, context.expectedReturnType)); } - private JetType getTypeWithNewDataFlowInfo(JetScope scope, JetExpression expression, boolean preferBlock, @NotNull DataFlowInfo newDataFlowInfo) { - return getTypeWithNewContext(expression, new TypeInferenceContext(context.trace, scope, preferBlock, newDataFlowInfo, context.expectedType, context.expectedReturnType)); + private JetType getTypeWithNewDataFlowInfo(JetScope scope, JetExpression expression, boolean preferBlock, @NotNull DataFlowInfo newDataFlowInfo, TypeInferenceContext context) { + return getType(expression, new TypeInferenceContext(context.trace, scope, context.services, preferBlock, newDataFlowInfo, context.expectedType, context.expectedReturnType)); } @Nullable - public JetType getTypeWithNewContext(@NotNull JetExpression expression, @NotNull TypeInferenceContext newContext) { - TypeInferrerVisitor visitor; - if (newContext.equals(context)) { - visitor = this; - } - else { - visitor = createNew(newContext); - } - JetType type = visitor.getType(expression); - visitor.result = null; - return type; - } - - @Nullable - public final JetType getType(@NotNull JetExpression expression) { - assert result == null; + public final JetType getType(@NotNull JetExpression expression, TypeInferenceContext context) { if (context.trace.isProcessed(expression)) { return context.trace.getBindingContext().getExpressionType(expression); } + JetType result; try { - expression.accept(this); + result = expression.visit(this, context); // Some recursive definitions (object expressions) must put their types in the cache manually: if (context.trace.isProcessed(expression)) { return context.trace.getBindingContext().getExpressionType(expression); @@ -816,7 +933,7 @@ public class JetTypeInferrer { if (result != null) { context.trace.recordExpressionType(expression, result); if (JetStandardClasses.isNothing(result) && !result.isNullable()) { - markDominatedExpressionsAsUnreachable(expression); + markDominatedExpressionsAsUnreachable(expression, context); } } } @@ -833,14 +950,14 @@ public class JetTypeInferrer { } public void resetResult() { - result = null; +// result = null; resultDataFlowInfo = null; // resultScope = null; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - private void markDominatedExpressionsAsUnreachable(JetExpression expression) { + private void markDominatedExpressionsAsUnreachable(JetExpression expression, TypeInferenceContext context) { List dominated = new ArrayList(); flowInformationProvider.collectDominatedExpressions(expression, dominated); Set rootExpressions = JetPsiUtil.findRootExpressions(dominated); @@ -851,20 +968,21 @@ public class JetTypeInferrer { } @Nullable - private JetType getBlockReturnedType(@NotNull JetScope outerScope, @NotNull List block, DataFlowInfo dataFlowInfo, JetType extectedReturnType) { + private JetType getBlockReturnedType(@NotNull JetScope outerScope, @NotNull JetBlockExpression expression, TypeInferenceContext context) { + List block = expression.getStatements(); if (block.isEmpty()) { - return JetStandardClasses.getUnitType(); + return context.services.checkType(JetStandardClasses.getUnitType(), expression, context); } DeclarationDescriptor containingDescriptor = outerScope.getContainingDeclaration(); WritableScope scope = new WritableScopeImpl(outerScope, containingDescriptor, context.trace.getErrorHandler()).setDebugName("getBlockReturnedType"); - return services.getBlockReturnedTypeWithWritableScope(scope, block, dataFlowInfo, extectedReturnType); + return context.services.getBlockReturnedTypeWithWritableScope(scope, block, context); } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @Override - public void visitSimpleNameExpression(JetSimpleNameExpression expression) { + public JetType visitSimpleNameExpression(JetSimpleNameExpression expression, TypeInferenceContext context) { // TODO : other members // TODO : type substitutions??? String referencedName = expression.getReferencedName(); @@ -876,7 +994,7 @@ public class JetTypeInferrer { } else { context.trace.recordReferenceResolution(expression, property); - result = property.getOutType(); + return context.services.checkEnrichedType(property.getOutType(), expression, context); } } else { @@ -885,16 +1003,17 @@ public class JetTypeInferrer { VariableDescriptor variable = context.scope.getVariable(referencedName); if (variable != null) { context.trace.recordReferenceResolution(expression, variable); - result = variable.getOutType(); + JetType result = variable.getOutType(); if (result == null) { context.trace.getErrorHandler().genericError(expression.getNode(), "This variable is not readable in this context"); } - return; + return context.services.checkEnrichedType(result, expression, context); } else { ClassifierDescriptor classifier = context.scope.getClassifier(referencedName); if (classifier != null) { JetType classObjectType = classifier.getClassObjectType(); + JetType result = null; if (classObjectType != null && (isNamespacePosition() || classifier.isClassObjectAValue())) { result = classObjectType; } @@ -902,32 +1021,48 @@ public class JetTypeInferrer { context.trace.getErrorHandler().genericError(expression.getNode(), "Classifier " + classifier.getName() + " does not have a class object"); } context.trace.recordReferenceResolution(expression, classifier); - return; + return context.services.checkEnrichedType(result, expression, context); } - else if (furtherNameLookup(expression, referencedName)) { - return; + else { + //TODO + LookupResult result = furtherNameLookup(expression, referencedName, context); + if (result.found) { + return context.services.checkEnrichedType(result.type, expression, context); + } + } } context.trace.getErrorHandler().unresolvedReference(expression); } } + return null; } public boolean isNamespacePosition() { return false; } + + protected class LookupResult { + private final JetType type; + private final boolean found; - protected boolean furtherNameLookup(@NotNull JetSimpleNameExpression expression, @NotNull String referencedName) { - NamespaceType namespaceType = lookupNamespaceType(expression, referencedName); + LookupResult(JetType type, boolean found) { + this.type = type; + this.found = found; + } + } + + protected LookupResult furtherNameLookup(@NotNull JetSimpleNameExpression expression, @NotNull String referencedName, TypeInferenceContext context) { + NamespaceType namespaceType = lookupNamespaceType(expression, referencedName, context); if (namespaceType != null) { context.trace.getErrorHandler().genericError(expression.getNode(), "Expression expected, but a namespace name found"); - return true; + return new LookupResult(null, true); } - return false; + return new LookupResult(null, false); } @Nullable - protected NamespaceType lookupNamespaceType(@NotNull JetSimpleNameExpression expression, @NotNull String referencedName) { + protected NamespaceType lookupNamespaceType(@NotNull JetSimpleNameExpression expression, @NotNull String referencedName, TypeInferenceContext context) { NamespaceDescriptor namespace = context.scope.getNamespace(referencedName); if (namespace == null) { return null; @@ -937,7 +1072,8 @@ public class JetTypeInferrer { } @Override - public void visitObjectLiteralExpression(final JetObjectLiteralExpression expression) { + public JetType visitObjectLiteralExpression(final JetObjectLiteralExpression expression, final TypeInferenceContext context) { + final JetType[] result = new JetType[1]; TopDownAnalyzer topDownAnalyzer = new TopDownAnalyzer(semanticServices, new BindingTraceAdapter(context.trace) { @Override public void recordDeclarationResolution(@NotNull PsiElement declaration, @NotNull final DeclarationDescriptor descriptor) { @@ -948,7 +1084,7 @@ public class JetTypeInferrer { return ((ClassDescriptor) descriptor).getDefaultType(); } }); - result = defaultType; + result[0] = defaultType; if (!context.trace.isProcessed(expression)) { recordExpressionType(expression, defaultType); markAsProcessed(expression); @@ -958,15 +1094,16 @@ public class JetTypeInferrer { } }); topDownAnalyzer.processObject(context.scope, context.scope.getContainingDeclaration(), expression.getObjectDeclaration()); + return context.services.checkType(result[0], expression, context); } @Override - public void visitFunctionLiteralExpression(JetFunctionLiteralExpression expression) { + public JetType visitFunctionLiteralExpression(JetFunctionLiteralExpression expression, TypeInferenceContext contextWithExpectedType) { + TypeInferenceContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE); JetFunctionLiteral functionLiteral = expression.getFunctionLiteral(); if (context.preferBlock && !functionLiteral.hasParameterSpecification()) { context.trace.recordBlock(expression); - result = getBlockReturnedType(context.scope, functionLiteral.getBodyExpression().getStatements(), context.dataFlowInfo, context.expectedReturnType); - return; + return context.services.checkType(getBlockReturnedType(context.scope, functionLiteral.getBodyExpression(), contextWithExpectedType), expression, contextWithExpectedType); } JetTypeReference receiverTypeRef = functionLiteral.getReceiverTypeRef(); @@ -1004,39 +1141,38 @@ public class JetTypeInferrer { functionDescriptor.initialize(effectiveReceiverType, Collections.emptyList(), valueParameterDescriptors, null); context.trace.recordDeclarationResolution(expression, functionDescriptor); + JetType returnType = NO_EXPECTED_TYPE; + JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(context.scope, functionDescriptor, context.trace); JetTypeReference returnTypeRef = functionLiteral.getReturnTypeRef(); - JetType returnType; if (returnTypeRef != null) { returnType = context.typeResolver.resolveType(context.scope, returnTypeRef); - JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(context.scope, functionDescriptor, context.trace); - services.checkFunctionReturnType(functionInnerScope, expression, functionDescriptor, returnType); + context.services.checkFunctionReturnType(functionInnerScope, expression, returnType, context.dataFlowInfo); } else { - JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(context.scope, functionDescriptor, context.trace); - returnType = getBlockReturnedType(functionInnerScope, functionLiteral.getBodyExpression().getStatements(), context.dataFlowInfo, context.expectedReturnType); + if (contextWithExpectedType.expectedType != NO_EXPECTED_TYPE && JetStandardClasses.isFunctionType(contextWithExpectedType.expectedType)) { + returnType = JetStandardClasses.getReturnType(contextWithExpectedType.expectedType); + } + returnType = getBlockReturnedType(functionInnerScope, functionLiteral.getBodyExpression(), context.replaceExpectedType(returnType)); } JetType safeReturnType = returnType == null ? ErrorUtils.createErrorType("") : returnType; functionDescriptor.setReturnType(safeReturnType); - result = JetStandardClasses.getFunctionType(Collections.emptyList(), effectiveReceiverType, parameterTypes, safeReturnType); + return context.services.checkType(JetStandardClasses.getFunctionType(Collections.emptyList(), effectiveReceiverType, parameterTypes, safeReturnType), expression, contextWithExpectedType); } @Override - public void visitParenthesizedExpression(JetParenthesizedExpression expression) { - JetExpression inner = expression.getExpression(); - if (inner != null) { - result = getType(context.scope, inner, false); - } + public JetType visitParenthesizedExpression(JetParenthesizedExpression expression, TypeInferenceContext context) { + return context.services.checkType(getType(context.scope, expression.getExpression(), false, context), expression, context); } @Override - public void visitConstantExpression(JetConstantExpression expression) { + public JetType visitConstantExpression(JetConstantExpression expression, TypeInferenceContext context) { ASTNode node = expression.getNode(); IElementType elementType = node.getElementType(); String text = node.getText(); JetStandardLibrary standardLibrary = semanticServices.getStandardLibrary(); - CompileTimeConstantResolver compileTimeConstantResolver = services.compileTimeConstantResolver; + CompileTimeConstantResolver compileTimeConstantResolver = context.services.compileTimeConstantResolver; CompileTimeConstant value; if (elementType == JetNodeTypes.INTEGER_CONSTANT) { @@ -1063,68 +1199,61 @@ public class JetTypeInferrer { if (value instanceof ErrorValue) { ErrorValue errorValue = (ErrorValue) value; context.trace.getErrorHandler().genericError(node, errorValue.getMessage()); + return null; } else { context.trace.recordCompileTimeValue(expression, value); - result = value.getType(standardLibrary); + return context.services.checkType(value.getType(standardLibrary), expression, context); } } @Override - public void visitThrowExpression(JetThrowExpression expression) { + public JetType visitThrowExpression(JetThrowExpression expression, TypeInferenceContext context) { JetExpression thrownExpression = expression.getThrownExpression(); if (thrownExpression != null) { - JetType type = getType(context.scope, thrownExpression, false); + JetType type = getType(context.scope, thrownExpression, false, context.replaceExpectedType(NO_EXPECTED_TYPE)); // TODO : check that it inherits Throwable } - result = JetStandardClasses.getNothingType(); + return context.services.checkType(JetStandardClasses.getNothingType(), expression, context); } @Override - public void visitReturnExpression(JetReturnExpression expression) { + public JetType visitReturnExpression(JetReturnExpression expression, TypeInferenceContext context) { if (context.expectedReturnType == FORBIDDEN) { context.trace.getErrorHandler().genericError(expression.getNode(), "'return' is not allowed here"); - return; + return null; } JetExpression returnedExpression = expression.getReturnedExpression(); JetType returnedType = JetStandardClasses.getUnitType(); if (returnedExpression != null) { - returnedType = getType(context.scope, returnedExpression, false); + getType(context.scope, returnedExpression, false, context.replaceExpectedType(context.expectedReturnType)); } else { - if (context.expectedReturnType != null && !JetStandardClasses.isUnit(context.expectedReturnType)) { + if (context.expectedReturnType != NO_EXPECTED_TYPE && !JetStandardClasses.isUnit(context.expectedReturnType)) { context.trace.getErrorHandler().genericError(expression.getNode(), "This function must return a value of type " + context.expectedReturnType); } } - - if (context.expectedReturnType != null && returnedType != null) { - if (!semanticServices.getTypeChecker().isSubtypeOf(returnedType, context.expectedReturnType)) { - JetType enrichedType = enrichOutType(returnedExpression, returnedType); - if (!semanticServices.getTypeChecker().isSubtypeOf(enrichedType, context.expectedReturnType)) { - context.trace.getErrorHandler().typeMismatch(returnedExpression == null ? expression : returnedExpression, context.expectedReturnType, returnedType); - } - } - } - - result = JetStandardClasses.getNothingType(); + return context.services.checkType(JetStandardClasses.getNothingType(), expression, context); } @Override - public void visitBreakExpression(JetBreakExpression expression) { - result = JetStandardClasses.getNothingType(); + public JetType visitBreakExpression(JetBreakExpression expression, TypeInferenceContext context) { + return context.services.checkType(JetStandardClasses.getNothingType(), expression, context); } @Override - public void visitContinueExpression(JetContinueExpression expression) { - result = JetStandardClasses.getNothingType(); + public JetType visitContinueExpression(JetContinueExpression expression, TypeInferenceContext context) { + return context.services.checkType(JetStandardClasses.getNothingType(), expression, context); } @Override - public void visitBinaryWithTypeRHSExpression(JetBinaryExpressionWithTypeRHS expression) { + public JetType visitBinaryWithTypeRHSExpression(JetBinaryExpressionWithTypeRHS expression, TypeInferenceContext contextWithExpectedType) { + TypeInferenceContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE); IElementType operationType = expression.getOperationSign().getReferencedNameElementType(); - JetType actualType = getType(context.scope, expression.getLeft(), false); + JetType actualType = getType(context.scope, expression.getLeft(), false, context); JetTypeReference right = expression.getRight(); + JetType result = null; if (right != null) { JetType targetType = context.typeResolver.resolveType(context.scope, right); if (operationType == JetTokens.COLON) { @@ -1134,20 +1263,21 @@ public class JetTypeInferrer { result = targetType; } else if (operationType == JetTokens.AS_KEYWORD) { - checkForCastImpossibility(expression, actualType, targetType); + checkForCastImpossibility(expression, actualType, targetType, context); result = targetType; } else if (operationType == JetTokens.AS_SAFE) { - checkForCastImpossibility(expression, actualType, targetType); + checkForCastImpossibility(expression, actualType, targetType, context); result = TypeUtils.makeNullable(targetType); } else { context.trace.getErrorHandler().genericError(expression.getOperationSign().getNode(), "Unsupported binary operation"); } } + return context.services.checkType(result, expression, contextWithExpectedType); } - private void checkForCastImpossibility(JetBinaryExpressionWithTypeRHS expression, JetType actualType, JetType targetType) { + private void checkForCastImpossibility(JetBinaryExpressionWithTypeRHS expression, JetType actualType, JetType targetType, TypeInferenceContext context) { if (actualType == null) return; JetTypeChecker typeChecker = semanticServices.getTypeChecker(); @@ -1168,18 +1298,25 @@ public class JetTypeInferrer { } @Override - public void visitTupleExpression(JetTupleExpression expression) { + public JetType visitTupleExpression(JetTupleExpression expression, TypeInferenceContext context) { List entries = expression.getEntries(); List types = new ArrayList(); for (JetExpression entry : entries) { - types.add(services.safeGetType(context.scope, entry, false, NO_EXPECTED_TYPE)); // TODO + types.add(context.services.safeGetType(context.scope, entry, false, NO_EXPECTED_TYPE)); // TODO + } + if (context.expectedType != NO_EXPECTED_TYPE && JetStandardClasses.isTupleType(context.expectedType)) { + List enrichedTypes = context.services.checkArgumentTypes(types, entries, context.expectedType.getArguments(), context); + if (enrichedTypes != types) { + return JetStandardClasses.getTupleType(enrichedTypes); + } } // TODO : labels - result = JetStandardClasses.getTupleType(types); + return context.services.checkType(JetStandardClasses.getTupleType(types), expression, context); } @Override - public void visitThisExpression(JetThisExpression expression) { + public JetType visitThisExpression(JetThisExpression expression, TypeInferenceContext context) { + JetType result = null; JetType thisType = null; String labelName = expression.getLabelName(); if (labelName != null) { @@ -1276,20 +1413,22 @@ public class JetTypeInferrer { } } } + return context.services.checkType(result, expression, context); } @Override - public void visitBlockExpression(JetBlockExpression expression) { - result = getBlockReturnedType(context.scope, expression.getStatements(), context.dataFlowInfo, context.expectedReturnType); + public JetType visitBlockExpression(JetBlockExpression expression, TypeInferenceContext context) { + return context.services.checkType(getBlockReturnedType(context.scope, expression, context), expression, context); } @Override - public void visitWhenExpression(final JetWhenExpression expression) { + public JetType visitWhenExpression(final JetWhenExpression expression, TypeInferenceContext contextWithExpectedType) { + TypeInferenceContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE); // TODO :change scope according to the bound value in the when header final JetExpression subjectExpression = expression.getSubjectExpression(); - final JetType subjectType = subjectExpression != null ? services.safeGetType(context.scope, subjectExpression, false, NO_EXPECTED_TYPE) : ErrorUtils.createErrorType("Unknown type"); - final VariableDescriptor variableDescriptor = subjectExpression != null ? getVariableDescriptorFromSimpleName(subjectExpression) : null; + final JetType subjectType = subjectExpression != null ? context.services.safeGetType(context.scope, subjectExpression, false, NO_EXPECTED_TYPE) : ErrorUtils.createErrorType("Unknown type"); + final VariableDescriptor variableDescriptor = subjectExpression != null ? context.services.getVariableDescriptorFromSimpleName(subjectExpression, context) : null; // TODO : exhaustive patterns @@ -1299,18 +1438,18 @@ public class JetTypeInferrer { DataFlowInfo newDataFlowInfo; WritableScope scopeToExtend; if (conditions.length == 1) { - scopeToExtend = newWritableScopeImpl().setDebugName("Scope extended in when entry"); + scopeToExtend = newWritableScopeImpl(context.scope, context.trace).setDebugName("Scope extended in when entry"); newDataFlowInfo = context.dataFlowInfo; JetWhenCondition condition = conditions[0]; if (condition != null) { - newDataFlowInfo = checkWhenCondition(subjectExpression, subjectType, condition, scopeToExtend, variableDescriptor); + newDataFlowInfo = checkWhenCondition(subjectExpression, subjectType, condition, scopeToExtend, context, variableDescriptor); } } else { - scopeToExtend = newWritableScopeImpl(); // We don't write to this scope + scopeToExtend = newWritableScopeImpl(context.scope, context.trace); // We don't write to this scope newDataFlowInfo = null; for (JetWhenCondition condition : conditions) { - DataFlowInfo dataFlowInfo = checkWhenCondition(subjectExpression, subjectType, condition, newWritableScopeImpl(), variableDescriptor); + DataFlowInfo dataFlowInfo = checkWhenCondition(subjectExpression, subjectType, condition, newWritableScopeImpl(context.scope, context.trace), context, variableDescriptor); if (newDataFlowInfo == null) { newDataFlowInfo = dataFlowInfo; } @@ -1327,7 +1466,7 @@ public class JetTypeInferrer { } JetExpression bodyExpression = whenEntry.getExpression(); if (bodyExpression != null) { - JetType type = getTypeWithNewDataFlowInfo(scopeToExtend, bodyExpression, true, newDataFlowInfo); + JetType type = getTypeWithNewDataFlowInfo(scopeToExtend, bodyExpression, true, newDataFlowInfo, contextWithExpectedType); if (type != null) { expressionTypes.add(type); } @@ -1335,14 +1474,15 @@ public class JetTypeInferrer { } if (!expressionTypes.isEmpty()) { - result = semanticServices.getTypeChecker().commonSupertype(expressionTypes); + return semanticServices.getTypeChecker().commonSupertype(expressionTypes); } else if (expression.getEntries().isEmpty()) { context.trace.getErrorHandler().genericError(expression.getNode(), "Entries required for when-expression"); // TODO : Scope, and maybe this should not an error } + return null; } - private DataFlowInfo checkWhenCondition(@Nullable final JetExpression subjectExpression, final JetType subjectType, JetWhenCondition condition, final WritableScope scopeToExtend, final VariableDescriptor... subjectVariables) { + private DataFlowInfo checkWhenCondition(@Nullable final JetExpression subjectExpression, final JetType subjectType, JetWhenCondition condition, final WritableScope scopeToExtend, final TypeInferenceContext context, final VariableDescriptor... subjectVariables) { final DataFlowInfo[] newDataFlowInfo = new DataFlowInfo[]{context.dataFlowInfo}; condition.accept(new JetVisitor() { @@ -1351,9 +1491,9 @@ public class JetTypeInferrer { JetExpression callSuffixExpression = condition.getCallSuffixExpression(); JetScope compositeScope = new ScopeWithReceiver(context.scope, subjectType, semanticServices.getTypeChecker()); if (callSuffixExpression != null) { - JetType selectorReturnType = getType(compositeScope, callSuffixExpression, false); - ensureBooleanResultWithCustomSubject(callSuffixExpression, selectorReturnType, "This expression"); - services.checkNullSafety(subjectType, condition.getOperationTokenNode(), getCalleeFunctionDescriptor(callSuffixExpression)); + JetType selectorReturnType = getType(compositeScope, callSuffixExpression, false, context); + ensureBooleanResultWithCustomSubject(callSuffixExpression, selectorReturnType, "This expression", context); + context.services.checkNullSafety(subjectType, condition.getOperationTokenNode(), getCalleeFunctionDescriptor(callSuffixExpression, context)); } } @@ -1362,7 +1502,7 @@ public class JetTypeInferrer { JetExpression rangeExpression = condition.getRangeExpression(); if (rangeExpression != null) { assert subjectExpression != null; - checkInExpression(condition.getOperationReference(), subjectExpression, rangeExpression); + checkInExpression(condition.getOperationReference(), subjectExpression, rangeExpression, context); } } @@ -1370,7 +1510,7 @@ public class JetTypeInferrer { public void visitWhenConditionIsPattern(JetWhenConditionIsPattern condition) { JetPattern pattern = condition.getPattern(); if (pattern != null) { - newDataFlowInfo[0] = checkPatternType(pattern, subjectType, scopeToExtend, subjectVariables); + newDataFlowInfo[0] = checkPatternType(pattern, subjectType, scopeToExtend, context, subjectVariables); } } @@ -1382,7 +1522,7 @@ public class JetTypeInferrer { return newDataFlowInfo[0]; } - private DataFlowInfo checkPatternType(@NotNull JetPattern pattern, @NotNull final JetType subjectType, @NotNull final WritableScope scopeToExtend, @NotNull final VariableDescriptor... subjectVariables) { + private DataFlowInfo checkPatternType(@NotNull JetPattern pattern, @NotNull final JetType subjectType, @NotNull final WritableScope scopeToExtend, final TypeInferenceContext context, @NotNull final VariableDescriptor... subjectVariables) { final DataFlowInfo[] result = new DataFlowInfo[] {context.dataFlowInfo}; pattern.accept(new JetVisitor() { @Override @@ -1416,7 +1556,7 @@ public class JetTypeInferrer { JetPattern entryPattern = entry.getPattern(); if (entryPattern != null) { - result[0] = checkPatternType(entryPattern, type, scopeToExtend); + result[0] = result[0].and(checkPatternType(entryPattern, type, scopeToExtend, context)); } } } @@ -1424,9 +1564,9 @@ public class JetTypeInferrer { @Override public void visitDecomposerPattern(JetDecomposerPattern pattern) { - JetType selectorReturnType = getSelectorReturnType(subjectType, pattern.getDecomposerExpression()); + JetType selectorReturnType = getSelectorReturnType(subjectType, pattern.getDecomposerExpression(), context); - result[0] = checkPatternType(pattern.getArgumentList(), selectorReturnType == null ? ErrorUtils.createErrorType("No type") : selectorReturnType, scopeToExtend); + result[0] = checkPatternType(pattern.getArgumentList(), selectorReturnType == null ? ErrorUtils.createErrorType("No type") : selectorReturnType, scopeToExtend, context); } @Override @@ -1438,7 +1578,7 @@ public class JetTypeInferrer { public void visitExpressionPattern(JetExpressionPattern pattern) { JetExpression expression = pattern.getExpression(); if (expression != null) { - JetType type = getType(scopeToExtend, expression, false); + JetType type = getType(scopeToExtend, expression, false, context); checkTypeCompatibility(type, subjectType, pattern); } } @@ -1462,7 +1602,7 @@ public class JetTypeInferrer { VariableDescriptor[] newSubjectVariables = new VariableDescriptor[oldLength + 1]; System.arraycopy(subjectVariables, 0, newSubjectVariables, 0, oldLength); newSubjectVariables[oldLength] = variableDescriptor; - result[0] = checkWhenCondition(null, subjectType, condition, scopeToExtend, newSubjectVariables); + result[0] = checkWhenCondition(null, subjectType, condition, scopeToExtend, context, newSubjectVariables); } } @@ -1485,7 +1625,8 @@ public class JetTypeInferrer { } @Override - public void visitTryExpression(JetTryExpression expression) { + public JetType visitTryExpression(JetTryExpression expression, TypeInferenceContext contextWithExpectedType) { + TypeInferenceContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE); JetExpression tryBlock = expression.getTryBlock(); List catchClauses = expression.getCatchClauses(); JetFinallySection finallyBlock = expression.getFinallyBlock(); @@ -1496,9 +1637,9 @@ public class JetTypeInferrer { if (catchParameter != null) { VariableDescriptor variableDescriptor = context.classDescriptorResolver.resolveLocalVariableDescriptor(context.scope.getContainingDeclaration(), context.scope, catchParameter); if (catchBody != null) { - WritableScope catchScope = newWritableScopeImpl().setDebugName("Catch scope"); + WritableScope catchScope = newWritableScopeImpl(context.scope, context.trace).setDebugName("Catch scope"); catchScope.addVariableDescriptor(variableDescriptor); - JetType type = getType(catchScope, catchBody, true); + JetType type = getType(catchScope, catchBody, true, contextWithExpectedType); if (type != null) { types.add(type); } @@ -1507,82 +1648,85 @@ public class JetTypeInferrer { } if (finallyBlock != null) { types.clear(); // Do not need the list for the check, but need the code above to typecheck catch bodies - JetType type = getType(context.scope, finallyBlock.getFinalExpression(), true); + JetType type = getType(context.scope, finallyBlock.getFinalExpression(), true, contextWithExpectedType); if (type != null) { types.add(type); } } - JetType type = getType(context.scope, tryBlock, true); + JetType type = getType(context.scope, tryBlock, true, contextWithExpectedType); if (type != null) { types.add(type); } if (types.isEmpty()) { - result = null; + return null; } else { - result = semanticServices.getTypeChecker().commonSupertype(types); + return semanticServices.getTypeChecker().commonSupertype(types); } } @Override - public void visitIfExpression(JetIfExpression expression) { + public JetType visitIfExpression(JetIfExpression expression, TypeInferenceContext contextWithExpectedType) { + TypeInferenceContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE); JetExpression condition = expression.getCondition(); - checkCondition(context.scope, condition); + checkCondition(context.scope, condition, context); JetExpression elseBranch = expression.getElse(); JetExpression thenBranch = expression.getThen(); - WritableScopeImpl thenScope = newWritableScopeImpl().setDebugName("Then scope"); - DataFlowInfo thenInfo = extractDataFlowInfoFromCondition(condition, true, thenScope); - DataFlowInfo elseInfo = extractDataFlowInfoFromCondition(condition, false, null); + WritableScopeImpl thenScope = newWritableScopeImpl(context.scope, context.trace).setDebugName("Then scope"); + DataFlowInfo thenInfo = extractDataFlowInfoFromCondition(condition, true, thenScope, context); + DataFlowInfo elseInfo = extractDataFlowInfoFromCondition(condition, false, null, context); if (elseBranch == null) { if (thenBranch != null) { - JetType type = getTypeWithNewDataFlowInfo(thenScope, thenBranch, true, thenInfo); + JetType type = getTypeWithNewDataFlowInfo(thenScope, thenBranch, true, thenInfo, context); if (type != null && JetStandardClasses.isNothing(type)) { resultDataFlowInfo = elseInfo; // resultScope = elseScope; } - result = JetStandardClasses.getUnitType(); + return context.services.checkType(JetStandardClasses.getUnitType(), expression, contextWithExpectedType); } + return null; } - else if (thenBranch == null) { - JetType type = getTypeWithNewDataFlowInfo(context.scope, elseBranch, true, elseInfo); + if (thenBranch == null) { + JetType type = getTypeWithNewDataFlowInfo(context.scope, elseBranch, true, elseInfo, context); if (type != null && JetStandardClasses.isNothing(type)) { resultDataFlowInfo = thenInfo; // resultScope = thenScope; } - result = JetStandardClasses.getUnitType(); + return context.services.checkType(JetStandardClasses.getUnitType(), expression, contextWithExpectedType); + } + JetType thenType = getTypeWithNewDataFlowInfo(thenScope, thenBranch, true, thenInfo, contextWithExpectedType); + JetType elseType = getTypeWithNewDataFlowInfo(context.scope, elseBranch, true, elseInfo, contextWithExpectedType); + + JetType result; + if (thenType == null) { + result = elseType; + } + else if (elseType == null) { + result = thenType; } else { - JetType thenType = getTypeWithNewDataFlowInfo(thenScope, thenBranch, true, thenInfo); - JetType elseType = getTypeWithNewDataFlowInfo(context.scope, elseBranch, true, elseInfo); - - if (thenType == null) { - result = elseType; - } - else if (elseType == null) { - result = thenType; - } - else { - result = semanticServices.getTypeChecker().commonSupertype(Arrays.asList(thenType, elseType)); - } - - boolean jumpInThen = thenType != null && JetStandardClasses.isNothing(thenType); - boolean jumpInElse = elseType != null && JetStandardClasses.isNothing(elseType); - - if (jumpInThen && !jumpInElse) { - resultDataFlowInfo = elseInfo; -// resultScope = elseScope; - } - else if (jumpInElse && !jumpInThen) { - resultDataFlowInfo = thenInfo; -// resultScope = thenScope; - } + result = semanticServices.getTypeChecker().commonSupertype(Arrays.asList(thenType, elseType)); } + + boolean jumpInThen = thenType != null && JetStandardClasses.isNothing(thenType); + boolean jumpInElse = elseType != null && JetStandardClasses.isNothing(elseType); + + if (jumpInThen && !jumpInElse) { + resultDataFlowInfo = elseInfo; +// resultScope = elseScope; + } + else if (jumpInElse && !jumpInThen) { + resultDataFlowInfo = thenInfo; +// resultScope = thenScope; + } + return result; } - private DataFlowInfo extractDataFlowInfoFromCondition(@Nullable JetExpression condition, final boolean conditionValue, @Nullable final WritableScope scopeToExtend) { + @NotNull + private DataFlowInfo extractDataFlowInfoFromCondition(@Nullable JetExpression condition, final boolean conditionValue, @Nullable final WritableScope scopeToExtend, final TypeInferenceContext context) { if (condition == null) return context.dataFlowInfo; final DataFlowInfo[] result = new DataFlowInfo[] {context.dataFlowInfo}; condition.accept(new JetVisitor() { @@ -1592,8 +1736,11 @@ public class JetTypeInferrer { JetPattern pattern = expression.getPattern(); result[0] = patternsToDataFlowInfo.get(pattern); if (scopeToExtend != null) { - for (VariableDescriptor variableDescriptor : patternsToBoundVariableLists.get(pattern)) { - scopeToExtend.addVariableDescriptor(variableDescriptor); + List descriptors = patternsToBoundVariableLists.get(pattern); + if (descriptors != null) { + for (VariableDescriptor variableDescriptor : descriptors) { + scopeToExtend.addVariableDescriptor(variableDescriptor); + } } } } @@ -1611,10 +1758,10 @@ public class JetTypeInferrer { actualScopeToExtend = conditionValue ? null : scopeToExtend; } - DataFlowInfo dataFlowInfo = extractDataFlowInfoFromCondition(expression.getLeft(), conditionValue, actualScopeToExtend); + DataFlowInfo dataFlowInfo = extractDataFlowInfoFromCondition(expression.getLeft(), conditionValue, actualScopeToExtend, context); JetExpression expressionRight = expression.getRight(); if (expressionRight != null) { - DataFlowInfo rightInfo = extractDataFlowInfoFromCondition(expressionRight, conditionValue, actualScopeToExtend); + DataFlowInfo rightInfo = extractDataFlowInfoFromCondition(expressionRight, conditionValue, actualScopeToExtend, context); DataFlowInfo.CompositionOperator operator; if (operationToken == JetTokens.ANDAND) { operator = conditionValue ? DataFlowInfo.AND : DataFlowInfo.OR; @@ -1644,7 +1791,8 @@ public class JetTypeInferrer { } } - VariableDescriptor variableDescriptor = getVariableDescriptorFromSimpleName(left); + VariableDescriptor variableDescriptor = context.services.getVariableDescriptorFromSimpleName(left, context); + if (variableDescriptor == null) return; // TODO : validate that DF makes sense for this variable: local, val, internal w/backing field, etc @@ -1655,7 +1803,7 @@ public class JetTypeInferrer { return; } - VariableDescriptor rightVariable = getVariableDescriptorFromSimpleName(right); + VariableDescriptor rightVariable = context.services.getVariableDescriptorFromSimpleName(right, context); if (rightVariable != null) { JetType lhsType = context.trace.getBindingContext().getExpressionType(left); if (lhsType != null && !lhsType.isNullable()) { @@ -1677,7 +1825,7 @@ public class JetTypeInferrer { } } - private void extendDataFlowWithNullComparison(IElementType operationToken, VariableDescriptor variableDescriptor, boolean equalsToNull) { + private void extendDataFlowWithNullComparison(IElementType operationToken, @NotNull VariableDescriptor variableDescriptor, boolean equalsToNull) { if (operationToken == JetTokens.EQEQ || operationToken == JetTokens.EQEQEQ) { result[0] = context.dataFlowInfo.equalsToNull(variableDescriptor, !equalsToNull); } @@ -1692,7 +1840,7 @@ public class JetTypeInferrer { if (operationTokenType == JetTokens.EXCL) { JetExpression baseExpression = expression.getBaseExpression(); if (baseExpression != null) { - result[0] = extractDataFlowInfoFromCondition(baseExpression, !conditionValue, scopeToExtend); + result[0] = extractDataFlowInfoFromCondition(baseExpression, !conditionValue, scopeToExtend, context); } } } @@ -1705,12 +1853,15 @@ public class JetTypeInferrer { } } }); + if (result[0] == null) { + return context.dataFlowInfo; + } return result[0]; } - private void checkCondition(@NotNull JetScope scope, @Nullable JetExpression condition) { + private void checkCondition(@NotNull JetScope scope, @Nullable JetExpression condition, TypeInferenceContext context) { if (condition != null) { - JetType conditionType = getType(scope, condition, false); + JetType conditionType = getType(scope, condition, false, context); if (conditionType != null && !isBoolean(conditionType)) { context.trace.getErrorHandler().genericError(condition.getNode(), "Condition must be of type Boolean, but was of type " + conditionType); @@ -1719,73 +1870,72 @@ public class JetTypeInferrer { } @Override - public void visitWhileExpression(JetWhileExpression expression) { + public JetType visitWhileExpression(JetWhileExpression expression, TypeInferenceContext contextWithExpectedType) { + TypeInferenceContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE); JetExpression condition = expression.getCondition(); - checkCondition(context.scope, condition); + checkCondition(context.scope, condition, context); JetExpression body = expression.getBody(); if (body != null) { - WritableScopeImpl scopeToExtend = newWritableScopeImpl().setDebugName("Scope extended in while's condition"); - DataFlowInfo conditionInfo = condition == null ? context.dataFlowInfo : extractDataFlowInfoFromCondition(condition, true, scopeToExtend); - getTypeWithNewDataFlowInfo(scopeToExtend, body, true, conditionInfo); + WritableScopeImpl scopeToExtend = newWritableScopeImpl(context.scope, context.trace).setDebugName("Scope extended in while's condition"); + DataFlowInfo conditionInfo = condition == null ? context.dataFlowInfo : extractDataFlowInfoFromCondition(condition, true, scopeToExtend, context); + getTypeWithNewDataFlowInfo(scopeToExtend, body, true, conditionInfo, context); } if (!flowInformationProvider.isBreakable(expression)) { // resultScope = newWritableScopeImpl(); - resultDataFlowInfo = extractDataFlowInfoFromCondition(condition, false, null); + resultDataFlowInfo = extractDataFlowInfoFromCondition(condition, false, null, context); } - result = JetStandardClasses.getUnitType(); + return context.services.checkType(JetStandardClasses.getUnitType(), expression, contextWithExpectedType); } @Override - public void visitDoWhileExpression(JetDoWhileExpression expression) { + public JetType visitDoWhileExpression(JetDoWhileExpression expression, TypeInferenceContext contextWithExpectedType) { + TypeInferenceContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE); JetExpression body = expression.getBody(); JetScope conditionScope = context.scope; if (body instanceof JetFunctionLiteralExpression) { JetFunctionLiteralExpression function = (JetFunctionLiteralExpression) body; if (!function.getFunctionLiteral().hasParameterSpecification()) { - WritableScope writableScope = newWritableScopeImpl().setDebugName("do..while body scope"); + WritableScope writableScope = newWritableScopeImpl(context.scope, context.trace).setDebugName("do..while body scope"); conditionScope = writableScope; - services.getBlockReturnedTypeWithWritableScope(writableScope, function.getFunctionLiteral().getBodyExpression().getStatements(), context.dataFlowInfo, context.expectedReturnType); + context.services.getBlockReturnedTypeWithWritableScope(writableScope, function.getFunctionLiteral().getBodyExpression().getStatements(), context); context.trace.recordBlock(function); } else { - getType(context.scope, body, true); + getType(context.scope, body, true, context); } } else if (body != null) { - WritableScope writableScope = newWritableScopeImpl().setDebugName("do..while body scope"); + WritableScope writableScope = newWritableScopeImpl(context.scope, context.trace).setDebugName("do..while body scope"); conditionScope = writableScope; - services.getBlockReturnedTypeWithWritableScope(writableScope, Collections.singletonList(body), context.dataFlowInfo, context.expectedReturnType); + context.services.getBlockReturnedTypeWithWritableScope(writableScope, Collections.singletonList(body), context); } JetExpression condition = expression.getCondition(); - checkCondition(conditionScope, condition); + checkCondition(conditionScope, condition, context); if (!flowInformationProvider.isBreakable(expression)) { // resultScope = newWritableScopeImpl(); - resultDataFlowInfo = extractDataFlowInfoFromCondition(condition, false, null); + resultDataFlowInfo = extractDataFlowInfoFromCondition(condition, false, null, context); } - result = JetStandardClasses.getUnitType(); + return context.services.checkType(JetStandardClasses.getUnitType(), expression, contextWithExpectedType); } - protected WritableScopeImpl newWritableScopeImpl() { - return newWritableScopeImpl(context.scope); - } - - protected WritableScopeImpl newWritableScopeImpl(JetScope scopeToExtend) { - return new WritableScopeImpl(scopeToExtend, scopeToExtend.getContainingDeclaration(), context.trace.getErrorHandler()); + protected WritableScopeImpl newWritableScopeImpl(JetScope scope, BindingTrace trace) { + return new WritableScopeImpl(scope, scope.getContainingDeclaration(), trace.getErrorHandler()); } @Override - public void visitForExpression(JetForExpression expression) { + public JetType visitForExpression(JetForExpression expression, TypeInferenceContext contextWithExpectedType) { + TypeInferenceContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE); JetParameter loopParameter = expression.getLoopParameter(); JetExpression loopRange = expression.getLoopRange(); JetType loopRangeType = null; if (loopRange != null) { - loopRangeType = getType(context.scope, loopRange, false); + loopRangeType = getType(context.scope, loopRange, false, context); } JetType expectedParameterType = null; if (loopRangeType != null) { - expectedParameterType = checkIterableConvention(loopRangeType, loopRange.getNode()); + expectedParameterType = checkIterableConvention(loopRangeType, loopRange.getNode(), context); } - WritableScope loopScope = newWritableScopeImpl().setDebugName("Scope with for-loop index"); + WritableScope loopScope = newWritableScopeImpl(context.scope, context.trace).setDebugName("Scope with for-loop index"); if (loopParameter != null) { JetTypeReference typeReference = loopParameter.getTypeReference(); @@ -1810,19 +1960,19 @@ public class JetTypeInferrer { JetExpression body = expression.getBody(); if (body != null) { - getType(loopScope, body, true); // TODO + getType(loopScope, body, true, context); // TODO } - result = JetStandardClasses.getUnitType(); + return context.services.checkType(JetStandardClasses.getUnitType(), expression, contextWithExpectedType); } @Nullable - private JetType checkIterableConvention(@NotNull JetType type, @NotNull ASTNode reportErrorsOn) { - OverloadResolutionResult iteratorResolutionResult = services.resolveNoParametersFunction(type, context.scope, "iterator"); + private JetType checkIterableConvention(@NotNull JetType type, @NotNull ASTNode reportErrorsOn, TypeInferenceContext context) { + OverloadResolutionResult iteratorResolutionResult = context.services.resolveNoParametersFunction(type, context.scope, "iterator"); if (iteratorResolutionResult.isSuccess()) { JetType iteratorType = iteratorResolutionResult.getFunctionDescriptor().getReturnType(); - boolean hasNextFunctionSupported = checkHasNextFunctionSupport(reportErrorsOn, iteratorType); - boolean hasNextPropertySupported = checkHasNextPropertySupport(reportErrorsOn, iteratorType); + boolean hasNextFunctionSupported = checkHasNextFunctionSupport(reportErrorsOn, iteratorType, context); + boolean hasNextPropertySupported = checkHasNextPropertySupport(reportErrorsOn, iteratorType, context); if (hasNextFunctionSupported && hasNextPropertySupported && !ErrorUtils.isErrorType(iteratorType)) { // TODO : overload resolution rules impose priorities here??? context.trace.getErrorHandler().genericError(reportErrorsOn, "An ambiguity between 'iterator().hasNext()' function and 'iterator().hasNext()' property"); @@ -1831,7 +1981,7 @@ public class JetTypeInferrer { context.trace.getErrorHandler().genericError(reportErrorsOn, "Loop range must have an 'iterator().hasNext()' function or an 'iterator().hasNext' property"); } - OverloadResolutionResult nextResolutionResult = services.resolveNoParametersFunction(iteratorType, context.scope, "next"); + OverloadResolutionResult nextResolutionResult = context.services.resolveNoParametersFunction(iteratorType, context.scope, "next"); if (nextResolutionResult.isAmbiguity()) { context.trace.getErrorHandler().genericError(reportErrorsOn, "Method 'iterator().next()' is ambiguous for this expression"); } else if (nextResolutionResult.isNothing()) { @@ -1850,8 +2000,8 @@ public class JetTypeInferrer { return null; } - private boolean checkHasNextFunctionSupport(@NotNull ASTNode reportErrorsOn, @NotNull JetType iteratorType) { - OverloadResolutionResult hasNextResolutionResult = services.resolveNoParametersFunction(iteratorType, context.scope, "hasNext"); + private boolean checkHasNextFunctionSupport(@NotNull ASTNode reportErrorsOn, @NotNull JetType iteratorType, TypeInferenceContext context) { + OverloadResolutionResult hasNextResolutionResult = context.services.resolveNoParametersFunction(iteratorType, context.scope, "hasNext"); if (hasNextResolutionResult.isAmbiguity()) { context.trace.getErrorHandler().genericError(reportErrorsOn, "Method 'iterator().hasNext()' is ambiguous for this expression"); } else if (hasNextResolutionResult.isNothing()) { @@ -1865,7 +2015,7 @@ public class JetTypeInferrer { return true; } - private boolean checkHasNextPropertySupport(@NotNull ASTNode reportErrorsOn, @NotNull JetType iteratorType) { + private boolean checkHasNextPropertySupport(@NotNull ASTNode reportErrorsOn, @NotNull JetType iteratorType, TypeInferenceContext context) { VariableDescriptor hasNextProperty = iteratorType.getMemberScope().getVariable("hasNext"); // TODO :extension properties if (hasNextProperty == null) { @@ -1967,102 +2117,78 @@ public class JetTypeInferrer { // } @Override - public void visitHashQualifiedExpression(JetHashQualifiedExpression expression) { + public JetType visitHashQualifiedExpression(JetHashQualifiedExpression expression, TypeInferenceContext context) { context.trace.getErrorHandler().genericError(expression.getOperationTokenNode(), "Unsupported"); + return null; } @Override - public void visitQualifiedExpression(JetQualifiedExpression expression) { + public JetType visitQualifiedExpression(JetQualifiedExpression expression, TypeInferenceContext contextWithExpectedType) { + TypeInferenceContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE); // TODO : functions as values JetExpression selectorExpression = expression.getSelectorExpression(); JetExpression receiverExpression = expression.getReceiverExpression(); - JetType receiverType = new TypeInferrerVisitorWithNamespaces(new TypeInferenceContext(context.trace, context.scope, false, context.dataFlowInfo, NO_EXPECTED_TYPE, null)).getType(receiverExpression); - if (receiverType != null) { - ErrorHandlerWithRegions errorHandler = context.trace.getErrorHandler(); - errorHandler.openRegion(); - JetType selectorReturnType = getSelectorReturnType(receiverType, selectorExpression); + JetType receiverType = context.services.typeInferrerVisitorWithNamespaces.getType(receiverExpression, new TypeInferenceContext(context.trace, context.scope, context.services, false, context.dataFlowInfo, NO_EXPECTED_TYPE, NO_EXPECTED_TYPE)); + if (receiverType == null) return null; + ErrorHandlerWithRegions errorHandler = context.trace.getErrorHandler(); + errorHandler.openRegion(); + JetType selectorReturnType = getSelectorReturnType(receiverType, selectorExpression, context); - if (selectorReturnType != null) { - errorHandler.closeAndCommitCurrentRegion(); - } - else { - ErrorHandlerWithRegions.DiagnosticsRegion regionToCommit = errorHandler.closeAndReturnCurrentRegion(); + if (selectorReturnType != null) { + errorHandler.closeAndCommitCurrentRegion(); + } + else { + ErrorHandlerWithRegions.DiagnosticsRegion regionToCommit = errorHandler.closeAndReturnCurrentRegion(); - VariableDescriptor variableDescriptor = getVariableDescriptorFromSimpleName(receiverExpression); - if (variableDescriptor != null) { - List possibleTypes = Lists.newArrayList(context.dataFlowInfo.getPossibleTypes(variableDescriptor)); - Collections.reverse(possibleTypes); - for (JetType possibleType : possibleTypes) { - errorHandler.openRegion(); - selectorReturnType = getSelectorReturnType(possibleType, selectorExpression); - if (selectorReturnType != null) { - regionToCommit = errorHandler.closeAndReturnCurrentRegion(); - context.trace.recordAutoCast(receiverExpression, possibleType); - break; - } - else { - errorHandler.closeAndReturnCurrentRegion(); - } + VariableDescriptor variableDescriptor = context.services.getVariableDescriptorFromSimpleName(receiverExpression, context); + if (variableDescriptor != null) { + List possibleTypes = Lists.newArrayList(context.dataFlowInfo.getPossibleTypes(variableDescriptor)); + Collections.reverse(possibleTypes); + for (JetType possibleType : possibleTypes) { + errorHandler.openRegion(); + selectorReturnType = getSelectorReturnType(possibleType, selectorExpression, context); + if (selectorReturnType != null) { + regionToCommit = errorHandler.closeAndReturnCurrentRegion(); + context.trace.recordAutoCast(receiverExpression, possibleType); + break; + } + else { + errorHandler.closeAndReturnCurrentRegion(); } } - - regionToCommit.commit(); } - if (expression.getOperationSign() == JetTokens.QUEST) { - if (selectorReturnType != null && !isBoolean(selectorReturnType) && selectorExpression != null) { - // TODO : more comprehensible error message - errorHandler.typeMismatch(selectorExpression, semanticServices.getStandardLibrary().getBooleanType(), selectorReturnType); - } - result = TypeUtils.makeNullable(receiverType); - } - else { - result = selectorReturnType; - } - if (selectorExpression != null && result != null) { - context.trace.recordExpressionType(selectorExpression, result); - } - if (selectorReturnType != null) { - // TODO : extensions to 'Any?' - if (selectorExpression != null) { - receiverType = enrichOutType(receiverExpression, receiverType); + regionToCommit.commit(); + } - services.checkNullSafety(receiverType, expression.getOperationTokenNode(), getCalleeFunctionDescriptor(selectorExpression)); - } + JetType result; + if (expression.getOperationSign() == JetTokens.QUEST) { + if (selectorReturnType != null && !isBoolean(selectorReturnType) && selectorExpression != null) { + // TODO : more comprehensible error message + errorHandler.typeMismatch(selectorExpression, semanticServices.getStandardLibrary().getBooleanType(), selectorReturnType); + } + result = TypeUtils.makeNullable(receiverType); + } + else { + result = selectorReturnType; + } + if (selectorExpression != null && result != null) { + context.trace.recordExpressionType(selectorExpression, result); + } + if (selectorReturnType != null) { + // TODO : extensions to 'Any?' + if (selectorExpression != null) { + receiverType = context.services.enrichOutType(receiverExpression, receiverType, context); + + context.services.checkNullSafety(receiverType, expression.getOperationTokenNode(), getCalleeFunctionDescriptor(selectorExpression, context)); } } + return context.services.checkType(result, expression, context); } - private JetType enrichOutType(JetExpression expression, JetType initialType) { - if (expression == null) return initialType; - VariableDescriptor variableDescriptor = getVariableDescriptorFromSimpleName(expression); - if (variableDescriptor != null) { - return context.dataFlowInfo.getOutType(variableDescriptor); - } - return initialType; - } - - @Nullable - private VariableDescriptor getVariableDescriptorFromSimpleName(@NotNull JetExpression receiverExpression) { - if (receiverExpression instanceof JetBinaryExpressionWithTypeRHS) { - JetBinaryExpressionWithTypeRHS expression = (JetBinaryExpressionWithTypeRHS) receiverExpression; - if (expression.getOperationSign().getReferencedNameElementType() == JetTokens.COLON) { - return getVariableDescriptorFromSimpleName(expression.getLeft()); - } - } - VariableDescriptor variableDescriptor = null; - if (receiverExpression instanceof JetSimpleNameExpression) { - JetSimpleNameExpression nameExpression = (JetSimpleNameExpression) receiverExpression; - DeclarationDescriptor declarationDescriptor = context.trace.getBindingContext().resolveReferenceExpression(nameExpression); - if (declarationDescriptor instanceof VariableDescriptor) { - variableDescriptor = (VariableDescriptor) declarationDescriptor; - } - } - return variableDescriptor; - } @NotNull - private FunctionDescriptor getCalleeFunctionDescriptor(@NotNull JetExpression selectorExpression) { + private FunctionDescriptor getCalleeFunctionDescriptor(@NotNull JetExpression selectorExpression, final TypeInferenceContext context) { final FunctionDescriptor[] result = new FunctionDescriptor[1]; selectorExpression.accept(new JetVisitor() { @Override @@ -2107,22 +2233,23 @@ public class JetTypeInferrer { return result[0]; } - private JetType getCallExpressionType(@Nullable JetType receiverType, @NotNull JetCallExpression callExpression) { + private JetType getCallExpressionType(@Nullable JetType receiverType, @NotNull JetCallExpression callExpression, TypeInferenceContext contextWithExpectedType) { + TypeInferenceContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE); JetExpression calleeExpression = callExpression.getCalleeExpression(); if (calleeExpression == null) { return null; } - OverloadDomain overloadDomain = services.getOverloadDomain(receiverType, context.scope, calleeExpression, callExpression.getValueArgumentList()); - return services.resolveCall(context.scope, overloadDomain, callExpression); + OverloadDomain overloadDomain = context.services.getOverloadDomain(receiverType, context.scope, calleeExpression, callExpression.getValueArgumentList()); + return context.services.resolveCall(context.scope, overloadDomain, callExpression); } - private JetType getSelectorReturnType(JetType receiverType, JetExpression selectorExpression) { + private JetType getSelectorReturnType(JetType receiverType, JetExpression selectorExpression, TypeInferenceContext context) { if (selectorExpression instanceof JetCallExpression) { - return getCallExpressionType(receiverType, (JetCallExpression) selectorExpression); + return getCallExpressionType(receiverType, (JetCallExpression) selectorExpression, context); } else if (selectorExpression instanceof JetSimpleNameExpression) { JetScope compositeScope = new ScopeWithReceiver(context.scope, receiverType, semanticServices.getTypeChecker()); - return getType(compositeScope, selectorExpression, false); + return getType(compositeScope, selectorExpression, false, context); } else if (selectorExpression != null) { // TODO : not a simple name -> resolve in scope, expect property type or a function type @@ -2132,93 +2259,94 @@ public class JetTypeInferrer { } @Override - public void visitCallExpression(JetCallExpression expression) { - result = getCallExpressionType(null, expression); + public JetType visitCallExpression(JetCallExpression expression, TypeInferenceContext context) { + return context.services.checkType(getCallExpressionType(null, expression, context), expression, context); } @Override - public void visitIsExpression(JetIsExpression expression) { - JetType knownType = getType(context.scope, expression.getLeftHandSide(), false); + public JetType visitIsExpression(JetIsExpression expression, TypeInferenceContext contextWithExpectedType) { + TypeInferenceContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE); + JetType knownType = getType(context.scope, expression.getLeftHandSide(), false, context); JetPattern pattern = expression.getPattern(); if (pattern != null && knownType != null) { - WritableScopeImpl scopeToExtend = newWritableScopeImpl().setDebugName("Scope extended in 'is'"); - DataFlowInfo newDataFlowInfo = checkPatternType(pattern, knownType, scopeToExtend, getVariableDescriptorFromSimpleName(expression.getLeftHandSide())); + WritableScopeImpl scopeToExtend = newWritableScopeImpl(context.scope, context.trace).setDebugName("Scope extended in 'is'"); + DataFlowInfo newDataFlowInfo = checkPatternType(pattern, knownType, scopeToExtend, context, context.services.getVariableDescriptorFromSimpleName(expression.getLeftHandSide(), context)); patternsToDataFlowInfo.put(pattern, newDataFlowInfo); patternsToBoundVariableLists.put(pattern, scopeToExtend.getDeclaredVariables()); } - result = semanticServices.getStandardLibrary().getBooleanType(); + return context.services.checkType(semanticServices.getStandardLibrary().getBooleanType(), expression, contextWithExpectedType); } @Override - public void visitUnaryExpression(JetUnaryExpression expression) { + public JetType visitUnaryExpression(JetUnaryExpression expression, TypeInferenceContext contextWithExpectedType) { + TypeInferenceContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE); JetExpression baseExpression = expression.getBaseExpression(); - if (baseExpression == null) { - return; - } + if (baseExpression == null) return null; JetSimpleNameExpression operationSign = expression.getOperationSign(); if (JetTokens.LABELS.contains(operationSign.getReferencedNameElementType())) { // TODO : Some processing for the label? - result = getType(baseExpression); - return; + return context.services.checkType(getType(baseExpression, context.replaceExpectedReturnType(contextWithExpectedType.expectedType)), expression, contextWithExpectedType); } IElementType operationType = operationSign.getReferencedNameElementType(); String name = unaryOperationNames.get(operationType); if (name == null) { context.trace.getErrorHandler().genericError(operationSign.getNode(), "Unknown unary operation"); + return null; } - else { - JetType receiverType = getType(context.scope, baseExpression, false); - if (receiverType != null) { - FunctionDescriptor functionDescriptor = services.lookupFunction(context.scope, expression.getOperationSign(), name, receiverType, Collections.emptyList(), true); - if (functionDescriptor != null) { - JetType returnType = functionDescriptor.getReturnType(); - if (operationType == JetTokens.PLUSPLUS || operationType == JetTokens.MINUSMINUS) { - if (semanticServices.getTypeChecker().isSubtypeOf(returnType, JetStandardClasses.getUnitType())) { - result = JetStandardClasses.getUnitType(); - } - else { - if (!semanticServices.getTypeChecker().isSubtypeOf(returnType, receiverType)) { - context.trace.getErrorHandler().genericError(operationSign.getNode(), name + " must return " + receiverType + " but returns " + returnType); - } - else { - context.trace.recordVariableReassignment(expression); - } - // TODO : Maybe returnType? - result = receiverType; - } - } else { - result = returnType; - } + JetType receiverType = getType(context.scope, baseExpression, false, context); + if (receiverType == null) return null; + FunctionDescriptor functionDescriptor = context.services.lookupFunction(context.scope, expression.getOperationSign(), name, receiverType, Collections.emptyList(), true); + if (functionDescriptor == null) return null; + JetType returnType = functionDescriptor.getReturnType(); + JetType result; + if (operationType == JetTokens.PLUSPLUS || operationType == JetTokens.MINUSMINUS) { + if (semanticServices.getTypeChecker().isSubtypeOf(returnType, JetStandardClasses.getUnitType())) { + result = JetStandardClasses.getUnitType(); + } + else { + if (!semanticServices.getTypeChecker().isSubtypeOf(returnType, receiverType)) { + context.trace.getErrorHandler().genericError(operationSign.getNode(), name + " must return " + receiverType + " but returns " + returnType); } + else { + context.trace.recordVariableReassignment(expression); + } + // TODO : Maybe returnType? + result = receiverType; } } + else { + result = returnType; + } + return context.services.checkType(result, expression, contextWithExpectedType); } @Override - public void visitBinaryExpression(JetBinaryExpression expression) { + public JetType visitBinaryExpression(JetBinaryExpression expression, TypeInferenceContext contextWithExpectedType) { + TypeInferenceContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE); JetSimpleNameExpression operationSign = expression.getOperationReference(); JetExpression left = expression.getLeft(); JetExpression right = expression.getRight(); + JetType result = null; IElementType operationType = operationSign.getReferencedNameElementType(); if (operationType == JetTokens.IDENTIFIER) { String referencedName = operationSign.getReferencedName(); if (referencedName != null) { - result = getTypeForBinaryCall(expression, referencedName, context.scope, true); + result = getTypeForBinaryCall(expression, referencedName, context.scope, true, context); } } else if (binaryOperationNames.containsKey(operationType)) { - result = getTypeForBinaryCall(expression, binaryOperationNames.get(operationType), context.scope, true); + result = getTypeForBinaryCall(expression, binaryOperationNames.get(operationType), context.scope, true, context); } else if (operationType == JetTokens.EQ) { - visitAssignment(expression); + result = visitAssignment(expression, context); } else if (assignmentOperationNames.containsKey(operationType)) { - visitAssignmentOperation(expression); + result = visitAssignmentOperation(expression, context); } else if (comparisonOperations.contains(operationType)) { - JetType compareToReturnType = getTypeForBinaryCall(expression, "compareTo", context.scope, true); + JetType compareToReturnType = getTypeForBinaryCall(expression, "compareTo", context.scope, true, context); if (compareToReturnType != null) { TypeConstructor constructor = compareToReturnType.getConstructor(); JetStandardLibrary standardLibrary = semanticServices.getStandardLibrary(); @@ -2233,16 +2361,16 @@ public class JetTypeInferrer { else if (equalsOperations.contains(operationType)) { String name = "equals"; if (right != null) { - JetType leftType = getType(context.scope, left, false); + JetType leftType = getType(context.scope, left, false, context); if (leftType != null) { - JetType rightType = getType(context.scope, right, false); + JetType rightType = getType(context.scope, right, false, context); if (rightType != null) { - FunctionDescriptor equals = services.lookupFunction( + FunctionDescriptor equals = context.services.lookupFunction( context.scope, operationSign, "equals", leftType, Collections.singletonList(JetStandardClasses.getNullableAnyType()), false); if (equals != null) { - if (ensureBooleanResult(operationSign, name, equals.getReturnType())) { - ensureNonemptyIntersectionOfOperandTypes(expression); + if (ensureBooleanResult(operationSign, name, equals.getReturnType(), context)) { + ensureNonemptyIntersectionOfOperandTypes(expression, context); } } else { @@ -2254,7 +2382,7 @@ public class JetTypeInferrer { result = semanticServices.getStandardLibrary().getBooleanType(); } else if (operationType == JetTokens.EQEQEQ || operationType == JetTokens.EXCLEQEQEQ) { - ensureNonemptyIntersectionOfOperandTypes(expression); + ensureNonemptyIntersectionOfOperandTypes(expression, context); // TODO : Check comparison pointlessness result = semanticServices.getStandardLibrary().getBooleanType(); @@ -2262,17 +2390,17 @@ public class JetTypeInferrer { else if (inOperations.contains(operationType)) { if (right == null) { result = ErrorUtils.createErrorType("No right argument"); // TODO - return; + return null; } - checkInExpression(operationSign, left, right); + checkInExpression(operationSign, left, right, context); result = semanticServices.getStandardLibrary().getBooleanType(); } else if (operationType == JetTokens.ANDAND || operationType == JetTokens.OROR) { - JetType leftType = getType(context.scope, left, false); - WritableScopeImpl leftScope = newWritableScopeImpl().setDebugName("Left scope of && or ||"); - DataFlowInfo flowInfoLeft = extractDataFlowInfoFromCondition(left, operationType == JetTokens.ANDAND, leftScope); // TODO: This gets computed twice: here and in extractDataFlowInfoFromCondition() for the whole condition - WritableScopeImpl rightScope = operationType == JetTokens.ANDAND ? leftScope : newWritableScopeImpl().setDebugName("Right scope of && or ||"); - JetType rightType = right == null ? null : getTypeWithNewDataFlowInfo(rightScope, right, false, flowInfoLeft); + JetType leftType = getType(context.scope, left, false, context); + WritableScopeImpl leftScope = newWritableScopeImpl(context.scope, context.trace).setDebugName("Left scope of && or ||"); + DataFlowInfo flowInfoLeft = extractDataFlowInfoFromCondition(left, operationType == JetTokens.ANDAND, leftScope, context); // TODO: This gets computed twice: here and in extractDataFlowInfoFromCondition() for the whole condition + WritableScopeImpl rightScope = operationType == JetTokens.ANDAND ? leftScope : newWritableScopeImpl(context.scope, context.trace).setDebugName("Right scope of && or ||"); + JetType rightType = right == null ? null : getTypeWithNewDataFlowInfo(rightScope, right, false, flowInfoLeft, context); if (leftType != null && !isBoolean(leftType)) { context.trace.getErrorHandler().typeMismatch(left, semanticServices.getStandardLibrary().getBooleanType(), leftType); } @@ -2282,8 +2410,8 @@ public class JetTypeInferrer { result = semanticServices.getStandardLibrary().getBooleanType(); } else if (operationType == JetTokens.ELVIS) { - JetType leftType = getType(context.scope, left, false); - JetType rightType = right == null ? null : getType(context.scope, right, false); + JetType leftType = getType(context.scope, left, false, context); + JetType rightType = right == null ? null : getType(context.scope, right, false, context); if (leftType != null) { if (!leftType.isNullable()) { context.trace.getErrorHandler().genericWarning(left.getNode(), "Elvis operator (?:) is always returns the left operand of non-nullable type " + leftType); @@ -2296,23 +2424,24 @@ public class JetTypeInferrer { else { context.trace.getErrorHandler().genericError(operationSign.getNode(), "Unknown operation"); } + return context.services.checkType(result, expression, contextWithExpectedType); } - private void checkInExpression(JetSimpleNameExpression operationSign, JetExpression left, JetExpression right) { + private void checkInExpression(JetSimpleNameExpression operationSign, JetExpression left, JetExpression right, TypeInferenceContext context) { String name = "contains"; - JetType containsType = getTypeForBinaryCall(context.scope, right, operationSign, left, name, true); - ensureBooleanResult(operationSign, name, containsType); + JetType containsType = getTypeForBinaryCall(context.scope, right, operationSign, left, name, true, context); + ensureBooleanResult(operationSign, name, containsType, context); } - private void ensureNonemptyIntersectionOfOperandTypes(JetBinaryExpression expression) { + private void ensureNonemptyIntersectionOfOperandTypes(JetBinaryExpression expression, TypeInferenceContext context) { JetSimpleNameExpression operationSign = expression.getOperationReference(); JetExpression left = expression.getLeft(); JetExpression right = expression.getRight(); // TODO : duplicated effort for == and != - JetType leftType = getType(context.scope, left, false); + JetType leftType = getType(context.scope, left, false, context); if (leftType != null && right != null) { - JetType rightType = getType(context.scope, right, false); + JetType rightType = getType(context.scope, right, false, context); if (rightType != null) { JetType intersect = TypeUtils.intersect(semanticServices.getTypeChecker(), new HashSet(Arrays.asList(leftType, rightType))); @@ -2323,23 +2452,24 @@ public class JetTypeInferrer { } } - protected void visitAssignmentOperation(JetBinaryExpression expression) { - assignmentIsNotAnExpressionError(expression); + protected JetType visitAssignmentOperation(JetBinaryExpression expression, TypeInferenceContext context) { + return assignmentIsNotAnExpressionError(expression, context); } - protected void visitAssignment(JetBinaryExpression expression) { - assignmentIsNotAnExpressionError(expression); + protected JetType visitAssignment(JetBinaryExpression expression, TypeInferenceContext context) { + return assignmentIsNotAnExpressionError(expression, context); } - private void assignmentIsNotAnExpressionError(JetBinaryExpression expression) { + private JetType assignmentIsNotAnExpressionError(JetBinaryExpression expression, TypeInferenceContext context) { context.trace.getErrorHandler().genericError(expression.getNode(), "Assignments are not expressions, and only expressions are allowed in this context"); + return null; } - private boolean ensureBooleanResult(JetExpression operationSign, String name, JetType resultType) { - return ensureBooleanResultWithCustomSubject(operationSign, resultType, "'" + name + "'"); + private boolean ensureBooleanResult(JetExpression operationSign, String name, JetType resultType, TypeInferenceContext context) { + return ensureBooleanResultWithCustomSubject(operationSign, resultType, "'" + name + "'", context); } - private boolean ensureBooleanResultWithCustomSubject(JetExpression operationSign, JetType resultType, String subjectName) { + private boolean ensureBooleanResultWithCustomSubject(JetExpression operationSign, JetType resultType, String subjectName, TypeInferenceContext context) { if (resultType != null) { // TODO : Relax? if (!isBoolean(resultType)) { @@ -2355,35 +2485,37 @@ public class JetTypeInferrer { } @Nullable - protected List getTypes(JetScope scope, List indexExpressions) { + protected List getTypes(JetScope scope, List indexExpressions, TypeInferenceContext context) { List argumentTypes = new ArrayList(); - TypeInferrerVisitor typeInferrerVisitor = new TypeInferrerVisitor(new TypeInferenceContext(context.trace, scope, false, context.dataFlowInfo, NO_EXPECTED_TYPE, null)); + TypeInferenceContext newContext = new TypeInferenceContext(context.trace, scope, context.services, false, context.dataFlowInfo, NO_EXPECTED_TYPE, NO_EXPECTED_TYPE); for (JetExpression indexExpression : indexExpressions) { - JetType type = typeInferrerVisitor.getType(indexExpression); + JetType type = context.services.typeInferrerVisitor.getType(indexExpression, newContext); if (type == null) { return null; } argumentTypes.add(type); - typeInferrerVisitor.resetResult(); // TODO : recreate? + context.services.typeInferrerVisitor.resetResult(); // TODO : recreate? } return argumentTypes; } @Override - public void visitArrayAccessExpression(JetArrayAccessExpression expression) { + public JetType visitArrayAccessExpression(JetArrayAccessExpression expression, TypeInferenceContext contextWithExpectedType) { + TypeInferenceContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE); JetExpression arrayExpression = expression.getArrayExpression(); - JetType receiverType = getType(context.scope, arrayExpression, false); + JetType receiverType = getType(context.scope, arrayExpression, false, context); List indexExpressions = expression.getIndexExpressions(); - List argumentTypes = getTypes(context.scope, indexExpressions); - if (argumentTypes == null) return; + List argumentTypes = getTypes(context.scope, indexExpressions, context); + if (argumentTypes == null) return null; if (receiverType != null) { - FunctionDescriptor functionDescriptor = services.lookupFunction(context.scope, expression, "get", receiverType, argumentTypes, true); + FunctionDescriptor functionDescriptor = context.services.lookupFunction(context.scope, expression, "get", receiverType, argumentTypes, true); if (functionDescriptor != null) { // checkNullSafety(receiverType, expression.getIndexExpressions().get(0).getNode(), functionDescriptor); - result = functionDescriptor.getReturnType(); + return context.services.checkType(functionDescriptor.getReturnType(), expression, contextWithExpectedType); } } + return null; } @Nullable @@ -2391,14 +2523,15 @@ public class JetTypeInferrer { @NotNull JetBinaryExpression expression, @NotNull String name, @NotNull JetScope scope, - boolean reportUnresolved) { + boolean reportUnresolved, + @NotNull TypeInferenceContext context) { JetExpression left = expression.getLeft(); JetExpression right = expression.getRight(); if (right == null) { return null; } JetSimpleNameExpression operationSign = expression.getOperationReference(); - return getTypeForBinaryCall(scope, left, operationSign, right, name, reportUnresolved); + return getTypeForBinaryCall(scope, left, operationSign, right, name, reportUnresolved, context); } @Nullable @@ -2408,13 +2541,14 @@ public class JetTypeInferrer { @NotNull JetSimpleNameExpression operationSign, @NotNull JetExpression right, @NotNull String name, - boolean reportUnresolved) { - JetType leftType = getType(scope, left, false); - JetType rightType = getType(scope, right, false); + boolean reportUnresolved, + @NotNull TypeInferenceContext context) { + JetType leftType = getType(scope, left, false, context); + JetType rightType = getType(scope, right, false, context); if (leftType == null || rightType == null) { return null; } - FunctionDescriptor functionDescriptor = services.lookupFunction(scope, operationSign, name, leftType, Collections.singletonList(rightType), reportUnresolved); + FunctionDescriptor functionDescriptor = context.services.lookupFunction(scope, operationSign, name, leftType, Collections.singletonList(rightType), reportUnresolved); if (functionDescriptor != null) { if (leftType.isNullable()) { // TODO : better error message for '1 + nullableVar' case @@ -2431,19 +2565,21 @@ public class JetTypeInferrer { } @Override - public void visitDeclaration(JetDeclaration dcl) { + public JetType visitDeclaration(JetDeclaration dcl, TypeInferenceContext context) { context.trace.getErrorHandler().genericError(dcl.getNode(), "Declarations are not allowed in this position"); + return null; } @Override - public void visitRootNamespaceExpression(JetRootNamespaceExpression expression) { + public JetType visitRootNamespaceExpression(JetRootNamespaceExpression expression, TypeInferenceContext context) { context.trace.getErrorHandler().genericError(expression.getNode(), "'namespace' is not an expression"); - result = null; + return null; } @Override - public void visitStringTemplateExpression(JetStringTemplateExpression expression) { + public JetType visitStringTemplateExpression(JetStringTemplateExpression expression, TypeInferenceContext contextWithExpectedType) { + final TypeInferenceContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE); final StringBuilder builder = new StringBuilder(); final CompileTimeConstant[] value = new CompileTimeConstant[1]; for (JetStringTemplateEntry entry : expression.getEntries()) { @@ -2453,7 +2589,7 @@ public class JetTypeInferrer { public void visitStringTemplateEntryWithExpression(JetStringTemplateEntryWithExpression entry) { JetExpression entryExpression = entry.getExpression(); if (entryExpression != null) { - getType(context.scope, entryExpression, true); + getType(context.scope, entryExpression, true, context); } value[0] = CompileTimeConstantResolver.OUT_OF_RANGE; } @@ -2484,40 +2620,31 @@ public class JetTypeInferrer { if (value[0] != CompileTimeConstantResolver.OUT_OF_RANGE) { context.trace.recordCompileTimeValue(expression, new StringValue(builder.toString())); } - result = semanticServices.getStandardLibrary().getStringType(); + return context.services.checkType(semanticServices.getStandardLibrary().getStringType(), expression, contextWithExpectedType); } @Override - public void visitJetElement(JetElement element) { + public JetType visitJetElement(JetElement element, TypeInferenceContext context) { context.trace.getErrorHandler().genericError(element.getNode(), "[JetTypeInferrer] Unsupported element: " + element + " " + element.getClass().getCanonicalName()); + return null; } } private class TypeInferrerVisitorWithNamespaces extends TypeInferrerVisitor { - private TypeInferrerVisitorWithNamespaces(@NotNull TypeInferenceContext context) { - super(context); - } - - @NotNull - @Override - public TypeInferrerVisitor createNew(@NotNull TypeInferenceContext context) { - return new TypeInferrerVisitorWithNamespaces(context); - } - @Override public boolean isNamespacePosition() { return true; } @Override - public void visitRootNamespaceExpression(JetRootNamespaceExpression expression) { - result = JetModuleUtil.getRootNamespaceType(expression); + public JetType visitRootNamespaceExpression(JetRootNamespaceExpression expression, TypeInferenceContext context) { + return context.services.checkType(JetModuleUtil.getRootNamespaceType(expression), expression, context); } @Override - protected boolean furtherNameLookup(@NotNull JetSimpleNameExpression expression, @NotNull String referencedName) { - result = lookupNamespaceType(expression, referencedName); - return result != null; + protected LookupResult furtherNameLookup(@NotNull JetSimpleNameExpression expression, @NotNull String referencedName, TypeInferenceContext context) { + JetType result = lookupNamespaceType(expression, referencedName, context); + return new LookupResult(result, result != null); } } @@ -2525,20 +2652,18 @@ public class JetTypeInferrer { private class TypeInferrerVisitorWithWritableScope extends TypeInferrerVisitor { private final WritableScope scope; - public TypeInferrerVisitorWithWritableScope(@NotNull WritableScope scope, @NotNull TypeInferenceContext context) { - super(context); + public TypeInferrerVisitorWithWritableScope(@NotNull WritableScope scope) { this.scope = scope; } + +// public TypeInferrerVisitorWithWritableScope(@NotNull BindingTrace trace, @NotNull JetScope scope) { +// super(trace); +// this.scope = newWritableScopeImpl(scope, trace).setDebugName("Block scope"); +// } - @NotNull - @Override - public TypeInferrerVisitor createNew(@NotNull TypeInferenceContext context) { - WritableScopeImpl writableScope = newWritableScopeImpl(context.scope).setDebugName("Block scope"); - return new TypeInferrerVisitorWithWritableScope(writableScope, context); - } @Override - public void visitObjectDeclaration(JetObjectDeclaration declaration) { + public JetType visitObjectDeclaration(JetObjectDeclaration declaration, TypeInferenceContext context) { TopDownAnalyzer topDownAnalyzer = new TopDownAnalyzer(semanticServices, context.trace); topDownAnalyzer.processObject(scope, scope.getContainingDeclaration(), declaration); ClassDescriptor classDescriptor = context.trace.getBindingContext().getClassDescriptor(declaration); @@ -2546,10 +2671,11 @@ public class JetTypeInferrer { PropertyDescriptor propertyDescriptor = context.classDescriptorResolver.resolveObjectDeclarationAsPropertyDescriptor(scope.getContainingDeclaration(), declaration, classDescriptor); scope.addVariableDescriptor(propertyDescriptor); } + return null; } @Override - public void visitProperty(JetProperty property) { + public JetType visitProperty(JetProperty property, TypeInferenceContext context) { JetTypeReference receiverTypeRef = property.getReceiverTypeRef(); if (receiverTypeRef != null) { context.trace.getErrorHandler().genericError(receiverTypeRef.getNode(), "Local receiver-properties are not allowed"); @@ -2568,98 +2694,101 @@ public class JetTypeInferrer { VariableDescriptor propertyDescriptor = context.classDescriptorResolver.resolveLocalVariableDescriptor(scope.getContainingDeclaration(), scope, property); JetExpression initializer = property.getInitializer(); if (property.getPropertyTypeRef() != null && initializer != null) { - JetType initializerType = getType(scope, initializer, false); JetType outType = propertyDescriptor.getOutType(); - if (outType != null && - initializerType != null && - !semanticServices.getTypeChecker().isConvertibleTo(initializerType, outType)) { - context.trace.getErrorHandler().typeMismatch(initializer, outType, initializerType); - } + JetType initializerType = getType(scope, initializer, false, context.replaceExpectedType(outType)); +// if (outType != null && +// initializerType != null && +// !semanticServices.getTypeChecker().isConvertibleTo(initializerType, outType)) { +// context.trace.getErrorHandler().typeMismatch(initializer, outType, initializerType); +// } } scope.addVariableDescriptor(propertyDescriptor); + return null; } @Override - public void visitNamedFunction(JetNamedFunction function) { - scope.addFunctionDescriptor(context.classDescriptorResolver.resolveFunctionDescriptor(scope.getContainingDeclaration(), scope, function)); + public JetType visitNamedFunction(JetNamedFunction function, TypeInferenceContext context) { + FunctionDescriptorImpl functionDescriptor = context.classDescriptorResolver.resolveFunctionDescriptor(scope.getContainingDeclaration(), scope, function); + scope.addFunctionDescriptor(functionDescriptor); + context.services.checkFunctionReturnType(context.scope, function, functionDescriptor, context.dataFlowInfo); + return null; } @Override - public void visitClass(JetClass klass) { - super.visitClass(klass); // TODO + public JetType visitClass(JetClass klass, TypeInferenceContext context) { + return super.visitClass(klass, context); // TODO } @Override - public void visitTypedef(JetTypedef typedef) { - super.visitTypedef(typedef); // TODO + public JetType visitTypedef(JetTypedef typedef, TypeInferenceContext context) { + return super.visitTypedef(typedef, context); // TODO } @Override - public void visitDeclaration(JetDeclaration dcl) { - visitJetElement(dcl); + public JetType visitDeclaration(JetDeclaration dcl, TypeInferenceContext context) { + return visitJetElement(dcl, context); } @Override - protected void visitAssignmentOperation(JetBinaryExpression expression) { + protected JetType visitAssignmentOperation(JetBinaryExpression expression, TypeInferenceContext context) { IElementType operationType = expression.getOperationReference().getReferencedNameElementType(); String name = assignmentOperationNames.get(operationType); - JetType assignmentOperationType = getTypeForBinaryCall(expression, name, scope, false); + JetType assignmentOperationType = getTypeForBinaryCall(expression, name, scope, false, context); if (assignmentOperationType == null) { String counterpartName = binaryOperationNames.get(assignmentOperationCounterparts.get(operationType)); - JetType typeForBinaryCall = getTypeForBinaryCall(expression, counterpartName, scope, true); + JetType typeForBinaryCall = getTypeForBinaryCall(expression, counterpartName, scope, true, context); if (typeForBinaryCall != null) { context.trace.recordVariableReassignment(expression); } } - result = null; // not an expression + return null; } @Override - protected void visitAssignment(JetBinaryExpression expression) { + protected JetType visitAssignment(JetBinaryExpression expression, TypeInferenceContext context) { JetExpression left = expression.getLeft(); JetExpression deparenthesized = JetPsiUtil.deparenthesize(left); JetExpression right = expression.getRight(); if (deparenthesized instanceof JetArrayAccessExpression) { JetArrayAccessExpression arrayAccessExpression = (JetArrayAccessExpression) deparenthesized; - resolveArrayAccessToLValue(arrayAccessExpression, right, expression.getOperationReference()); + return resolveArrayAccessToLValue(arrayAccessExpression, right, expression.getOperationReference(), context); } - else { - JetType leftType = getType(scope, left, false); - if (right != null) { - JetType rightType = getType(scope, right, false); - if (rightType != null && - leftType != null && - !semanticServices.getTypeChecker().isConvertibleTo(rightType, leftType)) { - context.trace.getErrorHandler().typeMismatch(right, leftType, rightType); - } + JetType leftType = getType(scope, left, false, context); + if (right != null) { + JetType rightType = getType(scope, right, false, context); + if (rightType != null && + leftType != null && + !semanticServices.getTypeChecker().isConvertibleTo(rightType, leftType)) { + context.trace.getErrorHandler().typeMismatch(right, leftType, rightType); } } - result = null; // This is not an element + return null; } - private void resolveArrayAccessToLValue(JetArrayAccessExpression arrayAccessExpression, JetExpression rightHandSide, JetSimpleNameExpression operationSign) { - List argumentTypes = getTypes(scope, arrayAccessExpression.getIndexExpressions()); - if (argumentTypes == null) return; - JetType rhsType = getType(scope, rightHandSide, false); - if (rhsType == null) return; + private JetType resolveArrayAccessToLValue(JetArrayAccessExpression arrayAccessExpression, JetExpression rightHandSide, JetSimpleNameExpression operationSign, TypeInferenceContext contextWithExpectedType) { + TypeInferenceContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE); + List argumentTypes = getTypes(scope, arrayAccessExpression.getIndexExpressions(), context); + if (argumentTypes == null) return null; + JetType rhsType = getType(scope, rightHandSide, false, context); + if (rhsType == null) return null; argumentTypes.add(rhsType); - JetType receiverType = getType(scope, arrayAccessExpression.getArrayExpression(), false); - if (receiverType == null) return; + JetType receiverType = getType(scope, arrayAccessExpression.getArrayExpression(), false, context); + if (receiverType == null) return null; // TODO : nasty hack: effort is duplicated - services.lookupFunction(scope, arrayAccessExpression, "set", receiverType, argumentTypes, true); - FunctionDescriptor functionDescriptor = services.lookupFunction(scope, operationSign, "set", receiverType, argumentTypes, true); - if (functionDescriptor != null) { - result = functionDescriptor.getReturnType(); - } + context.services.lookupFunction(scope, arrayAccessExpression, "set", receiverType, argumentTypes, true); + FunctionDescriptor functionDescriptor = context.services.lookupFunction(scope, operationSign, "set", receiverType, argumentTypes, true); + if (functionDescriptor == null) return null; + return context.services.checkType(functionDescriptor.getReturnType(), arrayAccessExpression, contextWithExpectedType); } @Override - public void visitJetElement(JetElement element) { + public JetType visitJetElement(JetElement element, TypeInferenceContext context) { context.trace.getErrorHandler().genericError(element.getNode(), "Unsupported element in a block: " + element + " " + element.getClass().getCanonicalName()); + return null; } } } diff --git a/idea/src/org/jetbrains/jet/resolve/DescriptorRenderer.java b/idea/src/org/jetbrains/jet/resolve/DescriptorRenderer.java index 2261bbaea69..e77446c986b 100644 --- a/idea/src/org/jetbrains/jet/resolve/DescriptorRenderer.java +++ b/idea/src/org/jetbrains/jet/resolve/DescriptorRenderer.java @@ -26,14 +26,11 @@ public class DescriptorRenderer { } public static final DescriptorRenderer TEXT = new DescriptorRenderer(); + //TODO remove TEXT_FOR_DEBUG public static final DescriptorRenderer TEXT_FOR_DEBUG = new DescriptorRenderer() { @Override public String renderType(JetType type) { - if (type instanceof DeferredType) { - DeferredType deferredType = (DeferredType) type; - if (!deferredType.isComputed()) return ""; - } - return "" + type; + return String.valueOf(type); } }; public static final DescriptorRenderer HTML = new DescriptorRenderer() { diff --git a/idea/testData/checker/AutomaticCasts.jet b/idea/testData/checker/AutomaticCasts.jet new file mode 100644 index 00000000000..36667a7cbdc --- /dev/null +++ b/idea/testData/checker/AutomaticCasts.jet @@ -0,0 +1,58 @@ +namespace automatic_casts + +fun toInt(i: Int?): Int = if (i != null) i else 0 +fun illegalWhenBody(a: Any): Int = when(a) { + is Int => a + is String => a +} +fun illegalWhenBlock(a: Any): Int { + when(a) { + is Int => return a + is String => return a + } +} +fun declarations(a: Any?) { + if (a is String) { + val p4: (Int, String) = (2, a) + } + if (a is String?) { + if (a != null) { + val s: String = a + } + } + if (a != null) { + if (a is String?) { + val s: String = a + } + } +} +fun tuples(a: Any?) { + if (a != null) { + val s: (Any, String) = (a, a) + } + if (a is String) { + val s: (Any, String) = (a, a) + } + fun illegalTupleReturnType(): (Any, String) = (a, a) + if (a is String) { + fun legalTupleReturnType(): (Any, String) = (a, a) + } + val illegalFunctionLiteral: Function0 = { a } + val illegalReturnValueInFunctionLiteral: Function0 = { (): Int => a } + + if (a is Int) { + val legalFunctionLiteral: Function0 = { a } + val alsoLegalFunctionLiteral: Function0 = { (): Int => a } + } +} +fun returnFunctionLiteralBlock(a: Any?): Function0 { + if (a is Int) return { a } + else return { 1 } +} +fun returnFunctionLiteral(a: Any?): Function0 = + if (a is Int) { (): Int => a } + else { () => 1 } + +fun illegalTupleReturnType(a: Any): (Any, String) = (a, a) + +fun declarationInsidePattern(x: (Any, Any)): String = when(x) { is (val a is String, *) => a; else => "something" } \ No newline at end of file diff --git a/idea/testData/checker/FunctionReturnTypes.jet b/idea/testData/checker/FunctionReturnTypes.jet index a0703efbbfc..a541589263a 100644 --- a/idea/testData/checker/FunctionReturnTypes.jet +++ b/idea/testData/checker/FunctionReturnTypes.jet @@ -61,7 +61,7 @@ fun blockAndAndMismatch() : Int { (return true) || (return false) } fun blockReturnValueTypeMatch() : Int { - return if (1 > 2) 1.0 else 2.0 + return if (1 > 2) 1.0 else 2.0 } fun blockReturnValueTypeMatch() : Int { return if (1 > 2) 1 @@ -138,4 +138,27 @@ class A() { return 1 } -} \ No newline at end of file +} +fun illegalConstantBody(): Int = "s" +fun illegalConstantBlock(): String { + return 1 +} +fun illegalIfBody(): Int = + if (1 < 2) 'a' else { 1.0 } +fun illegalIfBlock(): Boolean { + if (1 < 2) + return false + else { return 1 } +} +fun illegalReturnIf(): Char { + return if (1 < 2) 'a' else { 1 } +} + +fun returnNothing(): Nothing { + throw 1 +} +fun f(): Int { + if (1 < 2) { return 1 } else returnNothing() +} + +fun f(): Int = if (1 < 2) 1 else returnNothing() diff --git a/idea/testData/checker/Unresolved.jet b/idea/testData/checker/Unresolved.jet new file mode 100644 index 00000000000..9e361861010 --- /dev/null +++ b/idea/testData/checker/Unresolved.jet @@ -0,0 +1,30 @@ +namespace unresolved + +fun testGenericArgumentsCount() { + val p1: Tuple2 = (2, 2) + val p2: Tuple2 = (2, 2) +} + +fun testUnresolved() { + if (a is String) { + val s = a + } + foo(a) + val s = "s" + foo(s) + foo1(i) + s.foo() + + when(a) { + is Int => a + is String => a + } + + //TODO + for (j in collection) { + val i: Int = j + j += 1 + } +} + +fun foo1(i: Int) {}