/* * Copyright (C) 2014 Bob Browning * * 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 postfix.internal; import com.intellij.codeInsight.template.Template; import com.intellij.codeInsight.template.TemplateEditingAdapter; import com.intellij.codeInsight.template.TemplateManager; import com.intellij.codeInsight.template.impl.TextExpression; import com.intellij.codeInsight.template.postfix.templates.PostfixTemplateWithExpressionSelector; import com.intellij.codeInsight.template.postfix.templates.PostfixTemplatesUtils; import com.intellij.codeInsight.template.postfix.templates.StringBasedPostfixTemplate; import com.intellij.codeInsight.template.postfix.util.JavaPostfixTemplatesUtils; import com.intellij.openapi.actionSystem.ActionManager; import com.intellij.openapi.actionSystem.ActionPlaces; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.impl.ActionManagerImpl; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.playback.commands.ActionCommand; import com.intellij.openapi.util.Condition; import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import postfix.util.ClassNames; import postfix.util.AndroidPostfixUtil; /** * Base class that is a modified form of {@link StringBasedPostfixTemplate} that passes the project to {@link * AbstractRichStringBasedPostfixTemplate#createTemplate} to allow querying of project properties. * * @author Bob Browning */ public abstract class AbstractRichStringBasedPostfixTemplate extends PostfixTemplateWithExpressionSelector { protected AbstractRichStringBasedPostfixTemplate(@NotNull String name, @NotNull String example, @NotNull Condition<PsiElement> typeChecker) { super(name, example, JavaPostfixTemplatesUtils.selectorAllExpressionsWithCurrentOffset(typeChecker)); } @Override protected final void expandForChooseExpression(@NotNull PsiElement expr, @NotNull final Editor editor) { Project project = expr.getProject(); Document document = editor.getDocument(); PsiElement elementForRemoving = shouldRemoveParent() ? expr.getParent() : expr; document.deleteString(elementForRemoving.getTextRange().getStartOffset(), elementForRemoving.getTextRange().getEndOffset()); final TemplateManager manager = TemplateManager.getInstance(project); String templateString = getTemplateString(expr); if (templateString == null) { PostfixTemplatesUtils.showErrorHint(expr.getProject(), editor); return; } Template template = createTemplate(project, manager, templateString); if (shouldAddExpressionToContext()) { addExprVariable(expr, template); } setVariables(template, expr); manager.startTemplate(editor, template, new TemplateEditingAdapter() { @Override public void templateFinished(Template template, boolean brokenOff) { onTemplateFinished(manager, editor, template); } }); } protected void onTemplateFinished(TemplateManager manager, Editor editor, Template template) { // format and add ; final ActionManager actionManager = ActionManagerImpl.getInstance(); final String editorCompleteStatementText = "EditorCompleteStatement"; final AnAction action = actionManager.getAction(editorCompleteStatementText); actionManager.tryToExecute(action, ActionCommand.getInputEvent(editorCompleteStatementText), null, ActionPlaces.UNKNOWN, true); } protected void addExprVariable(@NotNull PsiElement expr, Template template) { template.addVariable("expr", new TextExpression(expr.getText()), false); } /** * Add custom variables to the template. * * @param template The template * @param element The expression being replaced */ protected void setVariables(@NotNull Template template, @NotNull PsiElement element) { } @Nullable public abstract String getTemplateString(@NotNull PsiElement element); /** * Returns true if the {@code expr} variable should be added to the template by default. */ protected boolean shouldAddExpressionToContext() { return true; } /** * Returns true if the formatting manager should be applied to the generated code block. */ protected boolean shouldReformat() { return false; } /** * Returns true if the parent element should be removed, for example for topmost expression. */ protected boolean shouldRemoveParent() { return false; } /** * Create a new instance of a code template for the current postfix template. * * @param project The current project * @param manager The template manager * @param templateString The template string */ protected Template createTemplate(Project project, TemplateManager manager, String templateString) { Template template = manager.createTemplate("", "", templateString); template.setToReformat(shouldReformat()); template.setValue(Template.Property.USE_STATIC_IMPORT_IF_POSSIBLE, false); return template; } /** * Gets the static method prefix for the android static method. * * @param className The android class name * @param methodName The method name * @param context The context element */ protected String getStaticPrefix(@NotNull ClassNames className, @NotNull String methodName, @NotNull PsiElement context) { return getStaticPrefix(className.getClassName(), methodName, context); } /** * Gets the static method prefix for the android static method. * * @param className The android class name * @param methodName The method name * @param context The context element */ protected String getStaticPrefix(@NotNull String className, @NotNull String methodName, @NotNull PsiElement context) { return AndroidPostfixUtil.getStaticPrefix(className, methodName, context); } }