From 54c811b9c759a938cb8ce248bcd3ffd670bc25ac Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Fri, 4 Mar 2016 12:19:22 +0100 Subject: [PATCH] [java] correct language levels for array stub classes (IDEA-152384) --- .../psi/impl/PsiElementFactoryImpl.java | 57 +++++++++++-------- .../psi/impl/JavaElementFactoryTest.java | 20 +++++-- 2 files changed, 50 insertions(+), 27 deletions(-) diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiElementFactoryImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiElementFactoryImpl.java index 58169e20f193..cbcc13b8cba4 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiElementFactoryImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiElementFactoryImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2016 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,6 +21,7 @@ import com.intellij.lang.java.parser.JavaParser; import com.intellij.lang.java.parser.JavaParserUtil; import com.intellij.lexer.Lexer; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.NotNullLazyValue; import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.*; import com.intellij.psi.codeStyle.CodeStyleManager; @@ -48,10 +49,23 @@ import java.util.Map; import java.util.concurrent.ConcurrentMap; public class PsiElementFactoryImpl extends PsiJavaParserFacadeImpl implements PsiElementFactory { - private PsiClass myArrayClass; - private PsiClass myArrayClass15; - private final ConcurrentMap myCachedObjectType = - ContainerUtil.newConcurrentMap(); + private final NotNullLazyValue myArrayClass = new NotNullLazyValue() { + @NotNull + @Override + protected PsiClass compute() { + return createArrayClass("public class __Array__{\n public final int length;\n public Object clone() {}\n}", LanguageLevel.JDK_1_3); + } + }; + + private final NotNullLazyValue myArrayClass15 = new NotNullLazyValue() { + @NotNull + @Override + protected PsiClass compute() { + return createArrayClass("public class __Array__ {\n public final int length;\n public T[] clone() {}\n}", LanguageLevel.JDK_1_5); + } + }; + + private final ConcurrentMap myCachedObjectType = ContainerUtil.newConcurrentMap(); public PsiElementFactoryImpl(final PsiManagerEx manager) { super(manager); @@ -65,23 +79,17 @@ public class PsiElementFactoryImpl extends PsiJavaParserFacadeImpl implements Ps @NotNull @Override - public PsiClass getArrayClass(@NotNull final LanguageLevel languageLevel) { - if (!languageLevel.isAtLeast(LanguageLevel.JDK_1_5)) { - if (myArrayClass == null) { - @NonNls final String body = "public class __Array__{\n public final int length;\n public Object clone() {}\n}"; - myArrayClass = ((PsiExtensibleClass)createClassFromText(body, null)).getOwnInnerClasses().get(0); - ensureNonWritable(myArrayClass); - } - return myArrayClass; - } - else { - if (myArrayClass15 == null) { - @NonNls final String body = "public class __Array__{\n public final int length;\n public T[] clone() {}\n}"; - myArrayClass15 = ((PsiExtensibleClass)createClassFromText(body, null)).getOwnInnerClasses().get(0); - ensureNonWritable(myArrayClass15); - } - return myArrayClass15; - } + public PsiClass getArrayClass(@NotNull LanguageLevel languageLevel) { + return (languageLevel.isAtLeast(LanguageLevel.JDK_1_5) ? myArrayClass15 : myArrayClass).getValue(); + } + + private PsiClass createArrayClass(String text, LanguageLevel level) { + PsiClass psiClass = ((PsiExtensibleClass)createClassFromText(text, null)).getOwnInnerClasses().get(0); + ensureNonWritable(psiClass); + PsiFile file = psiClass.getContainingFile(); + ((PsiJavaFileBaseImpl)file).clearCaches(); + PsiUtil.FILE_LANGUAGE_LEVEL_KEY.set(file, level); + return psiClass; } private static void ensureNonWritable(PsiClass arrayClass) { @@ -438,6 +446,9 @@ public class PsiElementFactoryImpl extends PsiJavaParserFacadeImpl implements Ps else { text = aClass.getName(); } + if (text == null) { + throw new IncorrectOperationException("Invalid class: " + aClass); + } return new LightClassReference(myManager, text, aClass); } @@ -815,4 +826,4 @@ public class PsiElementFactoryImpl extends PsiJavaParserFacadeImpl implements Ps private boolean isIdentifier(@NotNull String name) { return PsiNameHelper.getInstance(myManager.getProject()).isIdentifier(name); } -} +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/psi/impl/JavaElementFactoryTest.java b/java/java-tests/testSrc/com/intellij/psi/impl/JavaElementFactoryTest.java index 5947eb9367d0..9a32349175ef 100644 --- a/java/java-tests/testSrc/com/intellij/psi/impl/JavaElementFactoryTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/impl/JavaElementFactoryTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * Copyright 2000-2016 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. @@ -15,11 +15,16 @@ */ package com.intellij.psi.impl; +import com.intellij.pom.java.LanguageLevel; +import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElementFactory; -import com.intellij.testFramework.LightIdeaTestCase; +import com.intellij.psi.util.PsiUtil; +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; import com.intellij.util.IncorrectOperationException; -public class JavaElementFactoryTest extends LightIdeaTestCase { +import static com.intellij.testFramework.LightCodeInsightTestCase.getJavaFacade; + +public class JavaElementFactoryTest extends LightCodeInsightFixtureTestCase { private PsiElementFactory myFactory; @Override @@ -39,4 +44,11 @@ public class JavaElementFactoryTest extends LightIdeaTestCase { } catch (IncorrectOperationException ignored) { } } -} + + public void testArrayClassLanguageLevel() { + PsiClass arrayClass3 = myFactory.getArrayClass(LanguageLevel.JDK_1_4); + PsiClass arrayClass5 = myFactory.getArrayClass(LanguageLevel.HIGHEST); + assertEquals(LanguageLevel.JDK_1_3, PsiUtil.getLanguageLevel(arrayClass3)); + assertEquals(LanguageLevel.JDK_1_5, PsiUtil.getLanguageLevel(arrayClass5)); + } +} \ No newline at end of file