Adding () automatically if supertype is class.

This commit is contained in:
Evgeny Gerashchenko
2012-02-07 19:15:08 +04:00
parent 5a6c658204
commit 9e021c07a7
2 changed files with 96 additions and 13 deletions
@@ -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<Editor, AnonymousTemplateEditingListener> ourAddedListeners =
new HashMap<Editor, AnonymousTemplateEditingListener>();
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);
}
}
}
@@ -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<PsiNamedElement> result = new ArrayList<PsiNamedElement>();
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()]);
}
}