diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java
index 496dc667a19b..f5d552fc9ba6 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java
@@ -17,6 +17,7 @@ package com.intellij.codeInsight.daemon.impl.analysis;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
+import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.codeInsight.ExceptionUtil;
import com.intellij.codeInsight.daemon.JavaErrorMessages;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
@@ -337,16 +338,36 @@ public class HighlightUtil {
@Nullable
static HighlightInfo checkInconvertibleTypeCast(PsiTypeCastExpression expression) {
+ PsiTypeElement castTypeElement = expression.getCastType();
+ if (castTypeElement == null) return null;
+ PsiType castType = castTypeElement.getType();
+
PsiExpression operand = expression.getOperand();
- PsiType castType = expression.getCastType().getType();
- PsiType operandType = operand == null ? null : operand.getType();
+ if (operand == null || isPolymorphicCall(operand)) return null;
+ PsiType operandType = operand.getType();
+
if (operandType != null && !TypeConversionUtil.areTypesConvertible(operandType, castType)) {
String message = JavaErrorMessages.message("inconvertible.type.cast", formatType(operandType), formatType(castType));
return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, expression, message);
}
+
return null;
}
+ /**
+ * Signature polymorphism
+ */
+ private static boolean isPolymorphicCall(final PsiExpression expression) {
+ if (PsiUtil.isLanguageLevel7OrHigher(expression) &&
+ expression instanceof PsiMethodCallExpression) {
+ final PsiElement method = ((PsiMethodCallExpression)expression).getMethodExpression().resolve();
+ if (method instanceof PsiMethod &&
+ AnnotationUtil.isAnnotated((PsiMethod)method, CommonClassNames.JAVA_LANG_INVOKE_MH_POLYMORPHIC, false, true)) {
+ return true;
+ }
+ }
+ return false;
+ }
@Nullable
static HighlightInfo checkVariableExpected(PsiExpression expression) {
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/PolymorphicTypeCast.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/PolymorphicTypeCast.java
new file mode 100644
index 000000000000..5ca925c9cee8
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/PolymorphicTypeCast.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2000-2011 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+
+class C {
+ // from http://download.java.net/jdk7/docs/api/java/lang/invoke/MethodHandle.html, "Usage examples"
+ void m() throws Throwable {
+ Object x, y; String s; int i;
+ MethodType mt; MethodHandle mh;
+ MethodHandles.Lookup lookup = MethodHandles.lookup();
+
+// mt is (char,char)String
+ mt = MethodType.methodType(String.class, char.class, char.class);
+ mh = lookup.findVirtual(String.class, "replace", mt);
+ s = (String) mh.invokeExact("daddy",'d','n');
+
+// invokeExact(Ljava/lang/String;CC)Ljava/lang/String;
+ assert(s.equals("nanny"));
+
+// weakly typed invocation (using MHs.invoke)
+ s = (String) mh.invokeWithArguments("sappy", 'p', 'v');
+ assert(s.equals("savvy"));
+
+// mt is (Object[])List
+ mt = MethodType.methodType(java.util.List.class, Object[].class);
+ mh = lookup.findStatic(java.util.Arrays.class, "asList", mt);
+ assert(mh.isVarargsCollector());
+ x = mh.invokeGeneric("one", "two");
+
+// invokeGeneric(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;
+ assert(x.equals(java.util.Arrays.asList("one","two")));
+
+// mt is (Object,Object,Object)Object
+ mt = MethodType.genericMethodType(3);
+ mh = mh.asType(mt);
+ x = mh.invokeExact((Object)1, (Object)2, (Object)3);
+
+// invokeExact(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
+ assert(x.equals(java.util.Arrays.asList(1,2,3)));
+
+// mt is int()
+ mt = MethodType.methodType(int.class);
+ mh = lookup.findVirtual(java.util.List.class, "size", mt);
+ i = (int) mh.invokeExact(java.util.Arrays.asList(1,2,3));
+
+// invokeExact(Ljava/util/List;)I
+ assert(i == 3);
+ mt = MethodType.methodType(void.class, String.class);
+ mh = lookup.findVirtual(java.io.PrintStream.class, "println", mt);
+ mh.invokeExact(System.out, "Hello, world.");
+// invokeExact(Ljava/io/PrintStream;Ljava/lang/String;)V
+ }
+
+ void unsupported() {
+ Object o = 42;
+ int i = (int) o;
+ System.out.println(i);
+ m((int) o);
+ if (o instanceof int) {
+ i = (Integer) o;
+ System.out.println(i);
+ }
+ }
+
+ void m(int i) { }
+}
\ No newline at end of file
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk7Test.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk7Test.java
index 6cead9ffd6f5..40f5519e84c1 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk7Test.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk7Test.java
@@ -260,4 +260,9 @@ public class LightAdvHighlightingJdk7Test extends LightDaemonAnalyzerTestCase {
public void testJavacQuirks() throws Exception {
doTest(true, false);
}
+
+ public void testPolymorphicTypeCast() throws Exception {
+ Object o = null;
+ doTest(false, false);
+ }
}
diff --git a/java/mockJDK-1.7/jre/lib/rt.jar b/java/mockJDK-1.7/jre/lib/rt.jar
index 4bc199ad9ad4..404bf3f98567 100644
Binary files a/java/mockJDK-1.7/jre/lib/rt.jar and b/java/mockJDK-1.7/jre/lib/rt.jar differ
diff --git a/java/openapi/src/com/intellij/psi/CommonClassNames.java b/java/openapi/src/com/intellij/psi/CommonClassNames.java
index 664976bb0cb0..bc799ed8690e 100644
--- a/java/openapi/src/com/intellij/psi/CommonClassNames.java
+++ b/java/openapi/src/com/intellij/psi/CommonClassNames.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2011 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -80,4 +80,6 @@ public interface CommonClassNames {
@NonNls String JAVA_UTIL_CONCURRENT_FUTURE = "java.util.concurrent.Future";
@NonNls String JAVA_UTIL_ARRAY_LIST = "java.util.ArrayList";
+
+ @NonNls String JAVA_LANG_INVOKE_MH_POLYMORPHIC = "java.lang.invoke.MethodHandle.PolymorphicSignature";
}