From 657d92ba50a461c611c720be5cbb211fd3b1fa20 Mon Sep 17 00:00:00 2001 From: "Gregory.Shrago" Date: Thu, 29 Jan 2015 21:23:12 +0300 Subject: [PATCH] IDEA-135780 Language Injection via comment: does not work for concatenated strings in annotations --- .../inject/java/ConcatenationInjector.java | 13 +++-- .../java/JavaLanguageInjectionSupport.java | 50 ++++++++++--------- .../util/ContextComputationProcessor.java | 7 +-- 3 files changed, 41 insertions(+), 29 deletions(-) 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 041896a01eca..2b22a98fd2c8 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 @@ -73,12 +73,12 @@ public class ConcatenationInjector implements ConcatenationAwareInjector { PsiFile containingFile = null; for (PsiElement operand : operands) { if (PsiUtilEx.isStringOrCharacterLiteral(operand)) { + hasLiteral = true; if (containingFile == null) { containingFile = operands[0].getContainingFile(); } tempInjectedLanguage = myTemporaryPlacesRegistry.getLanguageFor((PsiLanguageInjectionHost)operand, containingFile); - hasLiteral = true; if (tempInjectedLanguage != null) break; } } @@ -134,6 +134,13 @@ public class ConcatenationInjector implements ConcatenationAwareInjector { public void processInjections() { final PsiElement firstOperand = myOperands[0]; + Ref causeRef = Ref.create(); + BaseInjection commentInjection = mySupport.findCommentInjection(firstOperand, causeRef); + if (commentInjection != null) { + processCommentInjectionInner(causeRef.get(), commentInjection); + return; + } + final PsiElement topBlock = PsiUtil.getTopLevelEnclosingCodeBlock(firstOperand, null); final LocalSearchScope searchScope = new LocalSearchScope(new PsiElement[]{topBlock instanceof PsiCodeBlock ? topBlock : firstOperand.getContainingFile()}, "", true); @@ -258,10 +265,10 @@ public class ConcatenationInjector implements ConcatenationAwareInjector { Ref causeRef = Ref.create(); BaseInjection injection = mySupport.findCommentInjection(anchor, causeRef); - return injection == null || processCommentInjectionInner(owner, causeRef.get(), injection); + return injection == null || processCommentInjectionInner(causeRef.get(), injection); } - protected boolean processCommentInjectionInner(PsiVariable owner, PsiElement comment, BaseInjection injection) { + protected boolean processCommentInjectionInner(PsiElement comment, BaseInjection injection) { processInjectionWithContext(injection, false); return false; } diff --git a/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/java/JavaLanguageInjectionSupport.java b/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/java/JavaLanguageInjectionSupport.java index c597fc840521..c8bbfbc67bde 100644 --- a/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/java/JavaLanguageInjectionSupport.java +++ b/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/java/JavaLanguageInjectionSupport.java @@ -213,7 +213,6 @@ public class JavaLanguageInjectionSupport extends AbstractLanguageInjectionSuppo final PsiModifierListOwner modifierListOwner, @NotNull PsiLanguageInjectionHost host, final String languageId) { - // todo add languageId comment return doAddLanguageAnnotation(project, modifierListOwner, host, languageId, new Processor() { @Override public boolean process(PsiLanguageInjectionHost host) { @@ -230,37 +229,42 @@ public class JavaLanguageInjectionSupport extends AbstractLanguageInjectionSuppo }); } - public static boolean doAddLanguageAnnotation(final Project project, - final PsiModifierListOwner modifierListOwner, - @NotNull PsiLanguageInjectionHost host, + public static boolean doAddLanguageAnnotation(Project project, + @Nullable final PsiModifierListOwner modifierListOwner, + @NotNull final PsiLanguageInjectionHost host, final String languageId, Processor annotationFixer) { - if (modifierListOwner.getModifierList() == null || !PsiUtil.isLanguageLevel5OrHigher(modifierListOwner)) return false; - final Configuration.AdvancedConfiguration configuration = Configuration.getProjectInstance(project).getAdvancedConfiguration(); + final boolean addAnnotation = OrderEntryFix.isAnnotationsJarInPath(ModuleUtilCore.findModuleForPsiElement(modifierListOwner)) + && PsiUtil.isLanguageLevel5OrHigher(modifierListOwner) + && modifierListOwner.getModifierList() != null; + final PsiStatement statement = PsiTreeUtil.getParentOfType(host, PsiStatement.class); + if (!addAnnotation && statement == null) return false; + + Configuration.AdvancedConfiguration configuration = Configuration.getProjectInstance(project).getAdvancedConfiguration(); if (!configuration.isSourceModificationAllowed()) { host.putUserData(InjectLanguageAction.FIX_KEY, annotationFixer); return false; } - if (!OrderEntryFix.ensureAnnotationsJarInPath(ModuleUtilCore.findModuleForPsiElement(modifierListOwner))) { - return false; - } + new WriteCommandAction(modifierListOwner.getProject(), modifierListOwner.getContainingFile()) { - protected void run(@NotNull final Result result) throws Throwable { - JVMElementFactory factory = JVMElementFactories.getFactory(modifierListOwner.getLanguage(), modifierListOwner.getProject()); - if (factory == null) { - factory = JavaPsiFacade.getElementFactory(modifierListOwner.getProject()); - } - final PsiAnnotation annotation = factory.createAnnotationFromText("@" + AnnotationUtil.LANGUAGE + "(\"" + languageId + "\")", modifierListOwner); - final PsiModifierList list = modifierListOwner.getModifierList(); - assert list != null; - final PsiAnnotation existingAnnotation = list.findAnnotation(AnnotationUtil.LANGUAGE); - if (existingAnnotation != null) { - existingAnnotation.replace(annotation); + protected void run(@NotNull Result result) throws Throwable { + PsiElementFactory javaFacade = JavaPsiFacade.getElementFactory(getProject()); + if (addAnnotation) { + JVMElementFactory factory = ObjectUtils.chooseNotNull(JVMElementFactories.getFactory(modifierListOwner.getLanguage(), getProject()), javaFacade); + PsiAnnotation annotation = factory.createAnnotationFromText("@" + AnnotationUtil.LANGUAGE + "(\"" + languageId + "\")", modifierListOwner); + PsiModifierList list = ObjectUtils.assertNotNull(modifierListOwner.getModifierList()); + final PsiAnnotation existingAnnotation = list.findAnnotation(AnnotationUtil.LANGUAGE); + if (existingAnnotation != null) { + existingAnnotation.replace(annotation); + } + else { + list.addAfter(annotation, null); + } + JavaCodeStyleManager.getInstance(getProject()).shortenClassReferences(list); } else { - list.addAfter(annotation, null); + statement.getParent().addBefore(javaFacade.createCommentFromText("//language=" + languageId, host), statement); } - JavaCodeStyleManager.getInstance(getProject()).shortenClassReferences(list); } }.execute(); return true; @@ -392,7 +396,7 @@ public class JavaLanguageInjectionSupport extends AbstractLanguageInjectionSuppo new ConcatenationInjector.InjectionProcessor(configuration, support, host) { @Override - protected boolean processCommentInjectionInner(PsiVariable owner, PsiElement comment, BaseInjection injection) { + protected boolean processCommentInjectionInner(PsiElement comment, BaseInjection injection) { ContainerUtil.addAll(annotations, comment); return true; } diff --git a/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/util/ContextComputationProcessor.java b/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/util/ContextComputationProcessor.java index 0a583d2d3b8f..33eed5e47576 100644 --- a/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/util/ContextComputationProcessor.java +++ b/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/util/ContextComputationProcessor.java @@ -19,6 +19,8 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.util.ObjectUtils; import com.intellij.util.SmartList; import org.jetbrains.annotations.NotNull; @@ -45,9 +47,8 @@ public class ContextComputationProcessor { final ArrayList result = new ArrayList(); final ContextComputationProcessor processor = new ContextComputationProcessor(operands[0].getProject()); addStringFragment(prefix, result); - for (PsiElement operand : operands) { - processor.collectOperands(operand, result, unparsable); - } + PsiElement topParent = ObjectUtils.assertNotNull(PsiTreeUtil.findCommonParent(operands)); + processor.collectOperands(getTopLevelInjectionTarget(topParent), result, unparsable); addStringFragment(suffix, result); return result; }