function invocation with only type parameters prohibited

This commit is contained in:
Svetlana Isakova
2012-05-23 22:04:22 +04:00
parent 327b471eaf
commit 0fd882741b
22 changed files with 78 additions and 47 deletions
@@ -321,7 +321,7 @@ public interface Errors {
DiagnosticFactory2<JetDeclaration, CallableMemberDescriptor, String> CONFLICTING_OVERLOADS = DiagnosticFactory2.create(ERROR, DECLARATION); DiagnosticFactory2<JetDeclaration, CallableMemberDescriptor, String> CONFLICTING_OVERLOADS = DiagnosticFactory2.create(ERROR, DECLARATION);
DiagnosticFactory2<JetReferenceExpression, JetExpression, JetType> FUNCTION_EXPECTED = DiagnosticFactory2.create(ERROR); DiagnosticFactory2<JetReferenceExpression, JetExpression, JetType> FUNCTION_EXPECTED = DiagnosticFactory2.create(ERROR);
DiagnosticFactory2<JetReferenceExpression, JetExpression, Boolean> FUNCTION_CALL_EXPECTED = DiagnosticFactory2.create(ERROR); DiagnosticFactory2<JetExpression, JetExpression, Boolean> FUNCTION_CALL_EXPECTED = DiagnosticFactory2.create(ERROR, CALL_EXPRESSION);
DiagnosticFactory3<JetExpression, String, JetType, JetType> RESULT_TYPE_MISMATCH = DiagnosticFactory3.create(ERROR); DiagnosticFactory3<JetExpression, String, JetType, JetType> RESULT_TYPE_MISMATCH = DiagnosticFactory3.create(ERROR);
DiagnosticFactory3<JetReferenceExpression, String, String, String> UNSAFE_INFIX_CALL = DiagnosticFactory3.create(ERROR); DiagnosticFactory3<JetReferenceExpression, String, String, String> UNSAFE_INFIX_CALL = DiagnosticFactory3.create(ERROR);
@@ -298,4 +298,28 @@ public class PositioningStrategies {
return markNode(element.getQuestionMarkNode()); return markNode(element.getQuestionMarkNode());
} }
}; };
public static PositioningStrategy<JetExpression> CALL_EXPRESSION = new PositioningStrategy<JetExpression>() {
@NotNull
@Override
public List<TextRange> mark(@NotNull JetExpression element) {
if (element instanceof JetCallExpression) {
JetCallExpression callExpression = (JetCallExpression) element;
PsiElement endElement;
JetTypeArgumentList typeArgumentList = callExpression.getTypeArgumentList();
JetExpression calleeExpression = callExpression.getCalleeExpression();
if (typeArgumentList != null) {
endElement = typeArgumentList;
}
else if (calleeExpression != null) {
endElement = calleeExpression;
}
else {
endElement = element;
}
return markRange(new TextRange(element.getTextRange().getStartOffset(), endElement.getTextRange().getEndOffset()));
}
return super.mark(element);
}
};
} }
@@ -77,6 +77,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
return type; // TODO : Extensions to this return type; // TODO : Extensions to this
} }
@Nullable
private JetType lookupNamespaceOrClassObject(JetSimpleNameExpression expression, Name referencedName, ExpressionTypingContext context) { private JetType lookupNamespaceOrClassObject(JetSimpleNameExpression expression, Name referencedName, ExpressionTypingContext context) {
ClassifierDescriptor classifier = context.scope.getClassifier(referencedName); ClassifierDescriptor classifier = context.scope.getClassifier(referencedName);
if (classifier != null) { if (classifier != null) {
@@ -90,9 +91,9 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
context.trace.report(NO_CLASS_OBJECT.on(expression, classifier)); context.trace.report(NO_CLASS_OBJECT.on(expression, classifier));
} }
context.trace.record(REFERENCE_TARGET, expression, classifier); context.trace.record(REFERENCE_TARGET, expression, classifier);
if (result == null) { //if (result == null) {
return ErrorUtils.createErrorType("No class object in " + expression.getReferencedName()); // return ErrorUtils.createErrorType("No class object in " + expression.getReferencedName());
} //}
return DataFlowUtils.checkType(result, expression, context); return DataFlowUtils.checkType(result, expression, context);
} }
} }
@@ -684,7 +685,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
if (result[0]) { if (result[0]) {
traceForFunction.commit(); traceForFunction.commit();
boolean hasValueParameters = functionDescriptor == null || functionDescriptor.getValueParameters().size() > 0; boolean hasValueParameters = functionDescriptor == null || functionDescriptor.getValueParameters().size() > 0;
context.trace.report(Errors.FUNCTION_CALL_EXPECTED.on(nameExpression, nameExpression, hasValueParameters)); context.trace.report(FUNCTION_CALL_EXPECTED.on(nameExpression, nameExpression, hasValueParameters));
return functionDescriptor != null ? functionDescriptor.getReturnType() : null; return functionDescriptor != null ? functionDescriptor.getReturnType() : null;
} }
@@ -704,17 +705,23 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
context.replaceBindingTrace(traceForFunction), result); context.replaceBindingTrace(traceForFunction), result);
if (result[0]) { if (result[0]) {
traceForFunction.commit(); traceForFunction.commit();
if (callExpression.getValueArgumentList() == null && callExpression.getFunctionLiteralArguments().isEmpty()) {
// there are only type arguments
boolean hasValueParameters = functionDescriptor == null || functionDescriptor.getValueParameters().size() > 0;
context.trace.report(FUNCTION_CALL_EXPECTED.on(callExpression, callExpression, hasValueParameters));
}
return functionDescriptor != null ? functionDescriptor.getReturnType() : null; return functionDescriptor != null ? functionDescriptor.getReturnType() : null;
} }
JetExpression calleeExpression = callExpression.getCalleeExpression(); JetExpression calleeExpression = callExpression.getCalleeExpression();
if (calleeExpression instanceof JetSimpleNameExpression) { if (calleeExpression instanceof JetSimpleNameExpression && callExpression.getTypeArgumentList() == null) {
TemporaryBindingTrace traceForVariable = TemporaryBindingTrace.create(context.trace); TemporaryBindingTrace traceForVariable = TemporaryBindingTrace.create(context.trace);
JetType type = getVariableType((JetSimpleNameExpression) calleeExpression, receiver, callOperationNode, JetType type = getVariableType((JetSimpleNameExpression) calleeExpression, receiver, callOperationNode,
context.replaceBindingTrace(traceForVariable), result); context.replaceBindingTrace(traceForVariable), result);
if (result[0]) { if (result[0]) {
traceForVariable.commit(); traceForVariable.commit();
context.trace.report(Errors.FUNCTION_EXPECTED.on((JetReferenceExpression) calleeExpression, callExpression, type != null ? type : ErrorUtils.createErrorType(""))); context.trace.report(FUNCTION_EXPECTED.on((JetReferenceExpression) calleeExpression, calleeExpression,
type != null ? type : ErrorUtils.createErrorType("")));
return null; return null;
} }
} }
@@ -722,7 +729,8 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
return null; return null;
} }
private static void checkSuper(@NotNull ReceiverDescriptor receiverDescriptor, @NotNull OverloadResolutionResults<? extends CallableDescriptor> results, @NotNull BindingTrace trace, @NotNull JetExpression expression) { private static void checkSuper(@NotNull ReceiverDescriptor receiverDescriptor, @NotNull OverloadResolutionResults<? extends CallableDescriptor> results,
@NotNull BindingTrace trace, @NotNull JetExpression expression) {
if (!results.isSingleResult()) return; if (!results.isSingleResult()) return;
if (!(receiverDescriptor instanceof ExpressionReceiver)) return; if (!(receiverDescriptor instanceof ExpressionReceiver)) return;
JetExpression receiver = ((ExpressionReceiver) receiverDescriptor).getExpression(); JetExpression receiver = ((ExpressionReceiver) receiverDescriptor).getExpression();
@@ -2,7 +2,7 @@ import java.util.*
import java.io.* import java.io.*
class World() { class World() {
public val items: ArrayList<Item> = ArrayList<Item> public val items: ArrayList<Item> = ArrayList<Item>()
class Item() { class Item() {
{ {
@@ -11,7 +11,7 @@ fun box() : String {
// val vals = iarray(789, 678, 567, 456, 345, 234, 123, 012) // val vals = iarray(789, 678, 567, 456, 345, 234, 123, 012)
val vals = iarray(789, 678, 567, 456, 345, 234, 123, 12) val vals = iarray(789, 678, 567, 456, 345, 234, 123, 12)
val diffs = HashSet<Int> val diffs = HashSet<Int>()
for (i in vals.indices) for (i in vals.indices)
for (j in i..vals.lastIndex()) for (j in i..vals.lastIndex())
diffs.add(vals[i] - vals[j]) diffs.add(vals[i] - vals[j])
+1 -1
View File
@@ -10,5 +10,5 @@ class Box<T>() {
} }
fun box(): String { fun box(): String {
return Box<String>.inner().isT("OK") return Box<String>().inner().isT("OK")
} }
@@ -10,9 +10,9 @@ package boundsWithSubstitutors
class X<A, B : A>() class X<A, B : A>()
val b = X<Any, X<A<C>, C>> val b = X<Any, X<A<C>, C>>()
val b0 = X<Any, <!UPPER_BOUND_VIOLATED!>Any?<!>> val b0 = X<Any, <!UPPER_BOUND_VIOLATED!>Any?<!>>()
val b1 = X<Any, X<A<C>, <!UPPER_BOUND_VIOLATED!>String<!>>> val b1 = X<Any, X<A<C>, <!UPPER_BOUND_VIOLATED!>String<!>>>()
// FILE: b.kt // FILE: b.kt
open class A {} open class A {}
@@ -18,8 +18,8 @@ fun test(<!UNUSED_PARAMETER!>l<!> : java.util.List<Int>) {
val <!UNUSED_VARIABLE!>f<!> : java.io.File? = null val <!UNUSED_VARIABLE!>f<!> : java.io.File? = null
Collections.<!UNRESOLVED_REFERENCE!>emptyList<!> Collections.<!TYPE_INFERENCE_FAILED, FUNCTION_CALL_EXPECTED!>emptyList<!>
Collections.emptyList<Int> Collections.<!FUNCTION_CALL_EXPECTED!>emptyList<Int><!>
Collections.emptyList<Int>() Collections.emptyList<Int>()
Collections.<!TYPE_INFERENCE_FAILED!>emptyList()<!> Collections.<!TYPE_INFERENCE_FAILED!>emptyList()<!>
@@ -51,4 +51,4 @@ fun test(<!UNUSED_PARAMETER!>l<!> : java.util.List<Int>) {
// FILE: f.kt // FILE: f.kt
package xxx package xxx
import java.lang.Class; import java.lang.Class;
@@ -4,12 +4,12 @@ package kotlin1
import java.util.* import java.util.*
fun main(args : Array<String>) { fun main(args : Array<String>) {
val al : ArrayList<Int> = ArrayList<Int> val al : ArrayList<Int> = ArrayList<Int>()
val al1 = ArrayList<Int>(1) val al1 = ArrayList<Int>(1)
// for (x in al1) { // for (x in al1) {
// //
// } // }
val <!UNUSED_VARIABLE!>al2<!> = ArrayList<Int>(ArrayList<Int>) val <!UNUSED_VARIABLE!>al2<!> = ArrayList<Int>(ArrayList<Int>())
al : RandomAccess al : RandomAccess
al.clear() : Unit al.clear() : Unit
al.add(1) : Boolean al.add(1) : Boolean
@@ -4,6 +4,6 @@ package kotlin1
import java.util.* import java.util.*
fun main(args : Array<String>) { fun main(args : Array<String>) {
val al : ArrayList<Int> = ArrayList<Int> val al : ArrayList<Int> = ArrayList<Int>()
al.clone() : Object // A type mismatch on this line means that alt-headers were not loaded al.clone() : Object // A type mismatch on this line means that alt-headers were not loaded
} }
@@ -4,7 +4,7 @@ package kotlin1
import java.util.* import java.util.*
fun main(args : Array<String>) { fun main(args : Array<String>) {
val al : ArrayList<Int> = ArrayList<Int> val al : ArrayList<Int> = ArrayList<Int>()
// A type mismatch on this line means that alt-headers were not loaded // A type mismatch on this line means that alt-headers were not loaded
al.toArray(Array<Int>(3, {1})) : Array<Int> al.toArray(Array<Int>(3, {1})) : Array<Int>
@@ -9,5 +9,5 @@ package a
fun foo() { fun foo() {
// If this fails, it means that we have broken the rule that Java returns are always nullable // If this fails, it means that we have broken the rule that Java returns are always nullable
a.Test<Int>.t() <!UNSAFE_INFIX_CALL!>+<!> 1 a.Test<Int>().t() <!UNSAFE_INFIX_CALL!>+<!> 1
} }
@@ -6,7 +6,7 @@ abstract class Item(val room: Object) {
abstract val name : String abstract val name : String
} }
val items: ArrayList<Item> = ArrayList<Item> val items: ArrayList<Item> = ArrayList<Item>()
fun test(room : Object) { fun test(room : Object) {
for(val item: Item? in items) { for(val item: Item? in items) {
@@ -3,7 +3,7 @@ class Point() {
class G<T>() {} class G<T>() {}
fun f<T>(<!UNUSED_PARAMETER!>expression<!> : T) : G<out T> = G<T> fun f<T>(<!UNUSED_PARAMETER!>expression<!> : T) : G<out T> = G<T>()
fun foo() : G<Point> { fun foo() : G<Point> {
@@ -13,7 +13,7 @@ fun foo() : G<Point> {
class Out<out T>() {} class Out<out T>() {}
fun fout<T>(<!UNUSED_PARAMETER!>expression<!> : T) : Out<out T> = Out<T> fun fout<T>(<!UNUSED_PARAMETER!>expression<!> : T) : Out<out T> = Out<T>()
fun fooout() : Out<Point> { fun fooout() : Out<Point> {
val p = Point(); val p = Point();
@@ -8,7 +8,7 @@ fun iarray(vararg a : String) = a // BUG
fun main() { fun main() {
val vals = iarray("789", "678", "567") val vals = iarray("789", "678", "567")
val diffs = ArrayList<Int> val diffs = ArrayList<Int>()
for (i in vals.indices) { for (i in vals.indices) {
for (j in i..vals.lastIndex()) // Type inference failed for (j in i..vals.lastIndex()) // Type inference failed
diffs.add(vals[i].length - vals[j].length) diffs.add(vals[i].length - vals[j].length)
@@ -10,8 +10,8 @@ public class Throwables() {
} }
} }
public fun propagateIfPossible(throwable : Throwable?) { public fun propagateIfPossible(throwable : Throwable?) {
propagateIfInstanceOf(throwable, getJavaClass<Error?>) //; Type inference failed: Mismatch while expanding constraints propagateIfInstanceOf(throwable, getJavaClass<Error?>()) //; Type inference failed: Mismatch while expanding constraints
propagateIfInstanceOf(throwable, getJavaClass<RuntimeException?>) // Type inference failed: Mismatch while expanding constraints propagateIfInstanceOf(throwable, getJavaClass<RuntimeException?>()) // Type inference failed: Mismatch while expanding constraints
} }
} }
} }
@@ -9,8 +9,8 @@ fun <T> TypeInfo<T>.getJavaClass() : java.lang.Class<T> {
return <!UNCHECKED_CAST!>t.getClass() as java.lang.Class<T><!> // inferred type is Object but Serializable was expected return <!UNCHECKED_CAST!>t.getClass() as java.lang.Class<T><!> // inferred type is Object but Serializable was expected
} }
fun getJavaClass<T>() = typeinfo<T>.getJavaClass() fun getJavaClass<T>() = typeinfo<T>().getJavaClass()
fun main(args : Array<String>) { fun main(args : Array<String>) {
System.out.println(getJavaClass<String>) System.out.println(getJavaClass<String>())
} }
@@ -3,5 +3,5 @@ import java.util.ArrayList
class MyListOfPairs<T> : ArrayList<#(T, T)>() { } class MyListOfPairs<T> : ArrayList<#(T, T)>() { }
fun test() { fun test() {
MyListOfPairs<Int> : ArrayList<#(Int, Int)> MyListOfPairs<Int>() : ArrayList<#(Int, Int)>
} }
@@ -22,17 +22,16 @@ import com.intellij.psi.PsiFile;
import com.intellij.util.IncorrectOperationException; import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.diagnostics.Diagnostic; import org.jetbrains.jet.lang.diagnostics.Diagnostic;
import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetPsiFactory;
import org.jetbrains.jet.plugin.JetBundle; import org.jetbrains.jet.plugin.JetBundle;
import java.util.List;
/** /**
* @author svtk * @author svtk
*/ */
public class ChangeToFunctionInvocationFix extends JetIntentionAction<JetReferenceExpression> { public class ChangeToFunctionInvocationFix extends JetIntentionAction<JetExpression> {
public ChangeToFunctionInvocationFix(@NotNull JetReferenceExpression element) { public ChangeToFunctionInvocationFix(@NotNull JetExpression element) {
super(element); super(element);
} }
@@ -50,16 +49,16 @@ public class ChangeToFunctionInvocationFix extends JetIntentionAction<JetReferen
@Override @Override
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
JetReferenceExpression reference = (JetReferenceExpression) element.copy(); JetExpression reference = (JetExpression) element.copy();
element.replace(JetPsiFactory.createExpression(project, reference.getText() + "()")); element.replace(JetPsiFactory.createExpression(project, reference.getText() + "()"));
} }
public static JetIntentionActionFactory createFactory() { public static JetIntentionActionFactory createFactory() {
return new JetIntentionActionFactory() { return new JetIntentionActionFactory() {
@Override @Override
public JetIntentionAction<JetReferenceExpression> createAction(Diagnostic diagnostic) { public JetIntentionAction<JetExpression> createAction(Diagnostic diagnostic) {
if (diagnostic.getPsiElement() instanceof JetReferenceExpression) { if (diagnostic.getPsiElement() instanceof JetExpression) {
return new ChangeToFunctionInvocationFix((JetReferenceExpression) diagnostic.getPsiElement()); return new ChangeToFunctionInvocationFix((JetExpression) diagnostic.getPsiElement());
} }
return null; return null;
} }
@@ -8,6 +8,6 @@
class X<A, B : A>() class X<A, B : A>()
val b = X<Any, X<A<C>, C>> val b = X<Any, X<A<C>, C>>()
val b0 = X<Any, <error>Any?</error>> val b0 = X<Any, <error>Any?</error>>()
val b1 = X<Any, X<A<C>, <error>String</error>>> val b1 = X<Any, X<A<C>, <error>String</error>>>()
+2 -2
View File
@@ -16,8 +16,8 @@ fun test(<warning>l</warning> : java.util.List<Int>) {
val <warning>f</warning> : java.io.File? = null val <warning>f</warning> : java.io.File? = null
Collections.<error>emptyList</error> Collections.<error><error>emptyList</error></error>
Collections.emptyList<Int> Collections.<error>emptyList<Int></error>
Collections.emptyList<Int>() Collections.emptyList<Int>()
Collections.<error>emptyList()</error> Collections.<error>emptyList()</error>
+1 -1
View File
@@ -6,7 +6,7 @@ abstract class Item(val room: Object) {
abstract val name : String abstract val name : String
} }
val items: ArrayList<Item> = ArrayList<Item> val items: ArrayList<Item> = ArrayList<Item>()
fun test(room : Object) { fun test(room : Object) {
for(val item: Item in items) { for(val item: Item in items) {