Create from usage: Fixed adding methods across files.

This commit is contained in:
Jack Zhou
2013-04-12 00:18:25 -04:00
parent 2284c7bd48
commit 4ffbd353d9
@@ -29,11 +29,13 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.editor.CaretModel; import com.intellij.openapi.editor.CaretModel;
import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.popup.PopupChooserBuilder; import com.intellij.openapi.ui.popup.PopupChooserBuilder;
import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile; import com.intellij.psi.PsiFile;
@@ -423,6 +425,8 @@ public class CreateMethodFromUsageFix extends CreateFromUsageFixBase {
private boolean isExtension; private boolean isExtension;
private JetFile currentFile; private JetFile currentFile;
private JetFile containingFile; private JetFile containingFile;
private Editor currentFileEditor;
private Editor containingFileEditor;
private BindingContext currentFileContext; private BindingContext currentFileContext;
private JetClass ownerClass; private JetClass ownerClass;
private ClassDescriptor ownerClassDescriptor; private ClassDescriptor ownerClassDescriptor;
@@ -444,17 +448,16 @@ public class CreateMethodFromUsageFix extends CreateFromUsageFixBase {
} }
@Override @Override
public void invoke(@NotNull final Project project, final Editor editor, PsiFile file) throws IncorrectOperationException { public void invoke(@NotNull final Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
// TODO: editing across files assert file != null && file instanceof JetFile;
assert file instanceof JetFile;
currentFile = (JetFile) file; currentFile = (JetFile) file;
currentFileEditor = editor;
JetType[] possibleOwnerTypes = ownerType.getPossibleTypes(currentFileContext); JetType[] possibleOwnerTypes = ownerType.getPossibleTypes(currentFileContext);
assert possibleOwnerTypes.length > 0; assert possibleOwnerTypes.length > 0;
if (possibleOwnerTypes.length == 1) { if (possibleOwnerTypes.length == 1) {
JetType ownerType = possibleOwnerTypes[0]; JetType ownerType = possibleOwnerTypes[0];
doInvoke(project, editor, ownerType); doInvoke(project, ownerType);
} else { } else {
// class selection // class selection
List<String> options = new ArrayList<String>(); List<String> options = new ArrayList<String>();
@@ -489,7 +492,7 @@ public class CreateMethodFromUsageFix extends CreateFromUsageFixBase {
CommandProcessor.getInstance().executeCommand(project, new Runnable() { CommandProcessor.getInstance().executeCommand(project, new Runnable() {
@Override @Override
public void run() { public void run() {
doInvoke(project, editor, ownerType); doInvoke(project, ownerType);
} }
}, getText(), null); }, getText(), null);
} }
@@ -498,11 +501,11 @@ public class CreateMethodFromUsageFix extends CreateFromUsageFixBase {
builder.setTitle(JetBundle.message("choose.target.class.or.trait.title")) builder.setTitle(JetBundle.message("choose.target.class.or.trait.title"))
.setItemChoosenCallback(runnable) .setItemChoosenCallback(runnable)
.createPopup() .createPopup()
.showInBestPositionFor(editor); .showInBestPositionFor(currentFileEditor);
} }
} }
private void doInvoke(@NotNull final Project project, @NotNull final Editor editor, @NotNull JetType ownerType) { private void doInvoke(@NotNull final Project project, @NotNull JetType ownerType) {
// gather relevant information // gather relevant information
ClassifierDescriptor ownerTypeDescriptor = ownerType.getConstructor().getDeclarationDescriptor(); ClassifierDescriptor ownerTypeDescriptor = ownerType.getConstructor().getDeclarationDescriptor();
assert ownerTypeDescriptor != null && ownerTypeDescriptor instanceof ClassDescriptor; assert ownerTypeDescriptor != null && ownerTypeDescriptor instanceof ClassDescriptor;
@@ -534,7 +537,7 @@ public class CreateMethodFromUsageFix extends CreateFromUsageFixBase {
@Override @Override
public void run() { public void run() {
JetNamedFunction func = createFunctionSkeleton(project); JetNamedFunction func = createFunctionSkeleton(project);
buildAndRunTemplate(project, editor, func); buildAndRunTemplate(project, func);
} }
}); });
} }
@@ -552,6 +555,7 @@ public class CreateMethodFromUsageFix extends CreateFromUsageFixBase {
String methodText = String.format("fun %s.%s(%s)%s { }", ownerTypeString, methodName, parametersString, returnTypeString); String methodText = String.format("fun %s.%s(%s)%s { }", ownerTypeString, methodName, parametersString, returnTypeString);
func = JetPsiFactory.createFunction(project, methodText); func = JetPsiFactory.createFunction(project, methodText);
containingFile = currentFile; containingFile = currentFile;
containingFileEditor = currentFileEditor;
func = (JetNamedFunction) currentFile.add(func); func = (JetNamedFunction) currentFile.add(func);
} else { // create as method } else { // create as method
String methodText = String.format("fun %s(%s)%s { }", methodName, parametersString, returnTypeString); String methodText = String.format("fun %s(%s)%s { }", methodName, parametersString, returnTypeString);
@@ -559,16 +563,25 @@ public class CreateMethodFromUsageFix extends CreateFromUsageFixBase {
PsiFile classContainingFile = ownerClass.getContainingFile(); PsiFile classContainingFile = ownerClass.getContainingFile();
assert classContainingFile instanceof JetFile; assert classContainingFile instanceof JetFile;
containingFile = (JetFile) classContainingFile; containingFile = (JetFile) classContainingFile;
VirtualFile virtualFile = containingFile.getVirtualFile();
assert virtualFile != null;
FileEditorManager fileEditorManager = FileEditorManager.getInstance(project);
fileEditorManager.openFile(virtualFile, true);
containingFileEditor = fileEditorManager.getSelectedTextEditor();
JetClassBody classBody = ownerClass.getBody(); JetClassBody classBody = ownerClass.getBody();
assert classBody != null; assert classBody != null;
PsiElement rBrace = classBody.getRBrace(); PsiElement rBrace = classBody.getRBrace();
assert rBrace != null;
func = (JetNamedFunction) classBody.addBefore(func, rBrace); func = (JetNamedFunction) classBody.addBefore(func, rBrace);
} }
// TODO: add newlines // TODO: add newlines
return func; return func;
} }
private void buildAndRunTemplate(@NotNull final Project project, @NotNull Editor editor, @NotNull JetNamedFunction func) { private void buildAndRunTemplate(@NotNull final Project project, @NotNull JetNamedFunction func) {
JetParameterList parameterList = func.getValueParameterList(); JetParameterList parameterList = func.getValueParameterList();
assert parameterList != null; assert parameterList != null;
@@ -584,13 +597,12 @@ public class CreateMethodFromUsageFix extends CreateFromUsageFixBase {
// build templates // build templates
PsiDocumentManager.getInstance(project).commitAllDocuments(); PsiDocumentManager.getInstance(project).commitAllDocuments();
PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.getDocument()); PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(containingFileEditor.getDocument());
final CaretModel caretModel = editor.getCaretModel(); CaretModel caretModel = containingFileEditor.getCaretModel();
final int oldOffset = caretModel.getOffset(); caretModel.moveToOffset(containingFile.getNode().getStartOffset());
caretModel.moveToOffset(currentFile.getNode().getStartOffset());
TemplateBuilderImpl builder = new TemplateBuilderImpl(currentFile); TemplateBuilderImpl builder = new TemplateBuilderImpl(containingFile);
final TypeExpression returnTypeExpression = isUnit ? null : setupReturnTypeTemplate(builder, func); final TypeExpression returnTypeExpression = isUnit ? null : setupReturnTypeTemplate(builder, func);
final TypeExpression[] parameterTypeExpressions = setupParameterTypeTemplates(project, builder, parameterList); final TypeExpression[] parameterTypeExpressions = setupParameterTypeTemplates(project, builder, parameterList);
@@ -613,7 +625,7 @@ public class CreateMethodFromUsageFix extends CreateFromUsageFixBase {
variables.add(new Variable(TYPE_PARAMETER_LIST_VARIABLE_NAME, expression, expression, false, true)); variables.add(new Variable(TYPE_PARAMETER_LIST_VARIABLE_NAME, expression, expression, false, true));
// run the template // run the template
TemplateManager.getInstance(project).startTemplate(editor, template, new TemplateEditingAdapter() { TemplateManager.getInstance(project).startTemplate(containingFileEditor, template, new TemplateEditingAdapter() {
@Override @Override
public void templateFinished(Template _, boolean brokenOff) { public void templateFinished(Template _, boolean brokenOff) {
// file templates // file templates
@@ -634,8 +646,6 @@ public class CreateMethodFromUsageFix extends CreateFromUsageFixBase {
}); });
ReferenceToClassesShortening.compactReferenceToClasses(typeRefsToShorten); ReferenceToClassesShortening.compactReferenceToClasses(typeRefsToShorten);
caretModel.moveToOffset(oldOffset);
} }
}); });
} }
@@ -973,7 +983,7 @@ public class CreateMethodFromUsageFix extends CreateFromUsageFixBase {
// TODO: usages of variable // TODO: usages of variable
// TODO: case 5: nested in a trivial expression (e.g. parentheses or if-else) // TODO: nested in a trivial expression (e.g. parentheses or if-else)
return new JetType[0]; return new JetType[0];
} }