From cfc55bcb41bb04f51485a1c75b0f7218e074c875 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 7 Aug 2013 15:07:21 +0200 Subject: [PATCH] java: single underscore variables highlighting for Java 8 --- .../daemon/impl/analysis/HighlightUtil.java | 16 ++++++++++++++++ .../impl/analysis/HighlightVisitorImpl.java | 11 ++++++++--- .../src/messages/JavaErrorMessages.properties | 3 +++ .../lambda/highlighting/Underscores.java | 16 ++++++++++++++++ .../daemon/lambda/LambdaHighlightingTest.java | 9 +++++---- 5 files changed, 48 insertions(+), 7 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/Underscores.java 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 6c94896919a7..3181bed81402 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 @@ -622,6 +622,22 @@ public class HighlightUtil extends HighlightUtilBase { return null; } + @Nullable + public static HighlightInfo checkUnderscore(@NotNull PsiIdentifier identifier, @NotNull PsiVariable variable) { + if ("_".equals(variable.getName()) && PsiUtil.isLanguageLevel8OrHigher(variable)) { + if (variable instanceof PsiParameter && ((PsiParameter)variable).getDeclarationScope() instanceof PsiLambdaExpression) { + String message = JavaErrorMessages.message("underscore.lambda.identifier"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(identifier).descriptionAndTooltip(message).create(); + } + else { + String message = JavaErrorMessages.message("underscore.identifier"); + return HighlightInfo.newHighlightInfo(HighlightInfoType.WARNING).range(identifier).descriptionAndTooltip(message).create(); + } + } + + return null; + } + @NotNull public static String formatClass(@NotNull PsiClass aClass) { return formatClass(aClass, true); diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java index 8205c8ea9705..4b8075da2503 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java @@ -515,18 +515,19 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh @Override public void visitForeachStatement(final PsiForeachStatement statement) { - myHolder.add(HighlightUtil.checkForEachFeature(statement, myLanguageLevel,myFile)); + myHolder.add(HighlightUtil.checkForEachFeature(statement, myLanguageLevel, myFile)); } @Override public void visitImportStaticStatement(final PsiImportStaticStatement statement) { - myHolder.add(HighlightUtil.checkStaticImportFeature(statement, myLanguageLevel,myFile)); + myHolder.add(HighlightUtil.checkStaticImportFeature(statement, myLanguageLevel, myFile)); } @Override public void visitIdentifier(final PsiIdentifier identifier) { + TextAttributesScheme colorsScheme = myHolder.getColorsScheme(); + PsiElement parent = identifier.getParent(); - final TextAttributesScheme colorsScheme = myHolder.getColorsScheme(); if (parent instanceof PsiVariable) { PsiVariable variable = (PsiVariable)parent; myHolder.add(HighlightUtil.checkVariableAlreadyDefined(variable)); @@ -535,6 +536,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh final PsiElement child = variable.getLastChild(); if (child instanceof PsiErrorElement && child.getPrevSibling() == identifier) return; } + boolean isMethodParameter = variable instanceof PsiParameter && ((PsiParameter)variable).getDeclarationScope() instanceof PsiMethod; if (!isMethodParameter) { // method params are highlighted in visitMethod since we should make sure the method body was visited before if (HighlightControlFlowUtil.isReassigned(variable, myFinalVarProblems)) { @@ -547,6 +549,8 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh else { myReassignedParameters.put((PsiParameter)variable, 1); // mark param as present in current file } + + myHolder.add(HighlightUtil.checkUnderscore(identifier, variable)); } else if (parent instanceof PsiClass) { PsiClass aClass = (PsiClass)parent; @@ -569,6 +573,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh else { visitParentReference(parent); } + super.visitIdentifier(identifier); } diff --git a/java/java-psi-impl/src/messages/JavaErrorMessages.properties b/java/java-psi-impl/src/messages/JavaErrorMessages.properties index e108e585a02f..08aa5781f9c6 100644 --- a/java/java-psi-impl/src/messages/JavaErrorMessages.properties +++ b/java/java-psi-impl/src/messages/JavaErrorMessages.properties @@ -363,6 +363,9 @@ override.not.allowed.in.interfaces=@Override is not allowed when implementing in wildcard.not.expected=Unexpected wildcard bound.not.expected=Unexpected bound +underscore.identifier=Use of '_' as an identifier might not be supported in releases after Java 8 +underscore.lambda.identifier=Use of '_' as a lambda parameter name is not allowed + feature.generics=Generics feature.annotations=Annotations feature.static.imports=Static imports diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/Underscores.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/Underscores.java new file mode 100644 index 000000000000..2d89ec317ed9 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/Underscores.java @@ -0,0 +1,16 @@ +class C { + void test() { + { + I _ = new I() { public void f(int i) { } }; + accept(_); + } + + { + accept(_ -> System.out.println(_)); + accept((int _) -> System.out.println(_)); + } + } + + interface I { void f(int i); } + void accept(I i) { i.f(42); } +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java index 10b35d3d6c56..6a30811c7fd3 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java @@ -86,10 +86,11 @@ public class LambdaHighlightingTest extends LightDaemonAnalyzerTestCase { public void testVoidCompatibility() { doTest(); } public void testConditionalInferenceFromOppositePart() { doTest(); } public void testDeclaredTypeParameterBoundsAndUnboundedWildcard() { doTest(); } - public void testConflictResolution() throws Exception {doTest();} - public void testIDEA108195() throws Exception {doTest();} - public void testDiamondInference() throws Exception { doTest();} - public void testFunctionalInterfaceCheck() throws Exception { doTest();} + public void testConflictResolution() { doTest(); } + public void testIDEA108195() { doTest(); } + public void testDiamondInference() { doTest();} + public void testFunctionalInterfaceCheck() { doTest();} + public void testUnderscores() { doTest(true);} private void doTest() { doTest(false);