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 = new Element("context")
669 copy.writeTemplateContext(write)
670 assert write.children.size() == 2 : JDOMUtil.writeElement(write)
672 copy.setEnabled(TemplateContextType.EP_NAME.findExtension(JavaCommentContextType), false)
674 write = new Element("context")
675 copy.writeTemplateContext(write)
676 assert write.children.size() == 3 : JDOMUtil.writeElement(write)
679 void "test use default context when empty"() {
680 def context = new TemplateContext()
681 context.readTemplateContext(new Element("context"))
683 def defContext = new TemplateContext()
684 def commentContext = TemplateContextType.EP_NAME.findExtension(JavaCommentContextType)
685 defContext.setEnabled(commentContext, true)
687 context.setDefaultContext(defContext)
688 assert context.isEnabled(commentContext)
689 assert !context.isEnabled(TemplateContextType.EP_NAME.findExtension(JavaCodeContextType.Generic))
692 void "test adding new context to Other"() {
693 def defElement = JDOMUtil.loadDocument('''\
695 <option name="OTHER" value="true"/>
696 </context>''').rootElement
697 def context = new TemplateContext()
698 context.readTemplateContext(defElement)
700 def javaContext = TemplateContextType.EP_NAME.findExtension(JavaCodeContextType.Generic)
701 context.setEnabled(javaContext, true)
703 def saved = new Element('context')
704 context.writeTemplateContext(saved)
706 context = new TemplateContext()
707 context.readTemplateContext(saved)
709 assert context.isEnabled(javaContext)
710 assert context.isEnabled(TemplateContextType.EP_NAME.findExtension(EverywhereContextType))
713 private boolean isApplicable(String text, TemplateImpl inst) throws IOException {
714 configureFromFileText("a.java", text)
715 return TemplateManagerImpl.isApplicable(myFixture.getFile(), getEditor().getCaretModel().getOffset(), inst)
718 private static writeCommand(Runnable runnable) {
719 WriteCommandAction.runWriteCommandAction(null, runnable)
722 void testSearchByDescriptionWhenTemplatesListed() {
723 myFixture.configureByText("a.java", "class A {{ <caret> }}")
725 new ListTemplatesHandler().invoke(project, editor, myFixture.file)
726 myFixture.type('array')
727 assert 'itar' in myFixture.lookupElementStrings
730 void testListTemplatesSearchesPrefixInDescription() {
731 myFixture.configureByText("a.java", "class A { main<caret> }")
733 new ListTemplatesHandler().invoke(project, editor, myFixture.file)
734 assert myFixture.lookupElementStrings == ['psvm']
737 void testListTemplatesAction() {
738 myFixture.configureByText("a.java", "class A {{ <caret> }}")
740 new ListTemplatesHandler().invoke(project, editor, myFixture.file)
741 assert myFixture.lookupElementStrings.containsAll(['iter', 'itco', 'toar'])
744 assert myFixture.lookupElementStrings[0].startsWith('it')
745 assert LookupManager.getInstance(project).activeLookup.currentItem == myFixture.getLookupElements()[0]
748 assert myFixture.lookupElementStrings[0].startsWith('ite')
749 assert LookupManager.getInstance(project).activeLookup.currentItem == myFixture.getLookupElements()[0]
750 LookupManager.getInstance(project).hideActiveLookup()
752 myFixture.type('\b\b')
753 new ListTemplatesHandler().invoke(project, editor, myFixture.file)
754 assert myFixture.lookupElementStrings.containsAll(['iter', 'itco'])
755 LookupManager.getInstance(project).hideActiveLookup()
757 myFixture.type('xxxxx')
758 new ListTemplatesHandler().invoke(project, editor, myFixture.file)
759 assert myFixture.lookupElementStrings.containsAll(['iter', 'itco', 'toar'])
760 LookupManager.getInstance(project).hideActiveLookup()
763 void testSelectionFromLookupBySpace() {
764 myFixture.configureByText("a.java", "class A {{ itc<caret> }}")
766 new ListTemplatesHandler().invoke(project, editor, myFixture.file)
768 myFixture.checkResult """\
769 import java.util.Iterator;
772 for (Iterator <selection>iterator</selection> = collection.iterator(); iterator.hasNext(); ) {
773 Object next = iterator.next();
779 void testNavigationActionsDontTerminateTemplate() throws Throwable {
780 configureFromFileText("a.txt", "")
782 final TemplateManager manager = TemplateManager.getInstance(getProject())
783 final Template template = manager.createTemplate("vn", "user", 'Hello $V1$ World $V1$\nHello $V2$ World $V2$\nHello $V3$ World $V3$')
784 template.addVariable("V1", "", "", true)
785 template.addVariable("V2", "", "", true)
786 template.addVariable("V3", "", "", true)
787 final Editor editor = getEditor()
789 startTemplate(template)
791 final TemplateState state = getState()
793 for (int i = 0; i < 3; i++) {
794 assertFalse(String.valueOf(i), state.isFinished())
796 final String docText = editor.getDocument().getText()
797 assertTrue(docText, docText.startsWith("Hello H World H\n"))
798 final int offset = editor.getCaretModel().getOffset()
800 moveCaret(offset + 1)
803 myFixture.completeBasic()
806 assertEquals(offset + 1, editor.getCaretModel().getOffset())
807 assertFalse(state.isFinished())
810 assertFalse(state.isFinished())
811 writeCommand { state.nextTab() }
813 assertTrue(state.isFinished())
814 checkResultByFile(getTestName(false) + "-out.txt")
817 private void moveCaret(final int offset) {
819 getEditor().getCaretModel().moveToOffset(offset)
823 void testUseDefaultValueForQuickResultCalculation() {
824 myFixture.configureByText 'a.txt', '<caret>'
826 final TemplateManager manager = TemplateManager.getInstance(getProject())
827 final Template template = manager.createTemplate("vn", "user", '$V1$ var = $V2$;')
828 template.addVariable("V1", "", "", true)
829 template.addVariable("V2", "", '"239"', true)
831 startTemplate(template)
833 myFixture.checkResult '<caret> var = 239;'
836 myFixture.checkResult 'O<caret> var = 239;'
839 myFixture.checkResult 'O var = <selection>239</selection>;'
842 void testTemplateExpandingWithSelection() {
843 final TemplateManager manager = TemplateManager.getInstance(getProject())
844 final Template template = manager.createTemplate("tpl", "user", 'expanded')
845 final JavaStringContextType contextType = contextType(JavaStringContextType.class)
846 ((TemplateImpl)template).getTemplateContext().setEnabled(contextType, true)
848 myFixture.configureByText("a.java", "class A { void f() { Stri<selection>ng s = \"tpl</selection><caret>\"; } }")
850 CodeInsightTestUtil.addTemplate(template, testRootDisposable)
852 myFixture.checkResult 'class A { void f() { Stri "; } }'
855 void "test expand current live template on no suggestions in lookup"() {
856 myFixture.configureByText "a.java", "class Foo {{ <caret> }}"
857 myFixture.completeBasic()
858 assert myFixture.lookup
859 myFixture.type("sout")
860 assert myFixture.lookup
861 assert myFixture.lookupElementStrings == []
863 myFixture.checkResult "class Foo {{\n System.out.println(<caret>);\n}}"
866 void "_test multi-dimensional toar"() {
867 myFixture.configureByText "a.java", '''
869 java.util.List<String[]> list;
870 String[][] s = toar<caret>
874 myFixture.checkResult '''
876 java.util.List<String[]> list;
877 String[][] s = list.toArray(new String[list.size()][])<caret>
881 void "test inner class name"() {
882 myFixture.configureByText "a.java", '''
891 assert myFixture.editor.document.text.contains("\"Inner.foo")
894 void "test do not strip type argument containing class"() {
895 myFixture.configureByText 'a.java', '''
898 List<Map.Entry<String, Integer>> foo() {
904 final TemplateManager manager = TemplateManager.getInstance(getProject())
905 final Template template = manager.createTemplate("result", "user", '$T$ result;')
906 template.addVariable('T', new MacroCallNode(new MethodReturnTypeMacro()), new EmptyNode(), false)
907 template.toReformat = true
909 startTemplate(template)
910 assert myFixture.editor.document.text.contains('List<Map.Entry<String, Integer>> result;')
913 void "test name shadowing"() {
914 myFixture.configureByText "a.java", """class LiveTemplateVarSuggestion {
915 private Object value;
916 public void setValue(Object value, Object value1){
921 assert myFixture.lookupElementStrings == ['value', 'value1']
924 void "test invoke surround template by tab"() {
925 myFixture.configureByText "a.txt", "B<caret>"
927 myFixture.checkResult("{<caret>}")
930 void "test escape string characters in soutv"() {
931 myFixture.configureByText "a.java", """
938 myFixture.type('\t"a"')
939 myFixture.checkResult """
942 System.out.println("\\"a\\" = " + "a"<caret>);
948 void "test stop at SELECTION when invoked surround template by tab"() {
949 myFixture.configureByText "a.txt", "<caret>"
951 final TemplateManager manager = TemplateManager.getInstance(getProject())
952 final Template template = manager.createTemplate("xxx", "user", 'foo $ARG$ bar $END$ goo $SELECTION$ after')
953 template.addVariable("ARG", "", "", true)
955 startTemplate(template)
956 myFixture.type('arg')
959 checkResultByText 'foo arg bar goo <caret> after'
962 void "test reuse static import"() {
963 myFixture.addClass("""package foo;
965 public static void someMethod() {}
966 public static void someMethod(int a) {}
968 myFixture.configureByText "a.java", """
969 import static foo.Bar.someMethod;
977 final TemplateManager manager = TemplateManager.getInstance(getProject())
978 final Template template = manager.createTemplate("xxx", "user", 'foo.Bar.someMethod($END$)')
979 template.setValue(USE_STATIC_IMPORT_IF_POSSIBLE, true)
981 startTemplate(template)
982 myFixture.checkResult """
983 import static foo.Bar.someMethod;
993 void "test concat macro"() {
994 final TemplateManager manager = TemplateManager.getInstance(getProject())
995 final Template template = manager.createTemplate("result", "user", '$A$ $B$ c')
996 template.addVariable('A', new EmptyNode(), true)
998 def macroCallNode = new MacroCallNode(new ConcatMacro())
999 macroCallNode.addParameter(new VariableNode('A', null))
1000 macroCallNode.addParameter(new TextExpression("ID"))
1001 template.addVariable('B', macroCallNode, false)
1003 myFixture.configureByText "a.txt", "<caret>"
1004 startTemplate(template)
1005 myFixture.type('tableName')
1008 myFixture.checkResult('tableName tableNameID c')
1011 void "test snakeCase should convert hyphens to underscores"() {
1012 final TemplateManager manager = TemplateManager.getInstance(getProject())
1013 final Template template = manager.createTemplate("result", "user", '$A$ $B$ c')
1014 template.addVariable('A', new EmptyNode(), true)
1016 def macroCallNode = new MacroCallNode(new SplitWordsMacro.SnakeCaseMacro())
1017 macroCallNode.addParameter(new VariableNode('A', null))
1018 template.addVariable('B', macroCallNode, false)
1020 myFixture.configureByText "a.txt", "<caret>"
1021 startTemplate(template)
1022 myFixture.type('-foo-bar_goo-')
1025 myFixture.checkResult('-foo-bar_goo- _foo_bar_goo_ c<caret>')
1028 void "test use single member static import first"() {
1029 myFixture.addClass("""package foo;
1031 public static void someMethod() {}
1032 public static void someMethod(int a) {}
1034 myFixture.configureByText "a.java", """
1042 final TemplateManager manager = TemplateManager.getInstance(getProject())
1043 final Template template = manager.createTemplate("xxx", "user", 'foo.Bar.someMethod($END$)')
1044 template.setValue(USE_STATIC_IMPORT_IF_POSSIBLE, true)
1046 startTemplate(template)
1047 myFixture.checkResult """import static foo.Bar.someMethod;
1057 void "test two static imports"() {
1058 myFixture.configureByText "a.java", """
1066 final TemplateManager manager = TemplateManager.getInstance(getProject())
1067 final Template template = manager.createTemplate("xxx", "user", 'java.lang.Math.abs(java.lang.Math.PI);')
1068 template.setValue(USE_STATIC_IMPORT_IF_POSSIBLE, true)
1070 startTemplate(template)
1071 myFixture.checkResult """\
1072 import static java.lang.Math.PI;
1073 import static java.lang.Math.abs;
1083 void "test do not replace macro value with null result"() {
1084 myFixture.configureByText "a.java", """\
1091 final TemplateManager manager = TemplateManager.getInstance(getProject())
1092 final Template template = manager.createTemplate("xxx", "user", '$VAR1$ $VAR2$ $VAR1$')
1093 template.addVariable("VAR1", "", "", true)
1094 template.addVariable("VAR2", new MacroCallNode(new FileNameMacro()), new ConstantNode("default"), true)
1095 ((TemplateImpl)template).templateContext.setEnabled(contextType(JavaCodeContextType.class), true)
1096 CodeInsightTestUtil.addTemplate(template, testRootDisposable)
1098 startTemplate(template)
1099 myFixture.checkResult """\
1102 <caret> a.java """ + """
1106 myFixture.type 'test'
1108 myFixture.checkResult """\
1111 test<caret> a.java test
1117 void "test do replace macro value with empty result"() {
1118 myFixture.configureByText "a.java", """\
1125 final TemplateManager manager = TemplateManager.getInstance(getProject())
1126 final Template template = manager.createTemplate("xxx", "user", '$VAR1$ $VAR2$')
1127 template.addVariable("VAR1", "", "", true)
1128 template.addVariable("VAR2", new MacroCallNode(new MyMirrorMacro("VAR1")), null, true)
1129 ((TemplateImpl)template).templateContext.setEnabled(contextType(JavaCodeContextType.class), true)
1130 CodeInsightTestUtil.addTemplate(template, testRootDisposable)
1132 startTemplate(template)
1133 myFixture.checkResult """\
1141 myFixture.checkResult """\
1149 myFixture.type '\b\b'
1150 myFixture.checkResult """\
1159 private static class MyMirrorMacro extends Macro {
1160 private final String myVariableName
1162 MyMirrorMacro(String variableName) {
1163 this.myVariableName = variableName
1172 String getPresentableName() {
1177 Result calculateResult(@NotNull Expression[] params, ExpressionContext context) {
1178 def state = TemplateManagerImpl.getTemplateState(context.editor)
1179 return state != null ? state.getVariableValue(myVariableName) : null
1183 Result calculateQuickResult(@NotNull Expression[] params, ExpressionContext context) {
1184 return calculateResult(params, context)
1188 void "test escape shouldn't move caret to the end marker"() {
1189 myFixture.configureByText 'a.java', """
1194 myFixture.type '\ta'
1195 myFixture.performEditorAction(IdeActions.ACTION_EDITOR_ESCAPE)
1196 myFixture.checkResult """
1198 for (int a<caret> = 0; a < array.length; a++) {
1206 void "test add new line on enter outside editing variable"() {
1207 myFixture.configureByText 'a.java', """
1212 myFixture.type 'soutv\tabc'
1213 myFixture.editor.caretModel.moveCaretRelatively(3, 0, false, false, false)
1215 myFixture.checkResult """
1217 System.out.println("abc = " + abc);
1223 void "test type tab character on tab outside editing variable"() {
1224 myFixture.configureByText 'a.java', """
1229 myFixture.type 'soutv\tabc'
1230 myFixture.editor.caretModel.moveCaretRelatively(2, 0, false, false, false)
1232 myFixture.checkResult """
1234 System.out.println("abc = " + abc); <caret>
1239 void "test delete at the last template position"() {
1240 myFixture.configureByText 'a.java', """
1245 myFixture.type 'iter\t'
1246 LightPlatformCodeInsightTestCase.delete(myFixture.editor, myFixture.project)
1247 myFixture.checkResult """
1249 for (Object o : <caret> {
1258 void "test multicaret expanding with space"() {
1259 myFixture.configureByText "a.java", """\
1268 def defaultShortcutChar = TemplateSettings.instance.defaultShortcutChar
1270 TemplateSettings.instance.defaultShortcutChar = TemplateSettings.SPACE_CHAR
1271 startTemplate("sout", TemplateSettings.SPACE_CHAR)
1274 TemplateSettings.instance.defaultShortcutChar = defaultShortcutChar
1276 myFixture.checkResult("""\
1279 System.out.println();
1280 System.out.println();
1281 System.out.println();
1287 void "test multicaret expanding with enter"() {
1288 myFixture.configureByText "a.java", """\
1297 def defaultShortcutChar = TemplateSettings.instance.defaultShortcutChar
1299 TemplateSettings.instance.defaultShortcutChar = TemplateSettings.ENTER_CHAR
1300 startTemplate("sout", TemplateSettings.ENTER_CHAR)
1303 TemplateSettings.instance.defaultShortcutChar = defaultShortcutChar
1305 myFixture.checkResult("""\
1308 System.out.println();
1309 System.out.println();
1310 System.out.println();
1316 void "test multicaret expanding with tab"() {
1317 myFixture.configureByText "a.java", """\
1326 def defaultShortcutChar = TemplateSettings.instance.defaultShortcutChar
1328 TemplateSettings.instance.defaultShortcutChar = TemplateSettings.TAB_CHAR
1329 startTemplate("sout", TemplateSettings.TAB_CHAR)
1332 TemplateSettings.instance.defaultShortcutChar = defaultShortcutChar
1335 myFixture.checkResult("""\
1338 System.out.println();
1339 System.out.println();
1340 System.out.println();
1346 void "test sout template in expression lambda"() {
1347 myFixture.configureByText 'a.java', '''class Foo {{
1348 strings.stream().forEach(o -> sout<caret>);
1351 myFixture.type('\t')
1352 myFixture.checkResult '''class Foo {{
1353 strings.stream().forEach(o -> System.out.println(<caret>));
1358 void "test finish template on moving caret by completion insert handler"() {
1359 TemplateManagerImpl templateManager = TemplateManager.getInstance(project) as TemplateManagerImpl
1360 myFixture.configureByText('a.html', '<selection><p></p></selection>')
1361 def template = TemplateSettings.instance.getTemplate("T2", "html/xml")
1362 myFixture.testAction(new InvokeTemplateAction(template, myFixture.editor, myFixture.project, ContainerUtil.newHashSet()))
1363 myFixture.complete(CompletionType.BASIC)
1364 myFixture.type("nofra")
1365 myFixture.finishLookup(Lookup.REPLACE_SELECT_CHAR)
1366 myFixture.checkResult("<noframes><caret><p></p></noframes>")
1367 assertNull(templateManager.getActiveTemplate(myFixture.editor))
1370 void "test escape with selection"() {
1371 myFixture.configureByText "a.java", """
1378 myFixture.type('\tfoo')
1379 myFixture.editor.selectionModel.setSelection(myFixture.caretOffset - 3, myFixture.caretOffset)
1380 assert myFixture.editor.selectionModel.hasSelection()
1382 myFixture.performEditorAction(IdeActions.ACTION_EDITOR_ESCAPE)
1383 assert !myFixture.editor.selectionModel.hasSelection()
1384 assert TemplateManager.getInstance(project).getActiveTemplate(myFixture.editor)
1386 myFixture.performEditorAction(IdeActions.ACTION_EDITOR_ESCAPE)
1387 assert !TemplateManager.getInstance(project).getActiveTemplate(myFixture.editor)
1389 myFixture.checkResult """
1392 System.out.println("foo = " + foo<caret>);
1398 void "test escape with lookup"() {
1399 myFixture.configureByText "a.java", """
1407 myFixture.type('\t')
1408 assert myFixture.lookup
1410 myFixture.performEditorAction(IdeActions.ACTION_EDITOR_ESCAPE)
1411 assert !myFixture.lookup
1412 assert TemplateManager.getInstance(project).getActiveTemplate(myFixture.editor)
1414 myFixture.performEditorAction(IdeActions.ACTION_EDITOR_ESCAPE)
1415 assert !TemplateManager.getInstance(project).getActiveTemplate(myFixture.editor)
1417 myFixture.checkResult """
1421 System.out.println("foo_1 = " + foo_1);
1427 void "test escape with lookup and selection"() {
1428 myFixture.configureByText "a.java", """
1436 myFixture.type('\tfoo')
1437 myFixture.editor.selectionModel.setSelection(myFixture.caretOffset - 3, myFixture.caretOffset)
1438 myFixture.completeBasic()
1439 assert myFixture.editor.selectionModel.hasSelection()
1440 assert myFixture.lookup
1442 myFixture.performEditorAction(IdeActions.ACTION_EDITOR_ESCAPE)
1443 assert !myFixture.editor.selectionModel.hasSelection()
1444 assert !myFixture.lookup
1445 assert TemplateManager.getInstance(project).getActiveTemplate(myFixture.editor)
1447 myFixture.performEditorAction(IdeActions.ACTION_EDITOR_ESCAPE)
1448 assert !TemplateManager.getInstance(project).getActiveTemplate(myFixture.editor)
1450 myFixture.checkResult """
1454 System.out.println("foo = " + foo<caret>);
1460 void "test escape with empty lookup"() {
1461 myFixture.configureByText "a.java", """
1469 myFixture.type('\tfoobar')
1470 assert myFixture.lookup
1471 assert !myFixture.lookup.currentItem
1473 myFixture.performEditorAction(IdeActions.ACTION_EDITOR_ESCAPE)
1474 assert !myFixture.lookup
1475 assert !TemplateManager.getInstance(project).getActiveTemplate(myFixture.editor)
1477 myFixture.checkResult """
1481 System.out.println("foobar = " + foobar);
1487 void "test iterate over list with wildcard component type"() {
1488 myFixture.configureByText 'a.java', '''class C {{
1489 java.util.List<? extends Integer> list;
1492 myFixture.type('itli\t')
1493 myFixture.checkResult '''class C {{
1494 java.util.List<? extends Integer> list;
1495 for (int i = 0; i < list.size(); i++) {
1496 Integer integer = list.get(i);
1502 void "test home end go outside template fragments if already on their bounds"() {
1503 myFixture.configureByText 'a.txt', ' <caret> g'
1505 TemplateManager manager = TemplateManager.getInstance(getProject())
1506 Template template = manager.createTemplate("empty", "user", '$VAR$')
1507 template.addVariable("VAR", "", '"foo"', true)
1508 manager.startTemplate(myFixture.editor, template)
1510 myFixture.checkResult ' <selection>foo<caret></selection> g'
1512 myFixture.performEditorAction(IdeActions.ACTION_EDITOR_MOVE_LINE_START)
1513 myFixture.checkResult ' <caret>foo g'
1515 myFixture.performEditorAction(IdeActions.ACTION_EDITOR_MOVE_LINE_START)
1516 myFixture.checkResult '<caret> foo g'
1518 myFixture.performEditorAction(IdeActions.ACTION_EDITOR_MOVE_CARET_RIGHT)
1519 myFixture.performEditorAction(IdeActions.ACTION_EDITOR_MOVE_LINE_END)
1520 myFixture.checkResult ' foo<caret> g'
1522 myFixture.performEditorAction(IdeActions.ACTION_EDITOR_MOVE_LINE_END)
1523 myFixture.checkResult ' foo g<caret>'