2 * Copyright 2000-2016 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com.intellij.codeInsight.template
18 import com.intellij.JavaTestUtil
19 import com.intellij.codeInsight.CodeInsightSettings
20 import com.intellij.codeInsight.completion.CompletionType
21 import com.intellij.codeInsight.daemon.impl.quickfix.EmptyExpression
22 import com.intellij.codeInsight.lookup.Lookup
23 import com.intellij.codeInsight.lookup.LookupManager
24 import com.intellij.codeInsight.template.impl.*
25 import com.intellij.codeInsight.template.macro.*
26 import com.intellij.openapi.actionSystem.IdeActions
27 import com.intellij.openapi.command.WriteCommandAction
28 import com.intellij.openapi.editor.Editor
29 import com.intellij.openapi.editor.impl.DocumentImpl
30 import com.intellij.openapi.util.JDOMUtil
31 import com.intellij.openapi.util.text.StringUtil
32 import com.intellij.psi.PsiDocumentManager
33 import com.intellij.psi.codeStyle.CodeStyleSettingsManager
34 import com.intellij.psi.codeStyle.CommonCodeStyleSettings
35 import com.intellij.testFramework.LightPlatformCodeInsightTestCase
36 import com.intellij.testFramework.fixtures.CodeInsightTestUtil
37 import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
38 import com.intellij.util.containers.ContainerUtil
39 import com.intellij.util.ui.UIUtil
40 import org.jdom.Element
41 import org.jetbrains.annotations.NotNull
43 import static com.intellij.codeInsight.template.Template.Property.USE_STATIC_IMPORT_IF_POSSIBLE
44 import static com.intellij.testFramework.EdtTestUtil.runInEdtAndWait
48 @SuppressWarnings("SpellCheckingInspection")
49 class LiveTemplateTest extends LightCodeInsightFixtureTestCase {
51 protected String getBasePath() {
52 return JavaTestUtil.getRelativeJavaTestDataPath() + "/codeInsight/template/"
56 protected void setUp() {
58 TemplateManagerImpl.setTemplateTesting(getProject(), getTestRootDisposable())
62 protected void tearDown() {
63 CodeInsightSettings.instance.COMPLETION_CASE_SENSITIVE = CodeInsightSettings.FIRST_LETTER
64 CodeInsightSettings.instance.SELECT_AUTOPOPUP_SUGGESTIONS_BY_CHARS = false
66 WriteCommandAction.runWriteCommandAction project, {
73 private void doTestTemplateWithArg(@NotNull String templateName,
74 @NotNull String templateText,
75 @NotNull String fileText,
76 @NotNull String expected) throws IOException {
77 configureFromFileText("dummy.java", fileText)
78 final TemplateManager manager = TemplateManager.getInstance(getProject())
80 final Template template = manager.createTemplate(templateName, group, templateText)
81 template.addVariable("ARG", "", "", false)
82 TemplateContextType contextType = contextType(JavaCodeContextType.class)
83 ((TemplateImpl)template).getTemplateContext().setEnabled(contextType, true)
84 CodeInsightTestUtil.addTemplate(template, testRootDisposable)
86 writeCommand { manager.startTemplate(editor, (char)'\t') }
87 UIUtil.dispatchAllInvocationEvents()
88 checkResultByText(expected)
91 void testDependentSegmentsAtTheSamePosition() {
92 configureFromFileText("dummy.java", "class A { void test() { <caret> } }")
93 TemplateManager manager = TemplateManager.getInstance(getProject())
94 final Template template = manager.createTemplate("test_template", "user_group", '$A$$B$ then "$A$.$B$"')
95 template.addVariable("A", "", "", true)
96 template.addVariable("B", "", "", true)
97 startTemplate(template)
98 myFixture.type("HELLO")
100 myFixture.type("THERE")
103 checkResultByText("class A { void test() { HELLOTHERE then \"HELLO.THERE\" } }")
106 void testTemplateWithSegmentsAtTheSamePosition_1() {
107 doTestTemplateWithThreeVariables("", "", "", "class A { void test() { for(TestValue1TestValue2TestValue3) {} } }")
110 void testTemplateWithSegmentsAtTheSamePosition_2() {
111 doTestTemplateWithThreeVariables("Def1", "Def2", "DefaultValue", "class A { void test() { for(Def1Def2DefaultValue) {} } }")
114 void testTemplateWithSegmentsAtTheSamePosition_3() {
115 doTestTemplateWithThreeVariables("", "DefaultValue", "", "class A { void test() { for(TestValue1DefaultValueTestValue3) {} } }")
118 private void doTestTemplateWithThreeVariables(String firstDefaultValue, String secondDefaultValue, String thirdDefaultValue,
119 String expectedText) {
120 configureFromFileText("dummy.java", "class A { void test() { <caret> } }")
122 TemplateManager manager = TemplateManager.getInstance(getProject())
123 def templateName = "tst_template"
124 def templateGroup = "user"
125 final Template template = manager.createTemplate(templateName, templateGroup, 'for($TEST1$$TEST2$$TEST3$) {}')
126 template.addVariable("TEST1", "", StringUtil.wrapWithDoubleQuote(firstDefaultValue), true)
127 template.addVariable("TEST2", "", StringUtil.wrapWithDoubleQuote(secondDefaultValue), true)
128 template.addVariable("TEST3", "", StringUtil.wrapWithDoubleQuote(thirdDefaultValue), true)
129 startTemplate(template)
131 if (firstDefaultValue.empty) myFixture.type("TestValue1")
133 if (secondDefaultValue.empty) myFixture.type("TestValue2")
135 if (thirdDefaultValue.empty) myFixture.type("TestValue3")
138 checkResultByText(expectedText)
141 void testTemplateWithArg1() throws IOException {
142 doTestTemplateWithArg("tst", 'wrap($ARG$)', "tst arg<caret>", "wrap(arg)")
145 void testTemplateWithArg2() throws IOException {
146 doTestTemplateWithArg("tst#", 'wrap($ARG$)', "tst#arg<caret>", "wrap(arg)")
149 void testTemplateWithArg3() throws IOException {
150 doTestTemplateWithArg("tst#", 'wrap($ARG$)', "tst# arg<caret>", "tst# arg")
153 void testTemplateAtEndOfFile() {
154 configureFromFileText("empty.java", "")
155 final TemplateManager manager = TemplateManager.getInstance(getProject())
156 final Template template = manager.createTemplate("empty", "user", '$VAR$')
157 template.addVariable("VAR", "", "", false)
159 startTemplate(template)
160 checkResultByText("")
163 void testTemplateWithEnd() {
164 configureFromFileText("empty.java", "")
165 final TemplateManager manager = TemplateManager.getInstance(getProject())
166 final Template template = manager.createTemplate("empty", "user", '$VAR$$END$')
167 template.addVariable("VAR", "bar", "bar", true)
168 template.setToReformat(true)
170 startTemplate(template)
171 myFixture.type("foo")
172 checkResultByText("foo")
175 void testTemplateWithIndentedEnd() {
176 configureFromFileText("empty.java", "class C {\n" +
181 TemplateManager manager = TemplateManager.getInstance(getProject())
182 Template template = manager.createTemplate("empty", "user", 'foo();\n' +
183 'int i = 0; $END$\n' +
185 template.setToReformat(true)
186 startTemplate(template)
187 checkResultByText("class C {\n" +
190 " int i = 0; <caret>\n" +
197 void testTemplateWithEndOnEmptyLine() {
198 configureFromFileText("empty.java", "class C {\n" +
203 TemplateManager manager = TemplateManager.getInstance(getProject())
204 Template template = manager.createTemplate("empty", "user", 'foo()\n' +
207 template.setToReformat(true)
208 startTemplate(template)
209 checkResultByText("class C {\n" +
218 private void checkResultByText(String text) {
219 myFixture.checkResult(text)
222 private void configureFromFileText(String name, String text) {
223 myFixture.configureByText(name, text)
226 void testEndInTheMiddle() {
228 final TemplateManager manager = TemplateManager.getInstance(getProject())
229 final Template template = manager.createTemplate("frm", "user", "javax.swing.JFrame frame = new javax.swing.JFrame();\n" +
231 "frame.setVisible(true);\n" +
232 "frame.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);\n" +
234 template.setToShortenLongNames(false)
235 template.setToReformat(true)
236 startTemplate(template)
240 void "test honor custom completion caret placement"() {
241 myFixture.configureByText 'a.java', '''
247 final TemplateManager manager = TemplateManager.getInstance(getProject())
248 final Template template = manager.createTemplate("frm", "user", '$VAR$')
249 template.addVariable('VAR', new MacroCallNode(new CompleteMacro()), new EmptyNode(), true)
250 startTemplate(template)
251 myFixture.type('fo\n')
252 myFixture.checkResult '''
258 assert !state.finished
261 void "test cancel template when completion placed caret outside the variable"() {
262 myFixture.configureByText 'a.java', '''
268 final TemplateManager manager = TemplateManager.getInstance(getProject())
269 final Template template = manager.createTemplate("frm", "user", '$VAR$')
270 template.addVariable('VAR', new MacroCallNode(new CompleteMacro()), new EmptyNode(), true)
271 startTemplate(template)
272 myFixture.type('fo\n')
273 myFixture.checkResult '''
282 void "test not to go to next tab after insert if element is a psi package"() {
283 myFixture.configureByText 'a.java', '''
286 final TemplateManager manager = TemplateManager.getInstance(getProject())
287 final Template template = manager.createTemplate("imp", "user", 'import $MODIFIER$ java.$NAME$;')
288 template.addVariable('NAME', new MacroCallNode(new CompleteMacro(true)), new EmptyNode(), true)
289 template.addVariable('MODIFIER', new EmptyExpression(), true)
290 startTemplate(template)
291 myFixture.type('uti\n')
292 myFixture.checkResult '''
293 import java.util.<caret>;
295 assert !state.finished
298 void "test not to go to next tab after insert if element has call arguments"() {
299 myFixture.configureByText 'a.java', '''
302 List<String> getStringList(int i){
303 List<String> ints = null;
305 return new ArrayList<>(i);
309 final TemplateManager manager = TemplateManager.getInstance(getProject())
310 final Template template = manager.createTemplate("for", "user", 'for ($ELEMENT_TYPE$ $VAR$ : $ITERABLE_TYPE$) {\n' +
313 template.addVariable('ITERABLE_TYPE', new MacroCallNode(new CompleteSmartMacro()), new EmptyNode(), true)
314 template.addVariable('VAR', new TextExpression("item"), true)
315 template.addVariable('ELEMENT_TYPE', new TextExpression("String"), true)
316 template.setToReformat(true)
317 startTemplate(template)
318 myFixture.type('get\n')
319 myFixture.checkResult """
322 List<String> getStringList(int i){
323 List<String> ints = null;
324 for (String item : getStringList(<caret>)) {
327 return new ArrayList<>(i);
331 assert !state.finished
334 void "test go to next tab after insert if element does not have call arguments"() {
335 myFixture.configureByText 'a.java', '''
338 List<String> getStringList(int i){
339 List<String> ints = null;
341 return new ArrayList<>(i);
345 final TemplateManager manager = TemplateManager.getInstance(getProject())
346 final Template template = manager.createTemplate("for", "user", 'for ($ELEMENT_TYPE$ $VAR$ : $ITERABLE_TYPE$) {\n' +
349 template.addVariable('ITERABLE_TYPE', new MacroCallNode(new CompleteSmartMacro()), new EmptyNode(), true)
350 template.addVariable('VAR', new TextExpression("item"), true)
351 template.addVariable('ELEMENT_TYPE', new TextExpression("String"), true)
352 template.setToReformat(true)
353 startTemplate(template)
354 myFixture.type('in\n')
355 myFixture.checkResult """
358 List<String> getStringList(int i){
359 List<String> ints = null;
360 for (String <selection>item</selection> : ints) {
363 return new ArrayList<>(i);
367 assert !state.finished
370 void "test non-imported classes in className macro"() {
371 myFixture.addClass('package bar; public class Bar {}')
372 myFixture.configureByText 'a.java', '''
378 final TemplateManager manager = TemplateManager.getInstance(getProject())
379 final Template template = manager.createTemplate("frm", "user", '$VAR$')
380 template.addVariable('VAR', new MacroCallNode(new ClassNameCompleteMacro()), new EmptyNode(), true)
381 startTemplate(template)
382 assert !state.finished
383 assert 'Bar' in myFixture.lookupElementStrings
386 void "test variableOfType suggests inner static classes"() {
387 myFixture.addClass('public interface MyCallback {}')
388 myFixture.addClass('''
390 public static void doSomethingWithCallback(MyCallback cb) { }
393 myFixture.configureByText 'a.java', '''
395 static class Inner implements MyCallback {
403 TemplateManager manager = TemplateManager.getInstance(getProject())
404 Template template = manager.createTemplate("myCbDo", "user", 'MyUtils.doSomethingWithCallback($CB$)')
406 MacroCallNode call = new MacroCallNode(new VariableOfTypeMacro())
407 call.addParameter(new ConstantNode("MyCallback"))
408 template.addVariable('CB', call, new EmptyNode(), false)
409 startTemplate(template)
411 checkResultByText '''
413 static class Inner implements MyCallback {
415 MyUtils.doSomethingWithCallback(this)
422 private void checkResult() {
423 checkResultByFile(getTestName(false) + "-out.java")
426 private void checkResultByFile(String s) {
427 myFixture.checkResultByFile(s)
430 void testToar() throws Throwable {
432 startTemplate("toar", "other")
437 def startTemplate(String name, char expandKey) {
439 myFixture.type(expandKey)
442 def startTemplate(String name, String group) {
443 startTemplate(TemplateSettings.getInstance().getTemplate(name, group))
446 def startTemplate(Template template) {
447 TemplateManager.getInstance(getProject()).startTemplate(getEditor(), template)
448 UIUtil.dispatchAllInvocationEvents()
451 private static <T extends TemplateContextType> T contextType(Class<T> clazz) {
452 ContainerUtil.findInstance(TemplateContextType.EP_NAME.getExtensions(), clazz)
455 private void configure() {
456 myFixture.configureByFile(getTestName(false) + ".java")
459 void testIter() throws Throwable {
461 startTemplate("iter", "iterations")
462 writeCommand { state.nextTab() }
463 myFixture.finishLookup(Lookup.AUTO_INSERT_SELECT_CHAR)
467 void testPreferStartMatchesInLookups() throws Throwable {
469 startTemplate("iter", "iterations")
470 myFixture.type('ese\n') //for entrySet
471 assert myFixture.lookupElementStrings == ['barGooStringBuilderEntry', 'gooStringBuilderEntry', 'stringBuilderEntry', 'builderEntry', 'entry']
473 assert myFixture.lookupElementStrings == ['entry', 'barGooStringBuilderEntry', 'gooStringBuilderEntry', 'stringBuilderEntry', 'builderEntry']
474 assert LookupManager.getActiveLookup(editor).currentItem.lookupString == 'entry'
477 void testClassNameDotInTemplate() {
478 CodeInsightSettings.instance.COMPLETION_CASE_SENSITIVE = CodeInsightSettings.NONE
480 startTemplate("soutv", "output")
481 myFixture.type('File')
482 assert myFixture.lookupElementStrings == ['file']
485 assert !state.finished
488 void testFinishTemplateVariantWithDot() {
489 CodeInsightSettings.instance.SELECT_AUTOPOPUP_SUGGESTIONS_BY_CHARS = true
491 startTemplate("soutv", "output")
492 myFixture.type('fil')
493 assert myFixture.lookupElementStrings == ['file']
496 assert !state.finished
499 void testAllowTypingRandomExpressionsWithLookupOpen() {
501 startTemplate("iter", "iterations")
502 myFixture.type('file.')
504 assert !state.finished
507 private TemplateState getState() {
508 editor?.with { TemplateManagerImpl.getTemplateState(it) }
511 void testIter1() throws Throwable {
513 startTemplate("iter", "iterations")
514 myFixture.performEditorAction("NextTemplateVariable")
518 void "_testIterForceBraces"() {
519 CodeStyleSettingsManager.getSettings(getProject()).IF_BRACE_FORCE = CommonCodeStyleSettings.FORCE_BRACES_ALWAYS
523 startTemplate("iter", "iterations")
524 stripTrailingSpaces()
528 CodeStyleSettingsManager.getSettings(getProject()).IF_BRACE_FORCE = CommonCodeStyleSettings.DO_NOT_FORCE
532 private void stripTrailingSpaces() {
533 DocumentImpl document = (DocumentImpl)getEditor().getDocument()
534 document.setStripTrailingSpacesEnabled(true)
535 document.stripTrailingSpaces(getProject())
536 PsiDocumentManager.getInstance(getProject()).commitAllDocuments()
539 void testIterParameterizedInner() {
541 startTemplate("iter", "iterations")
542 stripTrailingSpaces()
546 void testIterParameterizedInnerInMethod() {
548 startTemplate("iter", "iterations")
549 stripTrailingSpaces()
553 void testAsListToar() {
555 startTemplate("toar", "other")
556 myFixture.type('\n\t')
560 void testVarargToar() {
562 startTemplate("toar", "other")
568 startTemplate("soutp", "output")
572 void testJavaStatementContext() {
573 final TemplateImpl template = TemplateSettings.getInstance().getTemplate("inst", "other")
574 assertFalse(isApplicable("class Foo {{ if (a inst<caret>) }}", template))
575 assertTrue(isApplicable("class Foo {{ <caret>inst }}", template))
576 assertTrue(isApplicable("class Foo {{ <caret>inst\n a=b; }}", template))
577 assertFalse(isApplicable("class Foo {{ return (<caret>inst) }}", template))
578 assertFalse(isApplicable("class Foo {{ return a <caret>inst) }}", template))
579 assertFalse(isApplicable("class Foo {{ \"<caret>\" }}", template))
580 assertTrue(isApplicable("class Foo {{ <caret>a.b(); ) }}", template))
581 assertTrue(isApplicable("class Foo {{ <caret>a(); ) }}", template))
582 assertTrue(isApplicable("class Foo {{ Runnable r = () -> { <caret>System.out.println(\"foo\"); }; ) }}", template))
583 assertTrue(isApplicable("class Foo {{ Runnable r = () -> <caret>System.out.println(\"foo\"); ) }}", template))
586 void testJavaExpressionContext() {
587 final TemplateImpl template = TemplateSettings.getInstance().getTemplate("toar", "other")
588 assertFalse(isApplicable("class Foo {{ if (a <caret>toar) }}", template))
589 assertTrue(isApplicable("class Foo {{ <caret>toar }}", template))
590 assertTrue(isApplicable("class Foo {{ return (<caret>toar) }}", template))
591 assertFalse(isApplicable("class Foo {{ return (aaa <caret>toar) }}", template))
592 assertTrue(isApplicable("class Foo {{ Runnable r = () -> { <caret>System.out.println(\"foo\"); }; ) }}", template))
593 assertTrue(isApplicable("class Foo {{ Runnable r = () -> <caret>System.out.println(\"foo\"); ) }}", template))
596 void testJavaDeclarationContext() {
597 final TemplateImpl template = TemplateSettings.getInstance().getTemplate("psvm", "other")
598 assertFalse(isApplicable("class Foo {{ <caret>xxx }}", template))
599 assertFalse(isApplicable("class Foo {{ <caret>xxx }}", template))
600 assertFalse(isApplicable("class Foo {{ if (a <caret>xxx) }}", template))
601 assertFalse(isApplicable("class Foo {{ return (<caret>xxx) }}", template))
602 assertTrue(isApplicable("class Foo { <caret>xxx }", template))
603 assertFalse(isApplicable("class Foo { int <caret>xxx }", template))
604 assertTrue(isApplicable("class Foo {} <caret>xxx", template))
606 assertTrue(isApplicable("class Foo { void foo(<caret>xxx) {} }", template))
607 assertTrue(isApplicable("class Foo { void foo(<caret>xxx String bar ) {} }", template))
608 assertTrue(isApplicable("class Foo { void foo(<caret>xxx String bar, int goo ) {} }", template))
609 assertTrue(isApplicable("class Foo { void foo(String bar, <caret>xxx int goo ) {} }", template))
610 assertTrue(isApplicable("class Foo { void foo(String bar, <caret>xxx goo ) {} }", template))
611 assertTrue(isApplicable("class Foo { <caret>xxx void foo(String bar, xxx goo ) {} }", template))
612 assertTrue(isApplicable("class Foo { void foo(<caret>String[] bar) {} }", template))
613 assertTrue(isApplicable("class Foo { <caret>xxx String[] foo(String[] bar) {} }", template))
615 assertTrue(isApplicable("class Foo { /**\nfoo **/ <caret>xxx String[] foo(String[] bar) {} }", template))
617 assertTrue(isApplicable("<caret>xxx package foo; class Foo {}", template))
620 void testOtherContext() throws IOException {
621 configureFromFileText("a.java", "class Foo { <caret>xxx }")
623 assertOneElement(TemplateManagerImpl.getApplicableContextTypes(myFixture.getFile(), getEditor().getCaretModel().getOffset())),
624 JavaCodeContextType.Declaration.class)
626 configureFromFileText("a.txt", "class Foo { <caret>xxx }")
628 assertOneElement(TemplateManagerImpl.getApplicableContextTypes(myFixture.getFile(), getEditor().getCaretModel().getOffset())),
629 EverywhereContextType.class)
632 void testJavaOtherContext() throws IOException {
633 def manager = (TemplateManagerImpl)TemplateManager.getInstance(project)
634 def stmtContext = TemplateContextType.EP_NAME.findExtension(JavaCodeContextType.Statement)
636 configureFromFileText("a.java", "class Foo {{ iter<caret> }}")
638 TemplateImpl template = TemplateSettings.instance.getTemplate("iter", "iterations")
639 assert (template in manager.findMatchingTemplates(myFixture.file, editor, Lookup.REPLACE_SELECT_CHAR, TemplateSettings.instance)?.keySet())
641 assert template.templateContext.getOwnValue(stmtContext)
642 assert !template.templateContext.getOwnValue(stmtContext.baseContextType)
643 template.templateContext.setEnabled(stmtContext, false)
644 template.templateContext.setEnabled(stmtContext.baseContextType, true)
646 assert !(template in manager.findMatchingTemplates(myFixture.file, editor, Lookup.REPLACE_SELECT_CHAR, TemplateSettings.instance)?.keySet())
648 template.templateContext.setEnabled(stmtContext, true)
649 template.templateContext.setEnabled(stmtContext.baseContextType, false)
653 void testDontSaveDefaultContexts() {
654 def defElement = JDOMUtil.loadDocument('''\
656 <option name="JAVA_STATEMENT" value="false"/>
657 <option name="JAVA_CODE" value="true"/>
658 </context>''').rootElement
659 def defContext = new TemplateContext()
660 defContext.readTemplateContext(defElement)
662 assert !defContext.isEnabled(TemplateContextType.EP_NAME.findExtension(JavaCodeContextType.Statement))
663 assert defContext.isEnabled(TemplateContextType.EP_NAME.findExtension(JavaCodeContextType.Declaration))
664 assert defContext.isEnabled(TemplateContextType.EP_NAME.findExtension(JavaCodeContextType.Generic))
666 def copy = defContext.createCopy()
668 def write = copy.writeTemplateContext(null)
669 assert write.children.size() == 2 : JDOMUtil.writeElement(write)
671 copy.setEnabled(TemplateContextType.EP_NAME.findExtension(JavaCommentContextType), false)
673 write = copy.writeTemplateContext(null)
674 assert write.children.size() == 3 : JDOMUtil.writeElement(write)
677 void "test use default context when empty"() {
678 def context = new TemplateContext()
679 context.readTemplateContext(new Element("context"))
681 def defContext = new TemplateContext()
682 def commentContext = TemplateContextType.EP_NAME.findExtension(JavaCommentContextType)
683 defContext.setEnabled(commentContext, true)
685 context.setDefaultContext(defContext)
686 assert context.isEnabled(commentContext)
687 assert !context.isEnabled(TemplateContextType.EP_NAME.findExtension(JavaCodeContextType.Generic))
690 void "test adding new context to Other"() {
691 def defElement = JDOMUtil.loadDocument('''\
693 <option name="OTHER" value="true"/>
694 </context>''').rootElement
695 def context = new TemplateContext()
696 context.readTemplateContext(defElement)
698 def javaContext = TemplateContextType.EP_NAME.findExtension(JavaCodeContextType.Generic)
699 context.setEnabled(javaContext, true)
701 def saved = context.writeTemplateContext(null)
703 context = new TemplateContext()
704 context.readTemplateContext(saved)
706 assert context.isEnabled(javaContext)
707 assert context.isEnabled(TemplateContextType.EP_NAME.findExtension(EverywhereContextType))
710 private boolean isApplicable(String text, TemplateImpl inst) throws IOException {
711 configureFromFileText("a.java", text)
712 return TemplateManagerImpl.isApplicable(myFixture.getFile(), getEditor().getCaretModel().getOffset(), inst)
715 private static writeCommand(Runnable runnable) {
716 WriteCommandAction.runWriteCommandAction(null, runnable)
719 void testSearchByDescriptionWhenTemplatesListed() {
720 myFixture.configureByText("a.java", "class A {{ <caret> }}")
722 new ListTemplatesHandler().invoke(project, editor, myFixture.file)
723 myFixture.type('array')
724 assert 'itar' in myFixture.lookupElementStrings
727 void testListTemplatesSearchesPrefixInDescription() {
728 myFixture.configureByText("a.java", "class A { main<caret> }")
730 new ListTemplatesHandler().invoke(project, editor, myFixture.file)
731 assert myFixture.lookupElementStrings == ['psvm']
734 void testListTemplatesAction() {
735 myFixture.configureByText("a.java", "class A {{ <caret> }}")
737 new ListTemplatesHandler().invoke(project, editor, myFixture.file)
738 assert myFixture.lookupElementStrings.containsAll(['iter', 'itco', 'toar'])
741 assert myFixture.lookupElementStrings[0].startsWith('it')
742 assert LookupManager.getInstance(project).activeLookup.currentItem == myFixture.getLookupElements()[0]
745 assert myFixture.lookupElementStrings[0].startsWith('ite')
746 assert LookupManager.getInstance(project).activeLookup.currentItem == myFixture.getLookupElements()[0]
747 LookupManager.getInstance(project).hideActiveLookup()
749 myFixture.type('\b\b')
750 new ListTemplatesHandler().invoke(project, editor, myFixture.file)
751 assert myFixture.lookupElementStrings.containsAll(['iter', 'itco'])
752 LookupManager.getInstance(project).hideActiveLookup()
754 myFixture.type('xxxxx')
755 new ListTemplatesHandler().invoke(project, editor, myFixture.file)
756 assert myFixture.lookupElementStrings.containsAll(['iter', 'itco', 'toar'])
757 LookupManager.getInstance(project).hideActiveLookup()
760 void testSelectionFromLookupBySpace() {
761 myFixture.configureByText("a.java", "class A {{ itc<caret> }}")
763 new ListTemplatesHandler().invoke(project, editor, myFixture.file)
765 myFixture.checkResult """\
766 import java.util.Iterator;
769 for (Iterator <selection>iterator</selection> = collection.iterator(); iterator.hasNext(); ) {
770 Object next = iterator.next();
776 void testNavigationActionsDontTerminateTemplate() throws Throwable {
777 configureFromFileText("a.txt", "")
779 final TemplateManager manager = TemplateManager.getInstance(getProject())
780 final Template template = manager.createTemplate("vn", "user", 'Hello $V1$ World $V1$\nHello $V2$ World $V2$\nHello $V3$ World $V3$')
781 template.addVariable("V1", "", "", true)
782 template.addVariable("V2", "", "", true)
783 template.addVariable("V3", "", "", true)
784 final Editor editor = getEditor()
786 startTemplate(template)
788 final TemplateState state = getState()
790 for (int i = 0; i < 3; i++) {
791 assertFalse(String.valueOf(i), state.isFinished())
793 final String docText = editor.getDocument().getText()
794 assertTrue(docText, docText.startsWith("Hello H World H\n"))
795 final int offset = editor.getCaretModel().getOffset()
797 moveCaret(offset + 1)
800 myFixture.completeBasic()
803 assertEquals(offset + 1, editor.getCaretModel().getOffset())
804 assertFalse(state.isFinished())
807 assertFalse(state.isFinished())
808 writeCommand { state.nextTab() }
810 assertTrue(state.isFinished())
811 checkResultByFile(getTestName(false) + "-out.txt")
814 private void moveCaret(final int offset) {
816 getEditor().getCaretModel().moveToOffset(offset)
820 void testUseDefaultValueForQuickResultCalculation() {
821 myFixture.configureByText 'a.txt', '<caret>'
823 final TemplateManager manager = TemplateManager.getInstance(getProject())
824 final Template template = manager.createTemplate("vn", "user", '$V1$ var = $V2$;')
825 template.addVariable("V1", "", "", true)
826 template.addVariable("V2", "", '"239"', true)
828 startTemplate(template)
830 myFixture.checkResult '<caret> var = 239;'
833 myFixture.checkResult 'O<caret> var = 239;'
836 myFixture.checkResult 'O var = <selection>239</selection>;'
839 void testTemplateExpandingWithSelection() {
840 final TemplateManager manager = TemplateManager.getInstance(getProject())
841 final Template template = manager.createTemplate("tpl", "user", 'expanded')
842 final JavaStringContextType contextType = contextType(JavaStringContextType.class)
843 ((TemplateImpl)template).getTemplateContext().setEnabled(contextType, true)
845 myFixture.configureByText("a.java", "class A { void f() { Stri<selection>ng s = \"tpl</selection><caret>\"; } }")
847 CodeInsightTestUtil.addTemplate(template, testRootDisposable)
849 myFixture.checkResult 'class A { void f() { Stri "; } }'
852 void "test expand current live template on no suggestions in lookup"() {
853 myFixture.configureByText "a.java", "class Foo {{ <caret> }}"
854 myFixture.completeBasic()
855 assert myFixture.lookup
856 myFixture.type("sout")
857 assert myFixture.lookup
858 assert myFixture.lookupElementStrings == []
860 myFixture.checkResult "class Foo {{\n System.out.println(<caret>);\n}}"
863 void "_test multi-dimensional toar"() {
864 myFixture.configureByText "a.java", '''
866 java.util.List<String[]> list;
867 String[][] s = toar<caret>
871 myFixture.checkResult '''
873 java.util.List<String[]> list;
874 String[][] s = list.toArray(new String[list.size()][])<caret>
878 void "test inner class name"() {
879 myFixture.configureByText "a.java", '''
888 assert myFixture.editor.document.text.contains("\"Inner.foo")
891 void "test do not strip type argument containing class"() {
892 myFixture.configureByText 'a.java', '''
895 List<Map.Entry<String, Integer>> foo() {
901 final TemplateManager manager = TemplateManager.getInstance(getProject())
902 final Template template = manager.createTemplate("result", "user", '$T$ result;')
903 template.addVariable('T', new MacroCallNode(new MethodReturnTypeMacro()), new EmptyNode(), false)
904 template.toReformat = true
906 startTemplate(template)
907 assert myFixture.editor.document.text.contains('List<Map.Entry<String, Integer>> result;')
910 void "test name shadowing"() {
911 myFixture.configureByText "a.java", """class LiveTemplateVarSuggestion {
912 private Object value;
913 public void setValue(Object value, Object value1){
918 assert myFixture.lookupElementStrings == ['value', 'value1']
921 void "test invoke surround template by tab"() {
922 myFixture.configureByText "a.txt", "B<caret>"
924 myFixture.checkResult("{<caret>}")
927 void "test escape string characters in soutv"() {
928 myFixture.configureByText "a.java", """
935 myFixture.type('\t"a"')
936 myFixture.checkResult """
939 System.out.println("\\"a\\" = " + "a"<caret>);
945 void "test stop at SELECTION when invoked surround template by tab"() {
946 myFixture.configureByText "a.txt", "<caret>"
948 final TemplateManager manager = TemplateManager.getInstance(getProject())
949 final Template template = manager.createTemplate("xxx", "user", 'foo $ARG$ bar $END$ goo $SELECTION$ after')
950 template.addVariable("ARG", "", "", true)
952 startTemplate(template)
953 myFixture.type('arg')
956 checkResultByText 'foo arg bar goo <caret> after'
959 void "test reuse static import"() {
960 myFixture.addClass("""package foo;
962 public static void someMethod() {}
963 public static void someMethod(int a) {}
965 myFixture.configureByText "a.java", """
966 import static foo.Bar.someMethod;
974 final TemplateManager manager = TemplateManager.getInstance(getProject())
975 final Template template = manager.createTemplate("xxx", "user", 'foo.Bar.someMethod($END$)')
976 template.setValue(USE_STATIC_IMPORT_IF_POSSIBLE, true)
978 startTemplate(template)
979 myFixture.checkResult """
980 import static foo.Bar.someMethod;
990 void "test concat macro"() {
991 final TemplateManager manager = TemplateManager.getInstance(getProject())
992 final Template template = manager.createTemplate("result", "user", '$A$ $B$ c')
993 template.addVariable('A', new EmptyNode(), true)
995 def macroCallNode = new MacroCallNode(new ConcatMacro())
996 macroCallNode.addParameter(new VariableNode('A', null))
997 macroCallNode.addParameter(new TextExpression("ID"))
998 template.addVariable('B', macroCallNode, false)
1000 myFixture.configureByText "a.txt", "<caret>"
1001 startTemplate(template)
1002 myFixture.type('tableName')
1005 myFixture.checkResult('tableName tableNameID c')
1008 void "test snakeCase should convert hyphens to underscores"() {
1009 final TemplateManager manager = TemplateManager.getInstance(getProject())
1010 final Template template = manager.createTemplate("result", "user", '$A$ $B$ c')
1011 template.addVariable('A', new EmptyNode(), true)
1013 def macroCallNode = new MacroCallNode(new SplitWordsMacro.SnakeCaseMacro())
1014 macroCallNode.addParameter(new VariableNode('A', null))
1015 template.addVariable('B', macroCallNode, false)
1017 myFixture.configureByText "a.txt", "<caret>"
1018 startTemplate(template)
1019 myFixture.type('-foo-bar_goo-')
1022 myFixture.checkResult('-foo-bar_goo- _foo_bar_goo_ c<caret>')
1025 void "test use single member static import first"() {
1026 myFixture.addClass("""package foo;
1028 public static void someMethod() {}
1029 public static void someMethod(int a) {}
1031 myFixture.configureByText "a.java", """
1039 final TemplateManager manager = TemplateManager.getInstance(getProject())
1040 final Template template = manager.createTemplate("xxx", "user", 'foo.Bar.someMethod($END$)')
1041 template.setValue(USE_STATIC_IMPORT_IF_POSSIBLE, true)
1043 startTemplate(template)
1044 myFixture.checkResult """import static foo.Bar.someMethod;
1054 void "test two static imports"() {
1055 myFixture.configureByText "a.java", """
1063 final TemplateManager manager = TemplateManager.getInstance(getProject())
1064 final Template template = manager.createTemplate("xxx", "user", 'java.lang.Math.abs(java.lang.Math.PI);')
1065 template.setValue(USE_STATIC_IMPORT_IF_POSSIBLE, true)
1067 startTemplate(template)
1068 myFixture.checkResult """\
1069 import static java.lang.Math.PI;
1070 import static java.lang.Math.abs;
1080 void "test do not replace macro value with null result"() {
1081 myFixture.configureByText "a.java", """\
1088 final TemplateManager manager = TemplateManager.getInstance(getProject())
1089 final Template template = manager.createTemplate("xxx", "user", '$VAR1$ $VAR2$ $VAR1$')
1090 template.addVariable("VAR1", "", "", true)
1091 template.addVariable("VAR2", new MacroCallNode(new FileNameMacro()), new ConstantNode("default"), true)
1092 ((TemplateImpl)template).templateContext.setEnabled(contextType(JavaCodeContextType.class), true)
1093 CodeInsightTestUtil.addTemplate(template, testRootDisposable)
1095 startTemplate(template)
1096 myFixture.checkResult """\
1099 <caret> a.java """ + """
1103 myFixture.type 'test'
1105 myFixture.checkResult """\
1108 test<caret> a.java test
1114 void "test do replace macro value with empty result"() {
1115 myFixture.configureByText "a.java", """\
1122 final TemplateManager manager = TemplateManager.getInstance(getProject())
1123 final Template template = manager.createTemplate("xxx", "user", '$VAR1$ $VAR2$')
1124 template.addVariable("VAR1", "", "", true)
1125 template.addVariable("VAR2", new MacroCallNode(new MyMirrorMacro("VAR1")), null, true)
1126 ((TemplateImpl)template).templateContext.setEnabled(contextType(JavaCodeContextType.class), true)
1127 CodeInsightTestUtil.addTemplate(template, testRootDisposable)
1129 startTemplate(template)
1130 myFixture.checkResult """\
1138 myFixture.checkResult """\
1146 myFixture.type '\b\b'
1147 myFixture.checkResult """\
1156 private static class MyMirrorMacro extends Macro {
1157 private final String myVariableName
1159 MyMirrorMacro(String variableName) {
1160 this.myVariableName = variableName
1169 String getPresentableName() {
1174 Result calculateResult(@NotNull Expression[] params, ExpressionContext context) {
1175 def state = TemplateManagerImpl.getTemplateState(context.editor)
1176 return state != null ? state.getVariableValue(myVariableName) : null
1180 Result calculateQuickResult(@NotNull Expression[] params, ExpressionContext context) {
1181 return calculateResult(params, context)
1185 void "test escape shouldn't move caret to the end marker"() {
1186 myFixture.configureByText 'a.java', """
1191 myFixture.type '\ta'
1192 myFixture.performEditorAction(IdeActions.ACTION_EDITOR_ESCAPE)
1193 myFixture.checkResult """
1195 for (int a<caret> = 0; a < array.length; a++) {
1203 void "test add new line on enter outside editing variable"() {
1204 myFixture.configureByText 'a.java', """
1209 myFixture.type 'soutv\tabc'
1210 myFixture.editor.caretModel.moveCaretRelatively(3, 0, false, false, false)
1212 myFixture.checkResult """
1214 System.out.println("abc = " + abc);
1220 void "test type tab character on tab outside editing variable"() {
1221 myFixture.configureByText 'a.java', """
1226 myFixture.type 'soutv\tabc'
1227 myFixture.editor.caretModel.moveCaretRelatively(2, 0, false, false, false)
1229 myFixture.checkResult """
1231 System.out.println("abc = " + abc); <caret>
1236 void "test delete at the last template position"() {
1237 myFixture.configureByText 'a.java', """
1242 myFixture.type 'iter\t'
1243 LightPlatformCodeInsightTestCase.delete(myFixture.editor, myFixture.project)
1244 myFixture.checkResult """
1246 for (Object o : <caret> {
1255 void "test multicaret expanding with space"() {
1256 myFixture.configureByText "a.java", """\
1265 def defaultShortcutChar = TemplateSettings.instance.defaultShortcutChar
1267 TemplateSettings.instance.defaultShortcutChar = TemplateSettings.SPACE_CHAR
1268 startTemplate("sout", TemplateSettings.SPACE_CHAR)
1271 TemplateSettings.instance.defaultShortcutChar = defaultShortcutChar
1273 myFixture.checkResult("""\
1276 System.out.println();
1277 System.out.println();
1278 System.out.println();
1284 void "test multicaret expanding with enter"() {
1285 myFixture.configureByText "a.java", """\
1294 def defaultShortcutChar = TemplateSettings.instance.defaultShortcutChar
1296 TemplateSettings.instance.defaultShortcutChar = TemplateSettings.ENTER_CHAR
1297 startTemplate("sout", TemplateSettings.ENTER_CHAR)
1300 TemplateSettings.instance.defaultShortcutChar = defaultShortcutChar
1302 myFixture.checkResult("""\
1305 System.out.println();
1306 System.out.println();
1307 System.out.println();
1313 void "test multicaret expanding with tab"() {
1314 myFixture.configureByText "a.java", """\
1323 def defaultShortcutChar = TemplateSettings.instance.defaultShortcutChar
1325 TemplateSettings.instance.defaultShortcutChar = TemplateSettings.TAB_CHAR
1326 startTemplate("sout", TemplateSettings.TAB_CHAR)
1329 TemplateSettings.instance.defaultShortcutChar = defaultShortcutChar
1332 myFixture.checkResult("""\
1335 System.out.println();
1336 System.out.println();
1337 System.out.println();
1343 void "test sout template in expression lambda"() {
1344 myFixture.configureByText 'a.java', '''class Foo {{
1345 strings.stream().forEach(o -> sout<caret>);
1348 myFixture.type('\t')
1349 myFixture.checkResult '''class Foo {{
1350 strings.stream().forEach(o -> System.out.println(<caret>));
1355 void "test finish template on moving caret by completion insert handler"() {
1356 TemplateManagerImpl templateManager = TemplateManager.getInstance(project) as TemplateManagerImpl
1357 myFixture.configureByText('a.html', '<selection><p></p></selection>')
1358 def template = TemplateSettings.instance.getTemplate("T2", "html/xml")
1359 myFixture.testAction(new InvokeTemplateAction(template, myFixture.editor, myFixture.project, ContainerUtil.newHashSet()))
1360 myFixture.complete(CompletionType.BASIC)
1361 myFixture.type("nofra")
1362 myFixture.finishLookup(Lookup.REPLACE_SELECT_CHAR)
1363 myFixture.checkResult("<noframes><caret><p></p></noframes>")
1364 assertNull(templateManager.getActiveTemplate(myFixture.editor))
1367 void "test escape with selection"() {
1368 myFixture.configureByText "a.java", """
1375 myFixture.type('\tfoo')
1376 myFixture.editor.selectionModel.setSelection(myFixture.caretOffset - 3, myFixture.caretOffset)
1377 assert myFixture.editor.selectionModel.hasSelection()
1379 myFixture.performEditorAction(IdeActions.ACTION_EDITOR_ESCAPE)
1380 assert !myFixture.editor.selectionModel.hasSelection()
1381 assert TemplateManager.getInstance(project).getActiveTemplate(myFixture.editor)
1383 myFixture.performEditorAction(IdeActions.ACTION_EDITOR_ESCAPE)
1384 assert !TemplateManager.getInstance(project).getActiveTemplate(myFixture.editor)
1386 myFixture.checkResult """
1389 System.out.println("foo = " + foo<caret>);
1395 void "test escape with lookup"() {
1396 myFixture.configureByText "a.java", """
1404 myFixture.type('\t')
1405 assert myFixture.lookup
1407 myFixture.performEditorAction(IdeActions.ACTION_EDITOR_ESCAPE)
1408 assert !myFixture.lookup
1409 assert TemplateManager.getInstance(project).getActiveTemplate(myFixture.editor)
1411 myFixture.performEditorAction(IdeActions.ACTION_EDITOR_ESCAPE)
1412 assert !TemplateManager.getInstance(project).getActiveTemplate(myFixture.editor)
1414 myFixture.checkResult """
1418 System.out.println("foo_1 = " + foo_1);
1424 void "test escape with lookup and selection"() {
1425 myFixture.configureByText "a.java", """
1433 myFixture.type('\tfoo')
1434 myFixture.editor.selectionModel.setSelection(myFixture.caretOffset - 3, myFixture.caretOffset)
1435 myFixture.completeBasic()
1436 assert myFixture.editor.selectionModel.hasSelection()
1437 assert myFixture.lookup
1439 myFixture.performEditorAction(IdeActions.ACTION_EDITOR_ESCAPE)
1440 assert !myFixture.editor.selectionModel.hasSelection()
1441 assert !myFixture.lookup
1442 assert TemplateManager.getInstance(project).getActiveTemplate(myFixture.editor)
1444 myFixture.performEditorAction(IdeActions.ACTION_EDITOR_ESCAPE)
1445 assert !TemplateManager.getInstance(project).getActiveTemplate(myFixture.editor)
1447 myFixture.checkResult """
1451 System.out.println("foo = " + foo<caret>);
1457 void "test escape with empty lookup"() {
1458 myFixture.configureByText "a.java", """
1466 myFixture.type('\tfoobar')
1467 assert myFixture.lookup
1468 assert !myFixture.lookup.currentItem
1470 myFixture.performEditorAction(IdeActions.ACTION_EDITOR_ESCAPE)
1471 assert !myFixture.lookup
1472 assert !TemplateManager.getInstance(project).getActiveTemplate(myFixture.editor)
1474 myFixture.checkResult """
1478 System.out.println("foobar = " + foobar);
1484 void "test iterate over list with wildcard component type"() {
1485 myFixture.configureByText 'a.java', '''class C {{
1486 java.util.List<? extends Integer> list;
1489 myFixture.type('itli\t')
1490 myFixture.checkResult '''class C {{
1491 java.util.List<? extends Integer> list;
1492 for (int i = 0; i < list.size(); i++) {
1493 Integer integer = list.get(i);
1499 void "test home end go outside template fragments if already on their bounds"() {
1500 myFixture.configureByText 'a.txt', ' <caret> g'
1502 TemplateManager manager = TemplateManager.getInstance(getProject())
1503 Template template = manager.createTemplate("empty", "user", '$VAR$')
1504 template.addVariable("VAR", "", '"foo"', true)
1505 manager.startTemplate(myFixture.editor, template)
1507 myFixture.checkResult ' <selection>foo<caret></selection> g'
1509 myFixture.performEditorAction(IdeActions.ACTION_EDITOR_MOVE_LINE_START)
1510 myFixture.checkResult ' <caret>foo g'
1512 myFixture.performEditorAction(IdeActions.ACTION_EDITOR_MOVE_LINE_START)
1513 myFixture.checkResult '<caret> foo g'
1515 myFixture.performEditorAction(IdeActions.ACTION_EDITOR_MOVE_CARET_RIGHT)
1516 myFixture.performEditorAction(IdeActions.ACTION_EDITOR_MOVE_LINE_END)
1517 myFixture.checkResult ' foo<caret> g'
1519 myFixture.performEditorAction(IdeActions.ACTION_EDITOR_MOVE_LINE_END)
1520 myFixture.checkResult ' foo g<caret>'