blob: ccdd54ce36b9f06b4dda8dd8142acb0b2642d626 [file] [log] [blame]
/*
* Copyright 2000-2012 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.daemon.quickFix;
import com.intellij.codeInsight.CodeInsightBundle;
import com.intellij.codeInspection.LocalQuickFixAndIntentionActionOnPsiElement;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.TextEditor;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.openapi.fileTypes.FileTypeRegistry;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.impl.PsiManagerImpl;
import com.intellij.psi.impl.file.PsiDirectoryImpl;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
/**
* @author peter
*/
public class CreateFileFix extends LocalQuickFixAndIntentionActionOnPsiElement {
private final boolean myIsDirectory;
private final String myNewFileName;
private final String myText;
@NotNull private final String myKey;
private boolean myIsAvailable;
private long myIsAvailableTimeStamp;
private static final int REFRESH_INTERVAL = 1000;
public CreateFileFix(boolean isDirectory,
@NotNull String newFileName,
@NotNull PsiDirectory directory,
@Nullable String text,
@NotNull String key) {
super(directory);
myIsDirectory = isDirectory;
myNewFileName = newFileName;
myText = text;
myKey = key;
myIsAvailable = isDirectory || !FileTypeManager.getInstance().getFileTypeByFileName(newFileName).isBinary();
myIsAvailableTimeStamp = System.currentTimeMillis();
}
public CreateFileFix(@NotNull String newFileName, @NotNull PsiDirectory directory, String text) {
this(false,newFileName,directory, text, "create.file.text");
}
public CreateFileFix(final boolean isDirectory, @NotNull String newFileName, @NotNull PsiDirectory directory) {
this(isDirectory,newFileName,directory,null, isDirectory ? "create.directory.text":"create.file.text" );
}
@Nullable
protected String getFileText() {
return myText;
}
@Override
@NotNull
public String getText() {
return CodeInsightBundle.message(myKey, myNewFileName);
}
@Override
@NotNull
public String getFamilyName() {
return CodeInsightBundle.message("create.file.family");
}
@Override
public void invoke(@NotNull final Project project,
@NotNull PsiFile file,
Editor editor,
@NotNull PsiElement startElement,
@NotNull PsiElement endElement) {
final PsiDirectory myDirectory = (PsiDirectory)startElement;
if (isAvailable(project, null, file)) {
new WriteCommandAction(project) {
@Override
protected void run(Result result) throws Throwable {
invoke(project, myDirectory);
}
}.execute();
}
}
@Override
public void applyFix() {
invoke(myStartElement.getProject(), (PsiDirectory)myStartElement.getElement());
}
@Override
public boolean isAvailable(@NotNull Project project,
@NotNull PsiFile file,
@NotNull PsiElement startElement,
@NotNull PsiElement endElement) {
final PsiDirectory myDirectory = (PsiDirectory)startElement;
long current = System.currentTimeMillis();
if (ApplicationManager.getApplication().isUnitTestMode() || current - myIsAvailableTimeStamp > REFRESH_INTERVAL) {
myIsAvailable &= myDirectory.getVirtualFile().findChild(myNewFileName) == null;
myIsAvailableTimeStamp = current;
}
return myIsAvailable;
}
private void invoke(@NotNull Project project, PsiDirectory myDirectory) throws IncorrectOperationException {
myIsAvailableTimeStamp = 0; // to revalidate applicability
try {
if (myIsDirectory) {
myDirectory.createSubdirectory(myNewFileName);
}
else {
String newFileName = myNewFileName;
String newDirectories = null;
if (myNewFileName.contains("/")) {
int pos = myNewFileName.lastIndexOf("/");
newFileName = myNewFileName.substring(pos + 1);
newDirectories = myNewFileName.substring(0, pos);
}
PsiDirectory directory = myDirectory;
if (newDirectories != null) {
try {
VfsUtil.createDirectoryIfMissing(myDirectory.getVirtualFile(), newDirectories);
VirtualFile vfsDir = VfsUtil.findRelativeFile(myDirectory.getVirtualFile(), ArrayUtil.toStringArray(StringUtil.split(newDirectories, "/")));
directory = new PsiDirectoryImpl((PsiManagerImpl)myDirectory.getManager(), vfsDir);
}
catch (IOException e) {
throw new IncorrectOperationException(e.getMessage());
}
}
final PsiFile newFile = directory.createFile(newFileName);
String text = getFileText();
if (text != null) {
final FileType type = FileTypeRegistry.getInstance().getFileTypeByFileName(newFileName);
final PsiFile psiFile = PsiFileFactory.getInstance(project).createFileFromText("_" + newFileName, type, text);
final PsiElement psiElement = CodeStyleManager.getInstance(project).reformat(psiFile);
text = psiElement.getText();
}
final FileEditorManager editorManager = FileEditorManager.getInstance(directory.getProject());
final FileEditor[] fileEditors = editorManager.openFile(newFile.getVirtualFile(), true);
if (text != null) {
for(FileEditor fileEditor: fileEditors) {
if (fileEditor instanceof TextEditor) { // JSP is not safe to edit via Psi
final Document document = ((TextEditor)fileEditor).getEditor().getDocument();
document.setText(text);
if (ApplicationManager.getApplication().isUnitTestMode()) {
FileDocumentManager.getInstance().saveDocument(document);
}
PsiDocumentManager.getInstance(project).commitDocument(document);
break;
}
}
}
}
}
catch (IncorrectOperationException e) {
myIsAvailable = false;
}
}
}