diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java index f4ad751675df..f563f316422b 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GenericsHighlightUtil.java @@ -658,7 +658,7 @@ public class GenericsHighlightUtil { return null; } - static HighlightInfo checkReferenceTypeUsedAsTypeArgument(final PsiTypeElement typeElement) { + static HighlightInfo checkReferenceTypeUsedAsTypeArgument(PsiTypeElement typeElement, LanguageLevel level) { final PsiType type = typeElement.getType(); if (type != PsiType.NULL && type instanceof PsiPrimitiveType || type instanceof PsiWildcardType && ((PsiWildcardType)type).getBound() instanceof PsiPrimitiveType) { @@ -668,9 +668,11 @@ public class GenericsHighlightUtil { .getElement(); if (element == null) return null; - String description = JavaErrorMessages.message("generics.type.argument.cannot.be.of.primitive.type"); - final HighlightInfo highlightInfo = - HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(typeElement).descriptionAndTooltip(description).create(); + if (level.isAtLeast(LanguageLevel.JDK_X)) return null; + + String text = JavaErrorMessages.message("generics.type.argument.cannot.be.of.primitive.type"); + HighlightInfo highlightInfo = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(typeElement).descriptionAndTooltip(text).create(); + PsiType toConvert = type; if (type instanceof PsiWildcardType) { toConvert = ((PsiWildcardType)type).getBound(); @@ -678,8 +680,8 @@ public class GenericsHighlightUtil { if (toConvert instanceof PsiPrimitiveType) { final PsiClassType boxedType = ((PsiPrimitiveType)toConvert).getBoxedType(typeElement); if (boxedType != null) { - QuickFixAction.registerQuickFixAction(highlightInfo, - QUICK_FIX_FACTORY.createReplacePrimitiveWithBoxedTypeAction(typeElement, toConvert.getPresentableText(), ((PsiPrimitiveType)toConvert).getBoxedTypeName())); + QuickFixAction.registerQuickFixAction(highlightInfo, QUICK_FIX_FACTORY.createReplacePrimitiveWithBoxedTypeAction( + typeElement, toConvert.getPresentableText(), ((PsiPrimitiveType)toConvert).getBoxedTypeName())); } } return highlightInfo; diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java index 7012c7603aec..917095adc2c9 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java @@ -1506,7 +1506,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh @Override public void visitTypeElement(final PsiTypeElement type) { if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkIllegalType(type)); - if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkReferenceTypeUsedAsTypeArgument(type)); + if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkReferenceTypeUsedAsTypeArgument(type, myLanguageLevel)); if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkWildcardUsage(type)); } diff --git a/java/java-psi-api/src/com/intellij/openapi/projectRoots/JavaSdkVersion.java b/java/java-psi-api/src/com/intellij/openapi/projectRoots/JavaSdkVersion.java index 9e19383fd45b..1e77a4cb936e 100644 --- a/java/java-psi-api/src/com/intellij/openapi/projectRoots/JavaSdkVersion.java +++ b/java/java-psi-api/src/com/intellij/openapi/projectRoots/JavaSdkVersion.java @@ -37,6 +37,8 @@ public enum JavaSdkVersion { JDK_1_8(LanguageLevel.JDK_1_8, "1.8"), JDK_1_9(LanguageLevel.JDK_1_9, "1.9"); + private static final JavaSdkVersion MAX_JDK = JDK_1_9; + private final LanguageLevel myMaxLanguageLevel; private final String myDescription; @@ -81,6 +83,9 @@ public enum JavaSdkVersion { if (languageLevel == LanguageLevel.JDK_1_3) { return JDK_1_3; } + if (languageLevel == LanguageLevel.JDK_X) { + return MAX_JDK; + } for (JavaSdkVersion version : values()) { if (version.getMaxLanguageLevel().isAtLeast(languageLevel)) { return version; diff --git a/java/java-psi-api/src/com/intellij/pom/java/LanguageLevel.java b/java/java-psi-api/src/com/intellij/pom/java/LanguageLevel.java index 176474cbc4d3..b0e03a7c8824 100644 --- a/java/java-psi-api/src/com/intellij/pom/java/LanguageLevel.java +++ b/java/java-psi-api/src/com/intellij/pom/java/LanguageLevel.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -20,7 +20,6 @@ import com.intellij.openapi.roots.LanguageLevelModuleExtension; import com.intellij.openapi.roots.LanguageLevelProjectExtension; import com.intellij.openapi.util.Key; import org.jetbrains.annotations.Nls; -import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -36,7 +35,8 @@ public enum LanguageLevel { JDK_1_6("Java 6", JavaCoreBundle.message("jdk.1.6.language.level.description")), JDK_1_7("Java 7", JavaCoreBundle.message("jdk.1.7.language.level.description")), JDK_1_8("Java 8", JavaCoreBundle.message("jdk.1.8.language.level.description")), - JDK_1_9("Java 9", JavaCoreBundle.message("jdk.1.9.language.level.description")); + JDK_1_9("Java 9", JavaCoreBundle.message("jdk.1.9.language.level.description")), + JDK_X("Java X", JavaCoreBundle.message("jdk.X.language.level.description")); public static final LanguageLevel HIGHEST = JDK_1_8; // TODO! when language level 9 is really supported, update this field public static final Key KEY = Key.create("LANGUAGE_LEVEL"); @@ -44,13 +44,12 @@ public enum LanguageLevel { private final String myName; private final String myPresentableText; - LanguageLevel(@NotNull @NonNls String name, @NotNull @Nls String presentableText) { + LanguageLevel(@NotNull String name, @NotNull @Nls String presentableText) { myName = name; myPresentableText = presentableText; } @NotNull - @NonNls public String getName() { return myName; } diff --git a/java/java-psi-api/src/messages/JavaCoreBundle.properties b/java/java-psi-api/src/messages/JavaCoreBundle.properties index 5ff783532c04..c64bfa9814c9 100644 --- a/java/java-psi-api/src/messages/JavaCoreBundle.properties +++ b/java/java-psi-api/src/messages/JavaCoreBundle.properties @@ -7,4 +7,6 @@ jdk.1.5.language.level.description=5.0 - 'enum' keyword, generics, autoboxing et jdk.1.6.language.level.description=6 - @Override in interfaces jdk.1.7.language.level.description=7 - Diamonds, ARM, multi-catch etc. jdk.1.8.language.level.description=8 - Lambdas, type annotations etc. -jdk.1.9.language.level.description=9 - Jigsaw project etc. +jdk.1.9.language.level.description=9 - JDK modularization etc. + +jdk.X.language.level.description=X - Experimental features diff --git a/java/java-psi-impl/src/com/intellij/lang/java/parser/JavaParserUtil.java b/java/java-psi-impl/src/com/intellij/lang/java/parser/JavaParserUtil.java index 1eb16b3f03d1..572707325034 100644 --- a/java/java-psi-impl/src/com/intellij/lang/java/parser/JavaParserUtil.java +++ b/java/java-psi-impl/src/com/intellij/lang/java/parser/JavaParserUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -21,8 +21,6 @@ import com.intellij.lang.impl.PsiBuilderAdapter; import com.intellij.lang.java.JavaLanguage; import com.intellij.lang.java.JavaParserDefinition; import com.intellij.lexer.Lexer; -import com.intellij.openapi.application.Application; -import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Key; @@ -38,7 +36,6 @@ import com.intellij.psi.impl.source.tree.TreeUtil; import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.TokenSet; import com.intellij.psi.util.PsiUtil; -import com.intellij.util.SystemProperties; import com.intellij.util.indexing.IndexingDataKeys; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -122,12 +119,6 @@ public class JavaParserUtil { public static final WhitespacesAndCommentsBinder SPECIAL_PRECEDING_COMMENT_BINDER = new PrecedingWhitespacesAndCommentsBinder(true); public static final WhitespacesAndCommentsBinder TRAILING_COMMENT_BINDER = new TrailingWhitespacesAndCommentsBinder(); - public static final boolean EXPERIMENTAL_FEATURES; - static { - Application app = ApplicationManager.getApplication(); - EXPERIMENTAL_FEATURES = SystemProperties.getBooleanProperty("idea.experimental.java.features", app != null && app.isUnitTestMode()); - } - private JavaParserUtil() { } public static void setLanguageLevel(final PsiBuilder builder, final LanguageLevel level) { diff --git a/java/java-psi-impl/src/com/intellij/lang/java/parser/ReferenceParser.java b/java/java-psi-impl/src/com/intellij/lang/java/parser/ReferenceParser.java index a2eb9047c2a8..ced52aa0c29a 100644 --- a/java/java-psi-impl/src/com/intellij/lang/java/parser/ReferenceParser.java +++ b/java/java-psi-impl/src/com/intellij/lang/java/parser/ReferenceParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -102,15 +102,20 @@ public class ReferenceParser { if (expect(builder, ElementType.PRIMITIVE_TYPE_BIT_SET)) { typeInfo.isPrimitive = true; } - else if (tokenType == JavaTokenType.IDENTIFIER) { - parseJavaCodeReference(builder, isSet(flags, EAT_LAST_DOT), true, false, false, false, isSet(flags, DIAMONDS), typeInfo); - } - else if ((isSet(flags, WILDCARD) || badWildcard) && tokenType == JavaTokenType.QUEST) { - builder.advanceLexer(); + else if ((isSet(flags, WILDCARD) || badWildcard) && (tokenType == JavaTokenType.QUEST || isKeywordAny(builder))) { + if (tokenType == JavaTokenType.QUEST) { + builder.advanceLexer(); + } + else { + dummy(builder); + } completeWildcardType(builder, isSet(flags, WILDCARD), type); typeInfo.marker = type; return typeInfo; } + else if (tokenType == JavaTokenType.IDENTIFIER) { + parseJavaCodeReference(builder, isSet(flags, EAT_LAST_DOT), true, false, false, false, isSet(flags, DIAMONDS), typeInfo); + } else if (isSet(flags, DIAMONDS) && tokenType == JavaTokenType.GT) { emptyElement(builder, JavaElementType.DIAMOND_TYPE); type.done(JavaElementType.TYPE); @@ -344,10 +349,8 @@ public class ReferenceParser { myParser.getDeclarationParser().parseAnnotations(builder); - if (EXPERIMENTAL_FEATURES && "any".equals(builder.getTokenText()) && getLanguageLevel(builder).isAtLeast(LanguageLevel.JDK_1_9)) { - PsiBuilder.Marker mark = builder.mark(); - builder.advanceLexer(); - mark.done(JavaElementType.DUMMY_ELEMENT); + if (isKeywordAny(builder)) { + dummy(builder); } final boolean wild = expect(builder, JavaTokenType.QUEST); @@ -368,8 +371,7 @@ public class ReferenceParser { } @NotNull - public PsiBuilder.Marker parseReferenceList(final PsiBuilder builder, final IElementType start, - @Nullable final IElementType type, final IElementType delimiter) { + public PsiBuilder.Marker parseReferenceList(PsiBuilder builder, IElementType start, @Nullable IElementType type, IElementType delimiter) { final PsiBuilder.Marker element = builder.mark(); if (expect(builder, start)) { @@ -392,4 +394,14 @@ public class ReferenceParser { } return element; } + + private static boolean isKeywordAny(PsiBuilder builder) { + return getLanguageLevel(builder).isAtLeast(LanguageLevel.JDK_X) && "any".equals(builder.getTokenText()); + } + + private static void dummy(PsiBuilder builder) { + PsiBuilder.Marker mark = builder.mark(); + builder.advanceLexer(); + mark.done(JavaElementType.DUMMY_ELEMENT); + } } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiTypeElementImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiTypeElementImpl.java index 1786bd719755..2adc60fbfac7 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiTypeElementImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiTypeElementImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 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. @@ -19,7 +19,6 @@ import com.intellij.lang.ASTNode; import com.intellij.psi.*; import com.intellij.psi.augment.PsiAugmentProvider; import com.intellij.psi.impl.PsiImplUtil; -import com.intellij.psi.impl.source.codeStyle.CodeEditUtil; import com.intellij.psi.impl.source.tree.CompositePsiElement; import com.intellij.psi.impl.source.tree.ElementType; import com.intellij.psi.impl.source.tree.JavaElementType; @@ -124,7 +123,8 @@ public class PsiTypeElementImpl extends CompositePsiElement implements PsiTypeEl type = PsiEllipsisType.createEllipsis(type, array); } - if (PsiUtil.isJavaToken(child, JavaTokenType.QUEST)) { + if (PsiUtil.isJavaToken(child, JavaTokenType.QUEST) || + child instanceof ASTNode && ((ASTNode)child).getElementType() == JavaElementType.DUMMY_ELEMENT && "any".equals(child.getText())) { assert type == null : this; PsiElement boundKind = PsiTreeUtil.skipSiblingsForward(child, PsiComment.class, PsiWhiteSpace.class); PsiElement boundType = PsiTreeUtil.skipSiblingsForward(boundKind, PsiComment.class, PsiWhiteSpace.class); diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting9/ValueTypes.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting9/ValueTypes.java new file mode 100644 index 000000000000..570d01af756a --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting9/ValueTypes.java @@ -0,0 +1,10 @@ +class C { } + +class Test { + void m(C c) { } + + void test() { + C c = new C(); + m(c); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/psi/parser-partial/references/AnyTypeArgs.txt b/java/java-tests/testData/psi/parser-partial/references/AnyTypeArgs.txt new file mode 100644 index 000000000000..f09448d75d08 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/references/AnyTypeArgs.txt @@ -0,0 +1,28 @@ +PsiJavaFile:AnyTypeArgs.java + PsiTypeElement:T + PsiJavaCodeReferenceElement:T + PsiIdentifier:T('T') + PsiReferenceParameterList + PsiJavaToken:LT('<') + PsiTypeElement:E_SRC + PsiJavaCodeReferenceElement:E_SRC + PsiIdentifier:E_SRC('E_SRC') + PsiReferenceParameterList + + PsiJavaToken:COMMA(',') + PsiWhiteSpace(' ') + PsiTypeElement:any + PsiElement(DUMMY_ELEMENT) + PsiIdentifier:any('any') + PsiJavaToken:COMMA(',') + PsiWhiteSpace(' ') + PsiTypeElement:E_DST + PsiJavaCodeReferenceElement:E_DST + PsiIdentifier:E_DST('E_DST') + PsiReferenceParameterList + + PsiJavaToken:COMMA(',') + PsiWhiteSpace(' ') + PsiTypeElement:? + PsiJavaToken:QUEST('?') + PsiJavaToken:GT('>') \ No newline at end of file diff --git a/java/java-tests/testData/psi/parser-partial/references/AnyType.txt b/java/java-tests/testData/psi/parser-partial/references/AnyTypeParams.txt similarity index 89% rename from java/java-tests/testData/psi/parser-partial/references/AnyType.txt rename to java/java-tests/testData/psi/parser-partial/references/AnyTypeParams.txt index e8ffbdfec6c8..33f4ecc9e871 100644 --- a/java/java-tests/testData/psi/parser-partial/references/AnyType.txt +++ b/java/java-tests/testData/psi/parser-partial/references/AnyTypeParams.txt @@ -1,4 +1,4 @@ -PsiJavaFile:AnyType.java +PsiJavaFile:AnyTypeParams.java PsiTypeParameterList PsiJavaToken:LT('<') PsiTypeParameter:T diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk9Test.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk9Test.java index 912947d67459..8a7f90174498 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk9Test.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk9Test.java @@ -46,4 +46,6 @@ public class LightAdvHighlightingJdk9Test extends LightDaemonAnalyzerTestCase { public void testSafeVarargsApplicability() { doTest(true, false); } public void testPrivateInInterfaces() { doTest(false, false); } + + public void testValueTypes() { setLanguageLevel(LanguageLevel.JDK_X); doTest(false, false); } } diff --git a/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/ReferenceParserTest.java b/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/ReferenceParserTest.java index 50b9a634cc33..7fd1e5422440 100644 --- a/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/ReferenceParserTest.java +++ b/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/ReferenceParserTest.java @@ -50,10 +50,8 @@ public class ReferenceParserTest extends JavaParsingTestCase { public void testTypeParams7() { doTypeParamsParserTest(""); } public void testTypeParams8() { doTypeParamsParserTest(""); } - public void testAnyType() { - setLanguageLevel(LanguageLevel.JDK_1_9); - doTypeParamsParserTest(""); - } + public void testAnyTypeParams() { setLanguageLevel(LanguageLevel.JDK_X); doTypeParamsParserTest(""); } + public void testAnyTypeArgs() { setLanguageLevel(LanguageLevel.JDK_X); doTypeParserTest("T"); } private void doRefParserTest(String text, boolean incomplete) { doParserTest(text, builder -> JavaParser.INSTANCE.getReferenceParser().parseJavaCodeReference(builder, incomplete, false, false, false));