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) + } +}