diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/search/AnnotatedElementsSearcher.java b/java/java-indexing-impl/src/com/intellij/psi/impl/search/AnnotatedElementsSearcher.java index 7c2a6a886d2c..48c239cbea65 100644 --- a/java/java-indexing-impl/src/com/intellij/psi/impl/search/AnnotatedElementsSearcher.java +++ b/java/java-indexing-impl/src/com/intellij/psi/impl/search/AnnotatedElementsSearcher.java @@ -64,7 +64,7 @@ public class AnnotatedElementsSearcher implements QueryExecutor() { @Override public PsiModifierListOwner compute() { - PsiElement parent = ann.getParent(); + PsiElement parent = ann.getContext(); if (!(parent instanceof PsiModifierList)) { return null; // Can be a PsiNameValuePair, if annotation is used to annotate annotation parameters } diff --git a/java/java-tests/testSrc/com/intellij/psi/JavaStubsTest.groovy b/java/java-tests/testSrc/com/intellij/psi/JavaStubsTest.groovy index 8994e2fef1ea..feb672c3e4e8 100644 --- a/java/java-tests/testSrc/com/intellij/psi/JavaStubsTest.groovy +++ b/java/java-tests/testSrc/com/intellij/psi/JavaStubsTest.groovy @@ -18,11 +18,13 @@ package com.intellij.psi import com.intellij.codeInspection.dataFlow.ControlFlowAnalyzer import com.intellij.psi.impl.source.PsiClassImpl import com.intellij.psi.impl.source.PsiFileImpl +import com.intellij.psi.search.GlobalSearchScope +import com.intellij.psi.search.searches.AnnotatedElementsSearch import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase class JavaStubsTest extends LightCodeInsightFixtureTestCase { - public void "test resolve from annotation method default"() { + void "test resolve from annotation method default"() { def cls = myFixture.addClass(""" public @interface BrokenAnnotation { enum Foo {DEFAULT, OTHER} @@ -41,7 +43,7 @@ class JavaStubsTest extends LightCodeInsightFixtureTestCase { assert file.stub } - public void "test literal annotation value"() { + void "test literal annotation value"() { def cls = myFixture.addClass(""" class Foo { @org.jetbrains.annotations.Contract(pure=true) @@ -55,7 +57,23 @@ class JavaStubsTest extends LightCodeInsightFixtureTestCase { assert !file.contentsLoaded } - public void "test applying type annotations"() { + void "test local variable annotation doesn't cause stub-ast switch"() { + def cls = myFixture.addClass(""" + class Foo { + @Anno int foo() { + @Anno int var = 2; + } + } + @interface Anno {} + """) + + def file = cls.containingFile as PsiFileImpl + assert AnnotatedElementsSearch.searchPsiMethods(myFixture.findClass("Anno"), GlobalSearchScope.allScope(project)).size() == 1 + assert file.stub + assert !file.contentsLoaded + } + + void "test applying type annotations"() { def cls = myFixture.addClass(""" import java.lang.annotation.*; class Foo { diff --git a/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/java/ConcatenationInjector.java b/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/java/ConcatenationInjector.java index 2f5570b000db..cfc7bf05de91 100644 --- a/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/java/ConcatenationInjector.java +++ b/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/java/ConcatenationInjector.java @@ -31,7 +31,6 @@ import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.util.ArrayUtil; -import com.intellij.util.Processor; import gnu.trove.THashSet; import org.intellij.plugins.intelliLang.Configuration; import org.intellij.plugins.intelliLang.inject.InjectedLanguage; @@ -97,6 +96,7 @@ public class ConcatenationInjector implements ConcatenationAwareInjector { @Override protected boolean areThereInjectionsWithName(String methodName, boolean annoOnly) { + if (methodName == null) return false; if (getAnnotatedElementsValue().contains(methodName)) { return true; } @@ -206,7 +206,7 @@ public class ConcatenationInjector implements ConcatenationAwareInjector { if (anchor != null && !processCommentInjection(anchor)) { myShouldStop = true; } - else if (areThereInjectionsWithName(variable.getName(), false)) { + else { process(variable, null, -1); } return false; @@ -287,16 +287,12 @@ public class ConcatenationInjector implements ConcatenationAwareInjector { } private boolean processAnnotationInjections(final PsiModifierListOwner annoElement) { - final String checkName; if (annoElement instanceof PsiParameter) { final PsiElement scope = ((PsiParameter)annoElement).getDeclarationScope(); - checkName = scope instanceof PsiMethod ? ((PsiNamedElement)scope).getName() : ((PsiNamedElement)annoElement).getName(); + if (scope instanceof PsiMethod && !areThereInjectionsWithName(((PsiNamedElement)scope).getName(), true)) { + return true; + } } - else if (annoElement instanceof PsiNamedElement) { - checkName = ((PsiNamedElement)annoElement).getName(); - } - else checkName = null; - if (checkName == null || !areThereInjectionsWithName(checkName, true)) return true; final PsiAnnotation[] annotations = AnnotationUtilEx.getAnnotationFrom(annoElement, myConfiguration.getAdvancedConfiguration().getLanguageAnnotationPair(), true); if (annotations.length > 0) { diff --git a/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/java/InjectionCache.java b/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/java/InjectionCache.java index c2bc154fd0c6..d795589532f0 100644 --- a/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/java/InjectionCache.java +++ b/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/java/InjectionCache.java @@ -17,11 +17,10 @@ package org.intellij.plugins.intelliLang.inject.java; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.patterns.ElementPattern; import com.intellij.psi.*; -import com.intellij.psi.impl.java.stubs.index.JavaAnnotationIndex; import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.search.searches.AnnotatedElementsSearch; import com.intellij.psi.util.CachedValue; import com.intellij.psi.util.CachedValueProvider; import com.intellij.psi.util.CachedValuesManager; @@ -33,21 +32,20 @@ import gnu.trove.THashSet; import org.intellij.plugins.intelliLang.Configuration; import org.intellij.plugins.intelliLang.inject.config.BaseInjection; import org.intellij.plugins.intelliLang.inject.config.InjectionPlace; +import org.jetbrains.annotations.NotNull; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Map; -import java.util.Set; +import java.util.*; /** * Created by Max Medvedev on 22/03/14 */ public class InjectionCache { - private final CachedValue> myAnnoIndex; + private final CachedValue> myAnnoIndex; private final CachedValue> myXmlIndex; + private final Project myProject; public InjectionCache(final Project project, final Configuration configuration) { - + myProject = project; myXmlIndex = CachedValuesManager.getManager(project).createCachedValue(() -> { final Map, BaseInjection> map = new THashMap<>(); for (BaseInjection injection : configuration.getInjections(JavaLanguageInjectionSupport.JAVA_SUPPORT_ID)) { @@ -61,45 +59,42 @@ public class InjectionCache { }, false); myAnnoIndex = CachedValuesManager.getManager(project).createCachedValue(() -> { - final String annotationClass = configuration.getAdvancedConfiguration().getLanguageAnnotationClass(); - final Collection result = new THashSet<>(); - final ArrayList annoClasses = new ArrayList<>(3); - annoClasses.add(StringUtil.getShortName(annotationClass)); - for (int cursor = 0; cursor < annoClasses.size(); cursor++) { - final String annoClass = annoClasses.get(cursor); - for (PsiAnnotation annotation : JavaAnnotationIndex.getInstance().get(annoClass, project, GlobalSearchScope.allScope(project))) { - final PsiElement modList = annotation.getParent(); - if (!(modList instanceof PsiModifierList)) continue; - final PsiElement element = modList.getParent(); - if (element instanceof PsiParameter) { - final PsiElement scope = ((PsiParameter)element).getDeclarationScope(); - if (scope instanceof PsiNamedElement) { - ContainerUtil.addIfNotNull(result, ((PsiNamedElement)scope).getName()); - } - else { - ContainerUtil.addIfNotNull(result, ((PsiNamedElement)element).getName()); - } - } - else if (element instanceof PsiNamedElement) { - if (element instanceof PsiClass && ((PsiClass)element).isAnnotationType()) { - final String s = ((PsiClass)element).getName(); - if (!annoClasses.contains(s)) annoClasses.add(s); - } - else { - ContainerUtil.addIfNotNull(result, ((PsiNamedElement)element).getName()); - } - } - } - } + Set result = collectMethodNamesWithLanguage( + configuration.getAdvancedConfiguration().getLanguageAnnotationClass()); return new CachedValueProvider.Result<>(result, PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT, configuration); }, false); } + @NotNull + private Set collectMethodNamesWithLanguage(String annotationClassName) { + GlobalSearchScope allScope = GlobalSearchScope.allScope(myProject); + Set result = new THashSet<>(); + ArrayList annoClasses = ContainerUtil.newArrayList(JavaPsiFacade.getInstance(myProject).findClasses(annotationClassName, allScope)); + for (int cursor = 0; cursor < annoClasses.size(); cursor++) { + AnnotatedElementsSearch.searchElements(annoClasses.get(cursor), allScope, PsiClass.class, PsiParameter.class, PsiMethod.class).forEach(element -> { + if (element instanceof PsiParameter) { + final PsiElement scope = ((PsiParameter)element).getDeclarationScope(); + if (scope instanceof PsiMethod) { + ContainerUtil.addIfNotNull(result, ((PsiMethod)scope).getName()); + } + } + else if (element instanceof PsiClass && ((PsiClass)element).isAnnotationType() && !annoClasses.contains(element)) { + annoClasses.add((PsiClass)element); + } + else if (element instanceof PsiMethod) { + ContainerUtil.addIfNotNull(result, element.getName()); + } + return true; + }); + } + return result; + } + public static InjectionCache getInstance(Project project) { return ServiceManager.getService(project, InjectionCache.class); } - public Collection getAnnoIndex() { + public Set getAnnoIndex() { return myAnnoIndex.getValue(); } diff --git a/plugins/groovy/src/org/intellij/plugins/intelliLang/inject/groovy/GrConcatenationAwareInjector.java b/plugins/groovy/src/org/intellij/plugins/intelliLang/inject/groovy/GrConcatenationAwareInjector.java index c4c0238614c0..6af416ad834d 100644 --- a/plugins/groovy/src/org/intellij/plugins/intelliLang/inject/groovy/GrConcatenationAwareInjector.java +++ b/plugins/groovy/src/org/intellij/plugins/intelliLang/inject/groovy/GrConcatenationAwareInjector.java @@ -93,6 +93,7 @@ public class GrConcatenationAwareInjector implements ConcatenationAwareInjector @Override protected boolean areThereInjectionsWithName(String methodName, boolean annoOnly) { + if (methodName == null) return false; if (getAnnotatedElementsValue().contains(methodName)) { return true; } @@ -201,7 +202,7 @@ public class GrConcatenationAwareInjector implements ConcatenationAwareInjector if (!processCommentInjections(variable)) { myShouldStop = true; } - else if (areThereInjectionsWithName(variable.getName(), false)) { + else { process(variable, null, -1); } return false; @@ -266,16 +267,12 @@ public class GrConcatenationAwareInjector implements ConcatenationAwareInjector } private boolean processAnnotationInjections(final PsiModifierListOwner annoElement) { - final String checkName; if (annoElement instanceof PsiParameter) { final PsiElement scope = ((PsiParameter)annoElement).getDeclarationScope(); - checkName = scope instanceof PsiMethod ? ((PsiNamedElement)scope).getName() : ((PsiNamedElement)annoElement).getName(); + if (scope instanceof PsiMethod && !areThereInjectionsWithName(((PsiNamedElement)scope).getName(), true)) { + return true; + } } - else if (annoElement instanceof PsiNamedElement) { - checkName = ((PsiNamedElement)annoElement).getName(); - } - else checkName = null; - if (checkName == null || !areThereInjectionsWithName(checkName, true)) return true; final PsiAnnotation[] annotations = GrConcatenationInjector.getAnnotationFrom(annoElement, myConfiguration.getAdvancedConfiguration().getLanguageAnnotationPair(), true, true); if (annotations.length > 0) {