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 9ed08267b807..8112653b44a9 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 @@ -2610,6 +2610,10 @@ public class HighlightUtil { @Nullable public static HighlightInfo checkMethodReferencesFeature(final PsiMethodReferenceExpression expression) { - return checkFeature(expression, Feature.METHOD_REFERENCES); + final HighlightInfo info = checkFeature(expression, Feature.METHOD_REFERENCES); + if (info != null) return info; + // todo[r.sh] stub; remove after implementing support in TypeConversionUtil + final String message = "Method references type check is not yet implemented"; + return HighlightInfo.createHighlightInfo(HighlightInfoType.WEAK_WARNING, expression, message); } } diff --git a/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceType.java b/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceType.java new file mode 100644 index 000000000000..306ea4edd58c --- /dev/null +++ b/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceType.java @@ -0,0 +1,73 @@ +/* + * Copyright 2000-2012 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. + */ +package com.intellij.psi; + +import com.intellij.psi.search.GlobalSearchScope; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; + +/** + * A type which represents a function denoted by a method reference. + */ +public class PsiMethodReferenceType extends PsiType { + private final PsiMethodReferenceExpression myReference; + + public PsiMethodReferenceType(@NotNull final PsiMethodReferenceExpression reference) { + super(PsiAnnotation.EMPTY_ARRAY); + myReference = reference; + } + + @Override + public String getPresentableText() { + return ""; + } + + @Override + public String getCanonicalText() { + return getPresentableText(); + } + + @Override + public String getInternalCanonicalText() { + return getPresentableText(); + } + + @Override + public boolean isValid() { + return myReference.isValid(); + } + + @Override + public boolean equalsToText(@NonNls final String text) { + return false; + } + + @Override + public A accept(@NotNull final PsiTypeVisitor visitor) { + return visitor.visitMethodReferenceType(this); + } + + @Override + public GlobalSearchScope getResolveScope() { + return null; + } + + @NotNull + @Override + public PsiType[] getSuperTypes() { + return PsiType.EMPTY_ARRAY; + } +} diff --git a/java/java-psi-api/src/com/intellij/psi/PsiTypeVisitor.java b/java/java-psi-api/src/com/intellij/psi/PsiTypeVisitor.java index f0e9afd057f2..4f925f6d7fb4 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiTypeVisitor.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiTypeVisitor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 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. @@ -56,4 +56,8 @@ public class PsiTypeVisitor { public A visitDiamondType(PsiDiamondType diamondType) { return visitType(diamondType); } + + public A visitMethodReferenceType(PsiMethodReferenceType methodReferenceType) { + return visitType(methodReferenceType); + } } diff --git a/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java b/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java index 39d9e684ca08..621eba1ef44d 100644 --- a/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java @@ -637,10 +637,14 @@ public class TypeConversionUtil { public static boolean isAssignable(@NotNull PsiType left, @NotNull PsiType right, boolean allowUncheckedConversion) { if (left == right || left.equals(right)) return true; + if (isNullType(right)) { return !(left instanceof PsiPrimitiveType) || isNullType(left); } + // todo[r.sh] implement + if (right instanceof PsiMethodReferenceType && left instanceof PsiClassType) return true; + if (left instanceof PsiIntersectionType) { PsiType[] conjuncts = ((PsiIntersectionType)left).getConjuncts(); for (PsiType conjunct : conjuncts) { diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java index 8bdb19b1d74c..0458abf01ab5 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodReferenceExpressionImpl.java @@ -44,8 +44,7 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase @Override public PsiType getType() { - // todo[r.sh]: implement - return null; + return new PsiMethodReferenceType(this); } @Override diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/ReplaceExpressionUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/ReplaceExpressionUtil.java index 0f89e33705df..2ce7b12f1303 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/ReplaceExpressionUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/ReplaceExpressionUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 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. @@ -157,6 +157,7 @@ public class ReplaceExpressionUtil { i == JavaElementType.ARRAY_ACCESS_EXPRESSION || i == JavaElementType.ARRAY_INITIALIZER_EXPRESSION || i == JavaElementType.JAVA_CODE_REFERENCE || + i == JavaElementType.METHOD_REF_EXPRESSION || i == JavaElementType.EMPTY_EXPRESSION) { return 14; } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/MethodReferences.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/MethodReferences.java index 150cf88144fe..da593cca9961 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/MethodReferences.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/MethodReferences.java @@ -19,8 +19,10 @@ class C { void m(); } void simplest() { } + void use(Simplest s) { } void test() { - Simplest simplest = this::simplest; + Simplest simplest = this::simplest; + use(this::simplest); } } \ 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 ac076e6a6c0f..171650d299bd 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk7Test.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk7Test.java @@ -17,6 +17,7 @@ package com.intellij.codeInsight.daemon; import com.intellij.ExtensionPoints; import com.intellij.codeInsight.daemon.impl.HighlightInfo; +import com.intellij.codeInspection.InspectionProfileEntry; import com.intellij.codeInspection.LocalInspectionTool; import com.intellij.codeInspection.compiler.JavacQuirksInspection; import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection; @@ -43,10 +44,16 @@ import java.util.List; public class LightAdvHighlightingJdk7Test extends LightDaemonAnalyzerTestCase { @NonNls static final String BASE_PATH = "/codeInsight/daemonCodeAnalyzer/advHighlighting7"; - private void doTest(boolean checkWarnings, boolean checkInfos) throws Exception { + private void doTest(boolean checkWarnings, boolean checkInfos, InspectionProfileEntry... tools) throws Exception { + for (InspectionProfileEntry tool : tools) { enableInspectionTool(tool); } doTest(BASE_PATH + "/" + getTestName(false) + ".java", checkWarnings, checkInfos); } + private void doTest(boolean checkWarnings, boolean checkWeakWarnings, boolean checkInfos, InspectionProfileEntry... tools) throws Exception { + for (InspectionProfileEntry tool : tools) { enableInspectionTool(tool); } + doTest(BASE_PATH + "/" + getTestName(false) + ".java", checkWarnings, checkWeakWarnings, checkInfos); + } + @Override protected LocalInspectionTool[] configureLocalInspectionTools() { return new LocalInspectionTool[]{ @@ -92,46 +99,14 @@ public class LightAdvHighlightingJdk7Test extends LightDaemonAnalyzerTestCase { public void testDynamicallyAddIgnoredAnnotations() throws Exception { ExtensionPoint point = Extensions.getRootArea().getExtensionPoint(ExtensionPoints.DEAD_CODE_TOOL); EntryPoint extension = new EntryPoint() { - @NotNull - @Override - public String getDisplayName() { - return "duh"; - } - - @Override - public boolean isEntryPoint(RefElement refElement, PsiElement psiElement) { - return false; - } - - @Override - public boolean isEntryPoint(PsiElement psiElement) { - return false; - } - - @Override - public boolean isSelected() { - return false; - } - - @Override - public void setSelected(boolean selected) { - - } - - @Override - public void readExternal(Element element) { - - } - - @Override - public void writeExternal(Element element) { - - } - - @Override - public String[] getIgnoreAnnotations() { - return new String[]{"MyAnno"}; - } + @NotNull @Override public String getDisplayName() { return "duh"; } + @Override public boolean isEntryPoint(RefElement refElement, PsiElement psiElement) { return false; } + @Override public boolean isEntryPoint(PsiElement psiElement) { return false; } + @Override public boolean isSelected() { return false; } + @Override public void setSelected(boolean selected) { } + @Override public void readExternal(Element element) { } + @Override public void writeExternal(Element element) { } + @Override public String[] getIgnoreAnnotations() { return new String[]{"MyAnno"}; } }; UnusedDeclarationInspection deadCodeInspection = new UnusedDeclarationInspection(); @@ -156,33 +131,19 @@ public class LightAdvHighlightingJdk7Test extends LightDaemonAnalyzerTestCase { public void testNumericLiterals() throws Exception { doTest(false, false); } public void testMultiCatch() throws Exception { doTest(false, false); } public void testTryWithResources() throws Exception { doTest(false, false); } - - public void testTryWithResourcesWarn() throws Exception { - enableInspectionTool(new DefUseInspection()); - doTest(true, false); - } - + public void testTryWithResourcesWarn() throws Exception { doTest(true, false, new DefUseInspection()); } public void testSafeVarargsApplicability() throws Exception { doTest(true, false); } public void testUncheckedGenericsArrayCreation() throws Exception { doTest(true, false); } public void testPreciseRethrow() throws Exception { doTest(false, false); } public void testImprovedCatchAnalysis() throws Exception { doTest(true, false); } public void testJavacQuirks() throws Exception { doTest(true, false); } public void testPolymorphicTypeCast() throws Exception { doTest(true, false); } - - public void testErasureClashConfusion() throws Exception { - enableInspectionTool(new UnusedDeclarationInspection()); - doTest(true, false); - } - - public void testUnused() throws Exception { - enableInspectionTool(new UnusedDeclarationInspection()); - doTest(true, false); - } - + public void testErasureClashConfusion() throws Exception { doTest(true, false, new UnusedDeclarationInspection()); } + public void testUnused() throws Exception { doTest(true, false, new UnusedDeclarationInspection()); } public void testSuperBound() throws Exception { doTest(false, false); } public void testExtendsBound() throws Exception { doTest(false, false); } public void testIDEA84533() throws Exception { doTest(false, false); } public void testClassLiteral() throws Exception { doTest(false, false); } public void testExtensionMethods() throws Exception { doTest(false, false); } - public void testMethodReferences() throws Exception { doTest(false, false); } + public void testMethodReferences() throws Exception { doTest(false, true, false); } } diff --git a/java/testFramework/src/com/intellij/codeInsight/daemon/LightDaemonAnalyzerTestCase.java b/java/testFramework/src/com/intellij/codeInsight/daemon/LightDaemonAnalyzerTestCase.java index 97c12f670b20..357134d2a19d 100644 --- a/java/testFramework/src/com/intellij/codeInsight/daemon/LightDaemonAnalyzerTestCase.java +++ b/java/testFramework/src/com/intellij/codeInsight/daemon/LightDaemonAnalyzerTestCase.java @@ -79,10 +79,19 @@ public abstract class LightDaemonAnalyzerTestCase extends LightCodeInsightTestCa doTestConfiguredFile(checkWarnings, checkInfos, filePath); } + protected void doTest(@NonNls String filePath, boolean checkWarnings, boolean checkWeakWarnings, boolean checkInfos) throws Exception { + configureByFile(filePath); + doTestConfiguredFile(checkWarnings, checkWeakWarnings, checkInfos, filePath); + } + protected void doTestConfiguredFile(boolean checkWarnings, boolean checkInfos, @Nullable String filePath) { + doTestConfiguredFile(checkWarnings, false, checkInfos, filePath); + } + + protected void doTestConfiguredFile(boolean checkWarnings, boolean checkWeakWarnings, boolean checkInfos, @Nullable String filePath) { getJavaFacade().setAssertOnFileLoadingFilter(VirtualFileFilter.NONE); - ExpectedHighlightingData data = new ExpectedHighlightingData(getEditor().getDocument(), checkWarnings, checkInfos); + ExpectedHighlightingData data = new ExpectedHighlightingData(getEditor().getDocument(), checkWarnings, checkWeakWarnings, checkInfos); checkHighlighting(data, composeLocalPath(filePath)); } diff --git a/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java b/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java index 83d230c03b29..5bca645a118c 100644 --- a/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java +++ b/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java @@ -22,12 +22,10 @@ import com.intellij.codeInsight.daemon.HighlightDisplayKey; import com.intellij.codeInsight.hint.HintManager; import com.intellij.codeInsight.hint.HintManagerImpl; import com.intellij.codeInsight.lookup.LookupManager; +import com.intellij.codeInspection.GlobalInspectionTool; import com.intellij.codeInspection.InspectionProfileEntry; import com.intellij.codeInspection.LocalInspectionTool; -import com.intellij.codeInspection.ex.InspectionProfileImpl; -import com.intellij.codeInspection.ex.InspectionTool; -import com.intellij.codeInspection.ex.LocalInspectionToolWrapper; -import com.intellij.codeInspection.ex.ToolsImpl; +import com.intellij.codeInspection.ex.*; import com.intellij.ide.highlighter.ProjectFileType; import com.intellij.ide.startup.StartupManagerEx; import com.intellij.ide.startup.impl.StartupManagerImpl; @@ -423,12 +421,19 @@ public abstract class LightPlatformTestCase extends UsefulTestCase implements Da } } - protected void enableInspectionTool(LocalInspectionTool tool){ - enableInspectionTool(new LocalInspectionToolWrapper(tool)); - } - - protected void enableInspectionTool(InspectionTool tool){ - enableInspectionTool(myAvailableInspectionTools, tool); + protected void enableInspectionTool(@NotNull InspectionProfileEntry tool) { + if (tool instanceof InspectionTool) { + enableInspectionTool(myAvailableInspectionTools, (InspectionTool)tool); + } + else if (tool instanceof LocalInspectionTool) { + enableInspectionTool(myAvailableInspectionTools, new LocalInspectionToolWrapper((LocalInspectionTool)tool)); + } + else if (tool instanceof GlobalInspectionTool) { + enableInspectionTool(myAvailableInspectionTools, new GlobalInspectionToolWrapper((GlobalInspectionTool)tool)); + } + else { + throw new IllegalArgumentException("Unexpected inspection type: " + tool); + } } private static void enableInspectionTool(final Map availableLocalTools, InspectionTool wrapper) {