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 c38cf6e026d6..70843dbd4763 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
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 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.
@@ -23,7 +23,7 @@ import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.WriteCommandAction;
-import com.intellij.openapi.module.ModuleUtil;
+import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogBuilder;
@@ -197,21 +197,26 @@ public class JavaLanguageInjectionSupport extends AbstractLanguageInjectionSuppo
else if (parent instanceof PsiVariable) {
if (doAddLanguageAnnotation(project, (PsiModifierListOwner)parent, languageId)) return true;
}
+ else if (target instanceof PsiVariable) {
+ if (doAddLanguageAnnotation(project, (PsiModifierListOwner)target, languageId)) return true;
+ }
return false;
}
- static boolean doAddLanguageAnnotation(final Project project, final PsiModifierListOwner modifierListOwner,
- final String languageId) {
+ public static boolean doAddLanguageAnnotation(final Project project, final PsiModifierListOwner modifierListOwner, final String languageId) {
if (!Configuration.getProjectInstance(project).getAdvancedConfiguration().isSourceModificationAllowed()) return false;
if (modifierListOwner.getModifierList() == null || !PsiUtil.isLanguageLevel5OrHigher(modifierListOwner)) return false;
- if (!OrderEntryFix.isAnnotationsJarInPath(ModuleUtil.findModuleForPsiElement(modifierListOwner))) {
+ if (!OrderEntryFix.isAnnotationsJarInPath(ModuleUtilCore.findModuleForPsiElement(modifierListOwner))) {
// todo add languageId comment
return false;
}
new WriteCommandAction(project, modifierListOwner.getContainingFile()) {
protected void run(final Result result) throws Throwable {
- final PsiAnnotation annotation = JavaPsiFacade.getInstance(project).getElementFactory()
- .createAnnotationFromText("@" + AnnotationUtil.LANGUAGE + "(\"" + languageId + "\")", modifierListOwner);
+ 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);
@@ -227,8 +232,10 @@ public class JavaLanguageInjectionSupport extends AbstractLanguageInjectionSuppo
return true;
}
- private static boolean doInjectInJavaMethod(final Project project, final PsiMethod psiMethod, final int parameterIndex,
- final String languageId) {
+ public static boolean doInjectInJavaMethod(@NotNull final Project project,
+ @Nullable final PsiMethod psiMethod,
+ final int parameterIndex,
+ @NotNull final String languageId) {
if (psiMethod == null) return false;
if (parameterIndex < -1) return false;
if (parameterIndex >= psiMethod.getParameterList().getParametersCount()) return false;
diff --git a/plugins/groovy/jetgroovy.iml b/plugins/groovy/jetgroovy.iml
index bb64ecbe2d34..38452af447cc 100644
--- a/plugins/groovy/jetgroovy.iml
+++ b/plugins/groovy/jetgroovy.iml
@@ -27,7 +27,7 @@
-
+
diff --git a/plugins/groovy/src/org/intellij/plugins/intelliLang/inject/groovy/GroovyLanguageInjectionSupport.java b/plugins/groovy/src/org/intellij/plugins/intelliLang/inject/groovy/GroovyLanguageInjectionSupport.java
index f19c1bf888f7..ea384086f3fb 100644
--- a/plugins/groovy/src/org/intellij/plugins/intelliLang/inject/groovy/GroovyLanguageInjectionSupport.java
+++ b/plugins/groovy/src/org/intellij/plugins/intelliLang/inject/groovy/GroovyLanguageInjectionSupport.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * Copyright 2000-2013 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.
@@ -16,13 +16,36 @@
package org.intellij.plugins.intelliLang.inject.groovy;
-import com.intellij.psi.PsiElement;
+import com.intellij.lang.Language;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Pair;
+import com.intellij.psi.*;
+import com.intellij.psi.impl.light.LightElement;
+import com.intellij.psi.tree.IElementType;
import org.intellij.plugins.intelliLang.inject.AbstractLanguageInjectionSupport;
+import org.intellij.plugins.intelliLang.inject.java.JavaLanguageInjectionSupport;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.groovy.codeInspection.utils.ControlFlowUtils;
+import org.jetbrains.plugins.groovy.lang.lexer.TokenSets;
+import org.jetbrains.plugins.groovy.lang.psi.GrControlFlowOwner;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
+import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
+import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrListOrMap;
+import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotationArrayInitializer;
+import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotationNameValuePair;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.GrReturnStatement;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.*;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrLiteral;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
+import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil;
+import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.literals.GrLiteralImpl;
import org.jetbrains.plugins.groovy.lang.psi.patterns.GroovyPatterns;
+import java.util.Map;
+
/**
* @author Gregory.Shrago
*/
@@ -47,4 +70,104 @@ public class GroovyLanguageInjectionSupport extends AbstractLanguageInjectionSup
public String getHelpId() {
return "reference.settings.language.injection.groovy";
}
+
+ @Override
+ public boolean addInjectionInPlace(Language language, PsiLanguageInjectionHost psiElement) {
+ if (!isStringLiteral(psiElement)) return false;
+
+
+ return doInject(language.getID(), psiElement);
+ }
+
+ private static boolean doInject(String languageId, PsiElement host) {
+ final PsiElement target = getTopLevelInjectionTarget(host);
+ final PsiElement parent = target.getParent();
+ final Project project = host.getProject();
+
+ if (parent instanceof GrReturnStatement) {
+ final GrControlFlowOwner owner = ControlFlowUtils.findControlFlowOwner(parent);
+ if (owner instanceof GrOpenBlock && owner.getParent() instanceof GrMethod) {
+ return JavaLanguageInjectionSupport.doInjectInJavaMethod(project, (PsiMethod)owner.getParent(), -1, languageId);
+ }
+ }
+ else if (parent instanceof GrMethod) {
+ return JavaLanguageInjectionSupport.doInjectInJavaMethod(project, (GrMethod)parent, -1, languageId);
+ }
+ else if (parent instanceof GrAnnotationNameValuePair) {
+ final PsiReference ref = parent.getReference();
+ if (ref != null) {
+ final PsiElement resolved = ref.resolve();
+ if (resolved instanceof PsiMethod) {
+ return JavaLanguageInjectionSupport.doInjectInJavaMethod(project, (PsiMethod)resolved, -1, languageId);
+ }
+ }
+ }
+ else if (parent instanceof GrArgumentList && parent.getParent() instanceof GrMethodCall) {
+ final PsiMethod method = ((GrMethodCall)parent.getParent()).resolveMethod();
+ if (method != null) {
+ final int index = findParameterIndex(target, ((GrMethodCall)parent.getParent()));
+ if (index >= 0) {
+ return JavaLanguageInjectionSupport.doInjectInJavaMethod(project, method, index, languageId);
+ }
+ }
+ }
+ else if (parent instanceof GrAssignmentExpression) {
+ final GrExpression expr = ((GrAssignmentExpression)parent).getLValue();
+ if (expr instanceof GrReferenceExpression) {
+ final PsiElement element = ((GrReferenceExpression)expr).resolve();
+ if (element != null) {
+ return doInject(languageId, element);
+ }
+ }
+ }
+ else {
+ if (parent instanceof PsiVariable) {
+ if (JavaLanguageInjectionSupport.doAddLanguageAnnotation(project, (PsiModifierListOwner)parent, languageId)) return true;
+ }
+ else if (target instanceof PsiVariable && !(target instanceof LightElement)) {
+ if (JavaLanguageInjectionSupport.doAddLanguageAnnotation(project, (PsiModifierListOwner)target, languageId)) return true;
+ }
+ }
+ return false;
+ }
+
+ private static int findParameterIndex(PsiElement arg, GrMethodCall call) {
+ final GroovyResolveResult result = call.advancedResolve();
+ assert result.getElement() instanceof PsiMethod;
+ final Map> map = GrClosureSignatureUtil
+ .mapArgumentsToParameters(result, call, false, false, call.getNamedArguments(), call.getExpressionArguments(),
+ call.getClosureArguments());
+ if (map == null) return -1;
+
+ final PsiMethod method = (PsiMethod)result.getElement();
+ final PsiParameter parameter = map.get(arg).first;
+ if (parameter == null) return -1;
+
+ return method.getParameterList().getParameterIndex(parameter);
+ }
+
+ private static boolean isStringLiteral(PsiLanguageInjectionHost element) {
+ if (element instanceof GrLiteral) {
+ final IElementType type = GrLiteralImpl.getLiteralType((GrLiteral)element);
+ return TokenSets.STRING_LITERALS.contains(type);
+ }
+ return false;
+ }
+
+ @NotNull
+ public static PsiElement getTopLevelInjectionTarget(@NotNull final PsiElement host) {
+ PsiElement target = host;
+ PsiElement parent = target.getParent();
+ for (; parent != null; target = parent, parent = target.getParent()) {
+ if (parent instanceof GrBinaryExpression) continue;
+ if (parent instanceof GrParenthesizedExpression) continue;
+ if (parent instanceof GrConditionalExpression && ((GrConditionalExpression)parent).getCondition() != target) continue;
+ if (parent instanceof GrAnnotationArrayInitializer) continue;
+ if (parent instanceof GrListOrMap) {
+ parent = parent.getParent(); continue;
+ }
+ break;
+ }
+ return target;
+ }
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/lexer/TokenSets.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/lexer/TokenSets.java
index f2dcba80117e..45c51b40dee0 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/lexer/TokenSets.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/lexer/TokenSets.java
@@ -125,14 +125,18 @@ public abstract class TokenSets {
public static final TokenSet STRING_LITERALS = TokenSet.create(
mSTRING_LITERAL,
- mREGEX_CONTENT,
- mDOLLAR_SLASH_REGEX_CONTENT,
mGSTRING_LITERAL,
- mGSTRING_CONTENT,
mGSTRING_BEGIN,
+ mGSTRING_CONTENT,
mGSTRING_END,
mREGEX_LITERAL,
- mDOLLAR_SLASH_REGEX_LITERAL
+ mREGEX_BEGIN,
+ mREGEX_CONTENT,
+ mREGEX_END,
+ mDOLLAR_SLASH_REGEX_LITERAL,
+ mDOLLAR_SLASH_REGEX_BEGIN,
+ mDOLLAR_SLASH_REGEX_CONTENT,
+ mDOLLAR_SLASH_REGEX_END
);
public static final TokenSet FOR_IN_DELIMITERS = TokenSet.create(kIN, mCOLON);