diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml
index 2c078548bed..e2992bda0ae 100644
--- a/idea/src/META-INF/plugin.xml
+++ b/idea/src/META-INF/plugin.xml
@@ -305,6 +305,7 @@
+
diff --git a/idea/src/org/jetbrains/kotlin/idea/liveTemplates/JetTemplateContextType.java b/idea/src/org/jetbrains/kotlin/idea/liveTemplates/JetTemplateContextType.java
index 30dbfea44a1..123382b4aec 100644
--- a/idea/src/org/jetbrains/kotlin/idea/liveTemplates/JetTemplateContextType.java
+++ b/idea/src/org/jetbrains/kotlin/idea/liveTemplates/JetTemplateContextType.java
@@ -43,9 +43,15 @@ public abstract class JetTemplateContextType extends TemplateContextType {
public boolean isInContext(@NotNull PsiFile file, int offset) {
if (PsiUtilBase.getLanguageAtOffset(file, offset).isKindOf(JetLanguage.INSTANCE)) {
PsiElement element = file.findElementAt(offset);
- if (element instanceof PsiWhiteSpace || element instanceof PsiComment) {
+ if (element == null) {
+ element = file.findElementAt(offset - 1);
+ }
+ if (element instanceof PsiWhiteSpace) {
return false;
}
+ else if (PsiTreeUtil.getParentOfType(element, PsiComment.class, false) != null) {
+ return isCommentInContext();
+ }
else if (PsiTreeUtil.getParentOfType(element, JetPackageDirective.class) != null
|| PsiTreeUtil.getParentOfType(element, JetImportDirective.class) != null) {
return false;
@@ -71,6 +77,10 @@ public abstract class JetTemplateContextType extends TemplateContextType {
return false;
}
+ protected boolean isCommentInContext() {
+ return false;
+ }
+
protected abstract boolean isInContext(@NotNull PsiElement element);
public static class Generic extends JetTemplateContextType {
@@ -82,6 +92,11 @@ public abstract class JetTemplateContextType extends TemplateContextType {
protected boolean isInContext(@NotNull PsiElement element) {
return true;
}
+
+ @Override
+ protected boolean isCommentInContext() {
+ return true;
+ }
}
public static class TopLevel extends JetTemplateContextType {
@@ -133,7 +148,7 @@ public abstract class JetTemplateContextType extends TemplateContextType {
}
e = e.getParent();
}
- return true;
+ return e != null;
}
}
@@ -170,4 +185,20 @@ public abstract class JetTemplateContextType extends TemplateContextType {
&& !(element.getParent() instanceof JetParameter);
}
}
+
+ public static class Comment extends JetTemplateContextType {
+ public Comment() {
+ super("KOTLIN_COMMENT", "Comment", Generic.class);
+ }
+
+ @Override
+ protected boolean isInContext(@NotNull PsiElement element) {
+ return false;
+ }
+
+ @Override
+ protected boolean isCommentInContext() {
+ return true;
+ }
+ }
}
diff --git a/idea/testData/templates/context/InDocComment.kt b/idea/testData/templates/context/InDocComment.kt
new file mode 100644
index 00000000000..ce85842dfa0
--- /dev/null
+++ b/idea/testData/templates/context/InDocComment.kt
@@ -0,0 +1,4 @@
+/**
+ * In Comment
+ */
+fun foo() {}
diff --git a/idea/testData/templates/context/TopLevel.kt b/idea/testData/templates/context/TopLevel.kt
new file mode 100644
index 00000000000..34327f6f2fc
--- /dev/null
+++ b/idea/testData/templates/context/TopLevel.kt
@@ -0,0 +1 @@
+psvm
\ No newline at end of file
diff --git a/idea/tests/org/jetbrains/kotlin/idea/codeInsight/LiveTemplatesContextTest.kt b/idea/tests/org/jetbrains/kotlin/idea/codeInsight/LiveTemplatesContextTest.kt
new file mode 100644
index 00000000000..c493fe39da4
--- /dev/null
+++ b/idea/tests/org/jetbrains/kotlin/idea/codeInsight/LiveTemplatesContextTest.kt
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2010-2015 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jetbrains.kotlin.idea.codeInsight
+
+import org.jetbrains.kotlin.idea.JetLightCodeInsightFixtureTestCase
+import org.jetbrains.kotlin.idea.PluginTestCaseBase
+
+import java.io.File
+import org.jetbrains.kotlin.idea.liveTemplates.JetTemplateContextType
+import com.intellij.codeInsight.template.TemplateContextType
+import com.intellij.testFramework.UsefulTestCase
+
+public class LiveTemplatesContextTest : JetLightCodeInsightFixtureTestCase() {
+ override fun getTestDataPath(): String =
+ File(PluginTestCaseBase.getTestDataPathBase(), "/templates/context").getPath() + File.separator
+
+ public fun testInDocComment() {
+ myFixture.configureByFile(getTestName(false) + ".kt")
+ assertInContexts(javaClass(), javaClass())
+ }
+
+ public fun testTopLevel() {
+ myFixture.configureByFile(getTestName(false) + ".kt")
+ assertInContexts(javaClass(),
+ javaClass(),
+ javaClass())
+ }
+
+ private fun assertInContexts(vararg expectedContexts: Class) {
+ val allContexts = TemplateContextType.EP_NAME.getExtensions().filter { it is JetTemplateContextType }
+ val enabledContexts = allContexts.filter { it.isInContext(myFixture.getFile(), myFixture.getCaretOffset()) }.map { it.javaClass }
+ UsefulTestCase.assertSameElements(enabledContexts, *expectedContexts)
+ }
+}