diff --git a/plugins/groovy/src/META-INF/plugin.xml b/plugins/groovy/src/META-INF/plugin.xml
index 580f953c9b08..18082ea1fa19 100644
--- a/plugins/groovy/src/META-INF/plugin.xml
+++ b/plugins/groovy/src/META-INF/plugin.xml
@@ -191,7 +191,11 @@
-
+
+
+
+
+
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionData.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionData.java
index 5dd733d78783..ad843193936a 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionData.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionData.java
@@ -250,7 +250,7 @@ public class GroovyCompletionData {
return context.getTextRange().getStartOffset() == 0 && !(context instanceof OuterLanguageElement);
}
- private static boolean suggestClassInterfaceEnum(PsiElement context) {
+ public static boolean suggestClassInterfaceEnum(PsiElement context) {
if (context.getParent() != null &&
(context.getParent() instanceof GrReferenceExpression) &&
context.getParent().getParent() instanceof GroovyFile) {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/template/GroovyTemplateContextType.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/template/GroovyTemplateContextType.java
index 865e5b405319..6255b8d895f3 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/template/GroovyTemplateContextType.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/template/GroovyTemplateContextType.java
@@ -15,16 +15,130 @@
*/
package org.jetbrains.plugins.groovy.template;
-import com.intellij.codeInsight.template.FileTypeBasedContextType;
+import com.intellij.codeInsight.template.EverywhereContextType;
+import com.intellij.codeInsight.template.TemplateContextType;
+import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiWhiteSpace;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.util.PsiUtilBase;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.GroovyFileType;
+import org.jetbrains.plugins.groovy.lang.completion.GroovyCompletionData;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrIfStatement;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrCodeBlock;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrCall;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
+import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
+
+import static com.intellij.patterns.PsiJavaPatterns.psiElement;
/**
* @author peter
*/
-public class GroovyTemplateContextType extends FileTypeBasedContextType{
+public abstract class GroovyTemplateContextType extends TemplateContextType {
- protected GroovyTemplateContextType() {
- super("GROOVY", "Groovy", GroovyFileType.GROOVY_FILE_TYPE);
+ protected GroovyTemplateContextType(@NotNull @NonNls String id,
+ @NotNull String presentableName,
+ @Nullable Class extends TemplateContextType> baseContextType) {
+ super(id, presentableName, baseContextType);
}
+ public boolean isInContext(@NotNull final PsiFile file, final int offset) {
+ if (PsiUtilBase.getLanguageAtOffset(file, offset).isKindOf(GroovyFileType.GROOVY_LANGUAGE)) {
+ PsiElement element = file.findElementAt(offset);
+ if (element instanceof PsiWhiteSpace) {
+ return false;
+ }
+ return element != null && isInContext(element);
+ }
+
+ return false;
+ }
+
+ protected abstract boolean isInContext(@NotNull PsiElement element);
+
+ @Override
+ public boolean isInContext(@NotNull final FileType fileType) {
+ return false;
+ }
+
+ public static class Generic extends GroovyTemplateContextType {
+ public Generic() {
+ super("GROOVY", "Groovy", EverywhereContextType.class);
+ }
+
+ @Override
+ protected boolean isInContext(@NotNull PsiElement element) {
+ return true;
+ }
+ }
+
+ public static class Statement extends GroovyTemplateContextType {
+ public Statement() {
+ super("GROOVY_STATEMENT", "Statement", Generic.class);
+ }
+
+ @Override
+ protected boolean isInContext(@NotNull PsiElement element) {
+ return isStatementContext(element);
+ }
+
+ private static boolean isStatementContext(PsiElement element) {
+ return Expression.isExpressionContext(element) && PsiUtil.isExpressionStatement(element.getParent());
+ }
+ }
+ public static class Expression extends GroovyTemplateContextType {
+ public Expression() {
+ super("GROOVY_EXPRESSION", "Expression", Generic.class);
+ }
+
+ @Override
+ protected boolean isInContext(@NotNull PsiElement element) {
+ return isExpressionContext(element);
+ }
+
+ private static boolean isExpressionContext(PsiElement element) {
+ final PsiElement parent = element.getParent();
+ if (!(parent instanceof GrReferenceExpression)) {
+ return false;
+ }
+ if (((GrReferenceExpression)parent).isQualified()) {
+ return false;
+ }
+ if (parent.getParent() instanceof GrCall) {
+ return false;
+ }
+ if (
+ psiElement().afterLeaf(
+ psiElement().inside(
+ psiElement(GrExpression.class).afterLeaf(
+ psiElement().withText("(").withParent(GrIfStatement.class))))
+ .accepts(element)) {
+ return false;
+ }
+ return true;
+ }
+ }
+ public static class Declaration extends GroovyTemplateContextType {
+ public Declaration() {
+ super("GROOVY_DECLARATION", "Declaration", Generic.class);
+ }
+
+ @Override
+ protected boolean isInContext(@NotNull PsiElement element) {
+ if (PsiTreeUtil.getParentOfType(element, GrCodeBlock.class, false, GrTypeDefinition.class) != null) {
+ return false;
+ }
+
+ return GroovyCompletionData.suggestClassInterfaceEnum(element) || GroovyCompletionData.suggestFinalDef(element);
+ }
+ }
+
+
}
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyLiveTemplatesTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyLiveTemplatesTest.java
index 85d78b5cc9b8..5987779ff7ab 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyLiveTemplatesTest.java
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyLiveTemplatesTest.java
@@ -7,6 +7,9 @@ package org.jetbrains.plugins.groovy.lang;
import com.intellij.codeInsight.lookup.Lookup;
import com.intellij.codeInsight.lookup.LookupManager;
import com.intellij.codeInsight.lookup.impl.LookupImpl;
+import com.intellij.codeInsight.template.impl.TemplateImpl;
+import com.intellij.codeInsight.template.impl.TemplateManagerImpl;
+import com.intellij.codeInsight.template.impl.TemplateSettings;
import com.intellij.codeInsight.template.impl.actions.ListTemplatesAction;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.WriteCommandAction;
@@ -14,6 +17,8 @@ import com.intellij.openapi.editor.Editor;
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
import org.jetbrains.plugins.groovy.util.TestUtils;
+import java.io.IOException;
+
/**
* @author peter
*/
@@ -39,4 +44,39 @@ public class GroovyLiveTemplatesTest extends LightCodeInsightFixtureTestCase{
}.execute();
}
+ public void testGroovyStatementContext() throws Exception {
+ final TemplateImpl template = TemplateSettings.getInstance().getTemplate("inst", "other");
+ assertFalse(isApplicable("class Foo {{ if (a inst) }}", template));
+ assertTrue(isApplicable("class Foo {{ inst }}", template));
+ assertTrue(isApplicable("inst", template));
+ assertFalse(isApplicable("class Foo {{ return (inst) }}", template));
+ }
+
+ public void testGroovyExpressionContext() throws Exception {
+ final TemplateImpl template = TemplateSettings.getInstance().getTemplate("lst", "other");
+ assertFalse(isApplicable("class Foo {{ if (a toar) }}", template));
+ assertTrue(isApplicable("class Foo {{ toar }}", template));
+ assertTrue(isApplicable("xxx", template));
+ assertTrue(isApplicable("xxx", template));
+ assertTrue(isApplicable("class Foo {{ return (toar) }}", template));
+ }
+
+ public void testGroovyDeclarationContext() throws Exception {
+ final TemplateImpl template = TemplateSettings.getInstance().getTemplate("psvm", "other");
+ assertFalse(isApplicable("class Foo {{ xxx }}", template));
+ assertFalse(isApplicable("class Foo {{ toar }}", template));
+ assertFalse(isApplicable("class Foo {{ if (a toar) }}", template));
+ assertFalse(isApplicable("class Foo {{ return (toar) }}", template));
+ assertTrue(isApplicable("class Foo { xxx }", template));
+ assertTrue(isApplicable("class Foo { xxx }", template));
+ assertFalse(isApplicable("class Foo { int xxx }", template));
+ assertTrue(isApplicable("class Foo {}\nxxx", template));
+ assertTrue(isApplicable("xxx", template));
+ }
+
+ private boolean isApplicable(String text, TemplateImpl inst) throws IOException {
+ myFixture.configureByText("a.groovy", text);
+ return TemplateManagerImpl.isApplicable(myFixture.getFile(), myFixture.getEditor().getCaretModel().getOffset(), inst);
+ }
+
}
diff --git a/resources/src/liveTemplates/iterations.xml b/resources/src/liveTemplates/iterations.xml
index 0c224edb9dba..b5098ceca9bc 100644
--- a/resources/src/liveTemplates/iterations.xml
+++ b/resources/src/liveTemplates/iterations.xml
@@ -9,8 +9,8 @@
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
+ name="inst" toReformat="true" toShortenFQNames="true" value="if ($EXPR$ instanceof $TYPE$) {
$TYPE$ $VAR1$ = ($TYPE$)$EXPR$;
$END$
}">
-
-
+
+
+ name="lst" toReformat="true" toShortenFQNames="true" value="$ARRAY$[$ARRAY$.length - 1]">
-
-
+
+
+ name="mn" toReformat="true" toShortenFQNames="true" value="$VAR$ = Math.min($VAR$, $END$);">
-
-
+
+
+ name="mx" toReformat="true" toShortenFQNames="true" value="$VAR$ = Math.max($VAR$, $END$);">
-
-
+
+
+ name="psvm" toReformat="true" toShortenFQNames="true" value="public static void main(String[] args){
$END$
}">
-
-
+
+
+ name="toar" toReformat="true" toShortenFQNames="true" value="$COLLECTION$.toArray(new $COMPONENT_TYPE$[$COLLECTION$.size()])$END$">
@@ -62,45 +62,45 @@
+ name="lazy" value="if ($VAR$ == null) {
$VAR$ = new $TYPE$($END$);
}" toReformat="true" toShortenFQNames="true">
-
-
+
+
+ name="inn" value="if ($VAR$ != null) {
$END$
}" toReformat="true" toShortenFQNames="true">
-
-
+
+
+ name="ifn" value="if ($VAR$ == null) {
$END$
}" toReformat="true" toShortenFQNames="true">
-
-
+
+
+ name="geti" toReformat="true" toShortenFQNames="true" value="public static $CLASS_NAME$ getInstance() {
return $VALUE$;
}">
-
-
+
+
diff --git a/resources/src/liveTemplates/output.xml b/resources/src/liveTemplates/output.xml
index 9878f2a5a8ef..69d0596b977f 100644
--- a/resources/src/liveTemplates/output.xml
+++ b/resources/src/liveTemplates/output.xml
@@ -1,7 +1,7 @@
+ name="serr" toReformat="true" toShortenFQNames="true" value="System.err.println("$END$");">
@@ -9,7 +9,7 @@
+ name="sout" toReformat="true" toShortenFQNames="true" value="System.out.println($END$);">
@@ -17,7 +17,7 @@
+ name="souf" toReformat="true" toShortenFQNames="true" value="System.out.printf("$END$");">
@@ -25,25 +25,25 @@
+ name="soutm" toReformat="true" toShortenFQNames="true" value="System.out.println("$CLASS_NAME$.$METHOD_NAME$");">
-
-
+
+
+ name="soutv" toReformat="true" toShortenFQNames="true" value="System.out.println("$EXPR_COPY$ = " + $EXPR$);">
-
-
+
+
diff --git a/resources/src/liveTemplates/plain.xml b/resources/src/liveTemplates/plain.xml
index 2f5833a71f24..b1025de159fb 100644
--- a/resources/src/liveTemplates/plain.xml
+++ b/resources/src/liveTemplates/plain.xml
@@ -1,50 +1,52 @@
+ name="St" toReformat="false" toShortenFQNames="true" value="String ">
-
-
+
+
+
+
+ name="psf" toReformat="false" toShortenFQNames="true" value="public static final ">
-
-
+
+
+ name="psfi" toReformat="false" toShortenFQNames="true" value="public static final int ">
-
-
+
+
+ name="psfs" toReformat="false" toShortenFQNames="true" value="public static final String ">
-
-
+
+
+ name="thr" toReformat="false" toShortenFQNames="true" value="throw new ">
-
-
+
+
diff --git a/resources/src/liveTemplates/surround.xml b/resources/src/liveTemplates/surround.xml
index 3bf9fc64bbf3..d5232bf4f6e5 100644
--- a/resources/src/liveTemplates/surround.xml
+++ b/resources/src/liveTemplates/surround.xml
@@ -11,7 +11,8 @@
-
+
+
@@ -26,7 +27,8 @@
-
+
+