package com.jetbrains.dart.analysisServer;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
import com.intellij.testFramework.fixtures.CodeInsightFixtureTestCase;
import com.intellij.testFramework.fixtures.impl.CodeInsightTestFixtureImpl;
import com.jetbrains.lang.dart.assists.AssistUtils;
import com.jetbrains.lang.dart.assists.DartSourceEditException;
import com.jetbrains.lang.dart.ide.refactoring.DartServerRenameHandler;
import com.jetbrains.lang.dart.ide.refactoring.ServerRenameRefactoring;
import com.jetbrains.lang.dart.ide.refactoring.status.RefactoringStatus;
import com.jetbrains.lang.dart.util.DartTestUtils;
import org.dartlang.analysis.server.protocol.SourceChange;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Set;
public class DartServerRenameTest extends CodeInsightFixtureTestCase {
private static class DataContextForTest implements DataContext {
private final Editor myEditor;
private final VirtualFile myVirtualFile;
private final PsiFile myPsiFile;
private final PsiElement myPsiElement;
public DataContextForTest(Editor editor, VirtualFile virtualFile, PsiFile psiFile, PsiElement psiElement) {
myEditor = editor;
myVirtualFile = virtualFile;
myPsiFile = psiFile;
myPsiElement = psiElement;
}
@Nullable
@Override
public Object getData(@NotNull String dataId) {
if (dataId.equals(CommonDataKeys.EDITOR.getName())) return myEditor;
if (dataId.equals(CommonDataKeys.VIRTUAL_FILE.getName())) return myVirtualFile;
if (dataId.equals(CommonDataKeys.PSI_FILE.getName())) return myPsiFile;
if (dataId.equals(CommonDataKeys.PSI_ELEMENT.getName())) return myPsiElement;
return null;
}
}
@Override
public void setUp() throws Exception {
super.setUp();
DartTestUtils.configureDartSdk(myModule, myFixture.getTestRootDisposable(), true);
myFixture.setTestDataPath(DartTestUtils.BASE_TEST_DATA_PATH + getBasePath());
((CodeInsightTestFixtureImpl)myFixture).canChangeDocumentDuringHighlighting(true);
}
@Override
protected String getBasePath() {
return "/analysisServer/refactoring/rename";
}
private void doTest(@NotNull final String newName) {
final ServerRenameRefactoring refactoring = createRenameRefactoring();
doTest(refactoring, newName);
}
private void doTest(@NotNull final ServerRenameRefactoring refactoring, @NotNull final String newName) {
// check initial conditions
final RefactoringStatus initialConditions = refactoring.checkInitialConditions();
assertNotNull(initialConditions);
assertTrue(initialConditions.isOK());
// check final conditions
refactoring.setNewName(newName);
final RefactoringStatus finalConditions = refactoring.checkFinalConditions();
assertNotNull(finalConditions);
assertTrue(finalConditions.isOK());
// apply the SourceChange
final SourceChange change = refactoring.getChange();
assertNotNull(change);
ApplicationManager.getApplication().runWriteAction(() -> {
final Set<String> excludedIds = refactoring.getPotentialEdits();
try {
AssistUtils.applySourceChange(myFixture.getProject(), change, false, excludedIds);
}
catch (DartSourceEditException e) {
fail(e.getMessage());
}
});
// validate
myFixture.checkResultByFile(getTestName(false) + ".after.dart");
}
@NotNull
private ServerRenameRefactoring createRenameRefactoring() {
myFixture.configureByFile(getTestName(false) + ".dart");
myFixture.doHighlighting(); // make sure server is warmed up
final int offset = getEditor().getCaretModel().getOffset();
return new ServerRenameRefactoring(getProject(), getFile().getVirtualFile(), offset, 0);
}
public void testAvailability() {
final XmlFile htmlPsiFile = (XmlFile)myFixture.configureByText("foo.html", "<script type='application/dart'>\n" +
" var <caret>foo;\n" +
"</script>");
final VirtualFile htmlVirtualFile = htmlPsiFile.getVirtualFile();
final XmlTag htmlTag = htmlPsiFile.getRootTag();
final PsiElement dartElementInHtmlFile = htmlPsiFile.findElementAt(getEditor().getCaretModel().getOffset());
final PsiFile dartPsiFile = myFixture.addFileToProject("bar.dart", "// comment");
final VirtualFile dartVirtualFile = dartPsiFile.getVirtualFile();
final PsiElement dartElement = dartPsiFile.findElementAt(0);
final DartServerRenameHandler handler = new DartServerRenameHandler();
assertFalse("no editor", handler.isRenaming(new DataContextForTest(null, htmlVirtualFile, htmlPsiFile, null)));
assertFalse("html element at caret", handler.isRenaming(new DataContextForTest(getEditor(), htmlVirtualFile, htmlPsiFile, htmlTag)));
assertTrue("dart element in html file at caret",
handler.isRenaming(new DataContextForTest(getEditor(), htmlVirtualFile, htmlPsiFile, null)));
assertTrue("dart element in html file",
handler.isRenaming(new DataContextForTest(getEditor(), htmlVirtualFile, htmlPsiFile, dartElementInHtmlFile)));
myFixture.openFileInEditor(dartVirtualFile);
assertTrue("dart comment at caret", handler.isRenaming(new DataContextForTest(getEditor(), dartVirtualFile, dartPsiFile, null)));
assertTrue("dart comment at caret", handler.isRenaming(new DataContextForTest(getEditor(), dartVirtualFile, dartPsiFile, dartElement)));
}
public void testCheckFinalConditionsNameFatalError() throws Throwable {
final ServerRenameRefactoring refactoring = createRenameRefactoring();
// initial status OK
final RefactoringStatus initialConditions = refactoring.checkInitialConditions();
assertNotNull(initialConditions);
assertTrue(initialConditions.isOK());
// final (actually options) status has a fatal error
refactoring.setNewName("bad name");
final RefactoringStatus finalConditions = refactoring.checkFinalConditions();
assertNotNull(finalConditions);
assertTrue(finalConditions.hasFatalError());
}
public void testCheckInitialConditionsCannotCreate() throws Throwable {
final ServerRenameRefactoring refactoring = createRenameRefactoring();
final RefactoringStatus initialConditions = refactoring.checkInitialConditions();
assertNotNull(initialConditions);
assertTrue(initialConditions.hasFatalError());
}
public void testClass() throws Throwable {
doTest("NewName");
}
public void testConstructorDefaultToNamed() throws Throwable {
doTest("newName");
}
public void testIgnorePotential() throws Throwable {
doTest("newName");
}
public void testTypeAndImmediatelyRenameLocalVar() throws Throwable {
myFixture.configureByFile(getTestName(false) + ".dart");
myFixture.doHighlighting(); // warm up
myFixture.type('\n');
final int offset = getEditor().getCaretModel().getOffset();
final ServerRenameRefactoring refactoring = new ServerRenameRefactoring(getProject(), getFile().getVirtualFile(), offset, 0);
doTest(refactoring, "newName");
}
public void testMethod() throws Throwable {
doTest("newName");
}
public void testFileRename() {
final PsiFile barFile = myFixture.addFileToProject("src/bar.dart", "");
final PsiFile fooFile = myFixture.addFileToProject("foo.dart", "import r'''src/bar.dart''' ;");
final PsiFile bazFile = myFixture.addFileToProject("src/baz.dart", "export 'bar.dart';");
myFixture.openFileInEditor(barFile.getVirtualFile());
myFixture.doHighlighting(); // warm up
myFixture.renameElement(barFile, "renamed.dart");
myFixture.openFileInEditor(fooFile.getVirtualFile());
myFixture.checkResult("import r'''src/renamed.dart''';");
myFixture.openFileInEditor(bazFile.getVirtualFile());
myFixture.checkResult("export 'renamed.dart';");
}
public void testTargetFileMove() {
final PsiFile fooFile = myFixture.addFileToProject("web/src/foo.dart", "import \"bar.dart\";");
myFixture.addFileToProject("web/src/bar.dart", "");
myFixture.openFileInEditor(fooFile.getVirtualFile());
myFixture.doHighlighting(); // warm up
myFixture.moveFile("web/src/bar.dart", "web");
myFixture.openFileInEditor(fooFile.getVirtualFile());
myFixture.checkResult("import \"../bar.dart\";");
}
}