IDEA-81171 (live template for auto-closeable expression)

This commit is contained in:
Roman Shevchenko
2015-06-22 18:06:59 +03:00
parent a13b23e427
commit fa2fcfaf84
5 changed files with 137 additions and 4 deletions
@@ -0,0 +1,54 @@
/*
* Copyright 2000-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 com.intellij.codeInsight.template.macro;
import com.intellij.codeInsight.CodeInsightBundle;
import com.intellij.codeInsight.template.*;
import com.intellij.psi.PsiExpression;
import com.intellij.psi.PsiType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class ExpressionTypeMacro extends Macro {
@Override
public String getName() {
return "expressionType";
}
@Override
public String getPresentableName() {
return CodeInsightBundle.message("macro.expression.type");
}
@Nullable
@Override
public Result calculateResult(@NotNull Expression[] params, ExpressionContext context) {
if (params.length == 1) {
Result result = params[0].calculateResult(context);
if (result != null) {
PsiExpression expression = MacroUtil.resultToPsiExpression(result, context);
if (expression != null) {
PsiType type = expression.getType();
if (type != null) {
return new PsiTypeResult(type, context.getProject());
}
}
}
}
return null;
}
}
@@ -0,0 +1,56 @@
/*
* Copyright 2000-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 com.intellij.codeInsight.template
import com.intellij.codeInsight.template.impl.InvokeTemplateAction
import com.intellij.codeInsight.template.impl.SurroundWithTemplateHandler
import com.intellij.openapi.actionSystem.DefaultActionGroup
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
class SurroundWithTemplateTest extends LightCodeInsightFixtureTestCase {
public void testSurroundWithTryWithResources() {
myFixture.configureByText "C.java", """\
import java.io.*;
class C {
void m() {
new FileReader("/dev/null")<caret>
}
}""".stripIndent()
invokeTemplate("TR")
myFixture.checkResult """\
import java.io.*;
class C {
void m() {
try (FileReader fileReader = new FileReader("/dev/null")) {
<caret>
}
}
}""".stripIndent()
}
private void invokeTemplate(String template) {
DefaultActionGroup group = SurroundWithTemplateHandler.createActionGroup(project, editor, file)
assertNotNull(group)
InvokeTemplateAction action = group.childActionsOrStubs.find {
it instanceof InvokeTemplateAction && (it as InvokeTemplateAction).template.key == template
} as InvokeTemplateAction
assertNotNull(action)
action.perform()
}
}
@@ -365,6 +365,7 @@ macro.enum=enum(...)
macro.expected.type=expectedType()
macro.groovy.script=groovyScript("groovy code")
macro.guess.element.type.of.container=guessElementType(Container)
macro.expression.type=expressionType(Expression)
macro.iterable.component.type=iterableComponentType(ArrayOrIterable)
macro.iterable.variable=iterableVariable()
macro.linenumber=lineNumber()
@@ -421,6 +422,7 @@ livetemplate.description.surround.cdata.in.xmlorhtmlorjsp=Surround with CDATA se
livetemplate.description.surround.with.callable=Surround with Callable
livetemplate.description.surround.with.read.lock=Surround with ReadWriteLock.readLock
livetemplate.description.surround.with.write.lock=Surround with ReadWriteLock.writeLock
livetemplate.description.surround.with.ARM=Surround with try-with-resources
quickfix.add.variable.text=Initialize variable ''{0}''
quickfix.add.variable.family.name=Initialize variable
inspection.i18n.quickfix.annotate.as=Annotate as @{0}
+1
View File
@@ -1194,6 +1194,7 @@
<liveTemplateMacro implementation="com.intellij.codeInsight.template.macro.SuggestIndexNameMacro"/>
<liveTemplateMacro implementation="com.intellij.codeInsight.template.macro.GuessElementTypeMacro"/>
<liveTemplateMacro implementation="com.intellij.codeInsight.template.macro.ExpectedTypeMacro"/>
<liveTemplateMacro implementation="com.intellij.codeInsight.template.macro.ExpressionTypeMacro"/>
<liveTemplateMacro implementation="com.intellij.codeInsight.template.macro.AnnotatedMacro"/>
<liveTemplateMacro implementation="com.intellij.codeInsight.template.macro.MethodNameMacro"/>
+24 -4
View File
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<templateSet group="surround">
<template resource-bundle="messages.CodeInsightBundle" key="livetemplate.description.surround.braces"
name="B" toReformat="true" toShortenFQNames="true" value="{$SELECTION$}">
<context>
@@ -15,6 +16,7 @@
<option name="OTHER" value="true" />
</context>
</template>
<template resource-bundle="messages.CodeInsightBundle" key="livetemplate.description.surround.parens"
name="P" toReformat="false" toShortenFQNames="true" value="($SELECTION$)">
<context>
@@ -30,30 +32,37 @@
<option name="OTHER" value="true" />
</context>
</template>
<template name="C" resource-bundle="messages.CodeInsightBundle" key="livetemplate.description.surround.with.callable"
value="java.util.concurrent.Callable&lt;$RET$&gt; callable = new java.util.concurrent.Callable&lt;$RET$&gt;() {&#10; public $RET$ call() throws Exception {&#10; $SELECTION$&#10; $END$ &#10; }&#10;};" toReformat="true" toShortenFQNames="true">
value="java.util.concurrent.Callable&lt;$RET$&gt; callable = new java.util.concurrent.Callable&lt;$RET$&gt;() {&#10; public $RET$ call() throws Exception {&#10; $SELECTION$&#10; $END$ &#10; }&#10;};"
toReformat="true" toShortenFQNames="true">
<variable name="RET" expression="" defaultValue="&quot;java.lang.Object&quot;" alwaysStopAt="true" />
<context>
<option name="JAVA_CODE" value="false" />
<option name="JAVA_STATEMENT" value="true" />
</context>
</template>
<template name="RL" resource-bundle="messages.CodeInsightBundle" key="livetemplate.description.surround.with.read.lock"
value="$LOCK$.readLock().lock();&#10;try { &#10; $SELECTION$&#10;} finally {&#10; $LOCK$.readLock().unlock();&#10;}&#10;" toReformat="true" toShortenFQNames="true">
value="$LOCK$.readLock().lock();&#10;try { &#10; $SELECTION$&#10;} finally {&#10; $LOCK$.readLock().unlock();&#10;}&#10;"
toReformat="true" toShortenFQNames="true">
<variable name="LOCK" expression="variableOfType(&quot;java.util.concurrent.locks.ReadWriteLock&quot;)" defaultValue="" alwaysStopAt="true" />
<context>
<option name="JAVA_CODE" value="false" />
<option name="JAVA_STATEMENT" value="true" />
</context>
</template>
<template name="WL" resource-bundle="messages.CodeInsightBundle" key="livetemplate.description.surround.with.write.lock"
value="$LOCK$.writeLock().lock();&#10;try { &#10; $SELECTION$&#10;} finally {&#10; $LOCK$.writeLock().unlock();&#10;}&#10;" toReformat="true" toShortenFQNames="true">
<template name="WL" resource-bundle="messages.CodeInsightBundle" key="livetemplate.description.surround.with.write.lock"
value="$LOCK$.writeLock().lock();&#10;try { &#10; $SELECTION$&#10;} finally {&#10; $LOCK$.writeLock().unlock();&#10;}&#10;"
toReformat="true" toShortenFQNames="true">
<variable name="LOCK" expression="variableOfType(&quot;java.util.concurrent.locks.ReadWriteLock&quot;)" defaultValue="" alwaysStopAt="true" />
<context>
<option name="JAVA_CODE" value="false" />
<option name="JAVA_STATEMENT" value="true" />
</context>
</template>
<template name="I" value="for ($ELEMENT_TYPE$ $VAR$ : $SELECTION$) {&#10; $END$&#10;}&#10;"
resource-bundle="messages.CodeInsightBundle" key="livetemplate.description.iter" toReformat="true" toShortenFQNames="true">
<variable name="ELEMENT_TYPE" expression="iterableComponentType(SELECTION)" defaultValue="&quot;java.lang.Object&quot;" alwaysStopAt="false" />
@@ -63,4 +72,15 @@
<option name="JAVA_STATEMENT" value="true" />
</context>
</template>
<template name="TR" value="try ($ELEMENT_TYPE$ $VAR$ = $SELECTION$) {&#10; $END$&#10;}&#10;"
resource-bundle="messages.CodeInsightBundle" key="livetemplate.description.surround.with.ARM" toReformat="true" toShortenFQNames="true">
<variable name="ELEMENT_TYPE" expression="expressionType(SELECTION)" defaultValue="java.lang.AutoCloseable" alwaysStopAt="false" />
<variable name="VAR" expression="suggestVariableName()" defaultValue="" alwaysStopAt="true" />
<context>
<option name="JAVA_CODE" value="false" />
<option name="JAVA_STATEMENT" value="true" />
</context>
</template>
</templateSet>