diff --git a/idea/src/org/jetbrains/jet/plugin/liveTemplates/macro/AnonymousTemplateEditingListener.java b/idea/src/org/jetbrains/jet/plugin/liveTemplates/macro/AnonymousTemplateEditingListener.java new file mode 100644 index 00000000000..781203e34c9 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/liveTemplates/macro/AnonymousTemplateEditingListener.java @@ -0,0 +1,82 @@ +package org.jetbrains.jet.plugin.liveTemplates.macro; + +import com.intellij.codeInsight.template.Template; +import com.intellij.codeInsight.template.TemplateEditingAdapter; +import com.intellij.codeInsight.template.impl.TemplateManagerImpl; +import com.intellij.codeInsight.template.impl.TemplateState; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import org.jetbrains.jet.lang.descriptors.ClassDescriptor; +import org.jetbrains.jet.lang.descriptors.ClassKind; +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; +import org.jetbrains.jet.lang.psi.JetFile; +import org.jetbrains.jet.lang.psi.JetReferenceExpression; +import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.plugin.compiler.WholeProjectAnalyzerFacade; + +import java.util.HashMap; +import java.util.Map; + +/** +* @author Evgeny Gerashchenko +* @since 2/7/12 +*/ +class AnonymousTemplateEditingListener extends TemplateEditingAdapter { + private JetReferenceExpression classRef; + private ClassDescriptor classDescriptor; + private Editor editor; + private final PsiFile psiFile; + + private static Map ourAddedListeners = + new HashMap(); + + public AnonymousTemplateEditingListener(PsiFile psiFile, Editor editor) { + this.psiFile = psiFile; + this.editor = editor; + } + + @Override + public void currentVariableChanged(TemplateState templateState, Template template, int oldIndex, int newIndex) { + TextRange variableRange = templateState.getVariableRange(0); + if (variableRange == null) return; + PsiElement name = psiFile.findElementAt(variableRange.getStartOffset()); + if (name != null && name.getParent() instanceof JetReferenceExpression) { + JetReferenceExpression ref = (JetReferenceExpression) name.getParent(); + + BindingContext bc = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile((JetFile) psiFile); + DeclarationDescriptor descriptor = bc.get(BindingContext.REFERENCE_TARGET, ref); + if (descriptor instanceof ClassDescriptor) { + classRef = ref; + classDescriptor = (ClassDescriptor) descriptor; + } + } + } + + @Override + public void templateFinished(Template template, boolean brokenOff) { + ourAddedListeners.remove(editor); + + if (classDescriptor != null && classDescriptor.getKind() == ClassKind.CLASS) { + int placeToInsert = classRef.getTextRange().getEndOffset(); + PsiDocumentManager.getInstance(psiFile.getProject()).getDocument(psiFile).insertString(placeToInsert, "()"); + } + } + + static void registerListener(Editor editor, Project project) { + if (ourAddedListeners.containsKey(editor)) { + return; + } + PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument()); + assert psiFile != null; + TemplateState templateState = TemplateManagerImpl.getTemplateState(editor); + if (templateState != null) { + AnonymousTemplateEditingListener listener = new AnonymousTemplateEditingListener(psiFile, editor); + ourAddedListeners.put(editor, listener); + templateState.addTemplateStateListener(listener); + } + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/liveTemplates/macro/JetAnonymousSuperMacro.java b/idea/src/org/jetbrains/jet/plugin/liveTemplates/macro/JetAnonymousSuperMacro.java index 001a217bddc..1fc8fdca8a4 100644 --- a/idea/src/org/jetbrains/jet/plugin/liveTemplates/macro/JetAnonymousSuperMacro.java +++ b/idea/src/org/jetbrains/jet/plugin/liveTemplates/macro/JetAnonymousSuperMacro.java @@ -2,19 +2,14 @@ package org.jetbrains.jet.plugin.liveTemplates.macro; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupElementBuilder; -import com.intellij.codeInsight.template.Expression; -import com.intellij.codeInsight.template.ExpressionContext; -import com.intellij.codeInsight.template.Macro; -import com.intellij.codeInsight.template.Result; +import com.intellij.codeInsight.template.*; import com.intellij.openapi.project.Project; -import com.intellij.psi.PsiDocumentManager; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; -import com.intellij.psi.PsiNamedElement; +import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.ClassDescriptor; +import org.jetbrains.jet.lang.descriptors.ClassKind; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.psi.JetFile; @@ -44,8 +39,10 @@ public class JetAnonymousSuperMacro extends Macro { } @Override - public Result calculateResult(@NotNull Expression[] params, ExpressionContext context) { - final PsiNamedElement[] vars = getSupertypes(params, context); + public Result calculateResult(@NotNull Expression[] params, final ExpressionContext context) { + AnonymousTemplateEditingListener.registerListener(context.getEditor(), context.getProject()); + + PsiNamedElement[] vars = getSupertypes(params, context); if (vars == null || vars.length == 0) return null; return new JetPsiElementResult(vars[0]); } @@ -77,18 +74,22 @@ public class JetAnonymousSuperMacro extends Macro { if (scope == null) { return null; } - + List result = new ArrayList(); for (DeclarationDescriptor descriptor : scope.getAllDescriptors()) { - if (descriptor instanceof ClassDescriptor && ((ClassDescriptor) descriptor).getModality().isOverridable()) { + if (!(descriptor instanceof ClassDescriptor)) continue; + ClassDescriptor classDescriptor = (ClassDescriptor) descriptor; + if (!classDescriptor.getModality().isOverridable()) continue; + ClassKind kind = classDescriptor.getKind(); + if (kind == ClassKind.TRAIT || kind == ClassKind.CLASS) { PsiElement declaration = bc.get(BindingContext.DESCRIPTOR_TO_DECLARATION, descriptor); if (declaration != null) { result.add((PsiNamedElement) declaration); } } } - + return result.toArray(new PsiNamedElement[result.size()]); } }