package com.intellij.flex.refactoring;
import com.intellij.flex.util.FlexTestUtils;
import com.intellij.javascript.flex.css.FlexStylesIndexableSetContributor;
import com.intellij.javascript.flex.mxml.schema.FlexSchemaHandler;
import com.intellij.lang.javascript.JSTestOption;
import com.intellij.lang.javascript.JSTestOptions;
import com.intellij.lang.javascript.JavaScriptSupportLoader;
import com.intellij.lang.javascript.dialects.JSDialectSpecificHandlersFactory;
import com.intellij.lang.javascript.flex.FlexModuleType;
import com.intellij.lang.javascript.psi.ecmal4.JSClass;
import com.intellij.lang.javascript.psi.resolve.JSInheritanceUtil;
import com.intellij.lang.javascript.refactoring.memberPushDown.JSPushDownProcessor;
import com.intellij.lang.javascript.refactoring.util.JSMemberInfo;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.module.ModuleType;
import com.intellij.openapi.util.Conditions;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.newvfs.impl.VfsRootAccess;
import com.intellij.psi.impl.source.PostprocessReformattingAspect;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.refactoring.BaseRefactoringProcessor;
import com.intellij.refactoring.MultiFileTestCase;
import com.intellij.refactoring.util.DocCommentPolicy;
import com.intellij.usageView.UsageInfo;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
import java.util.List;
import static com.intellij.openapi.vfs.VfsUtilCore.convertFromUrl;
import static com.intellij.openapi.vfs.VfsUtilCore.urlToPath;
public class FlexPushDownTest extends MultiFileTestCase {
@Override
protected void setUp() throws Exception {
VfsRootAccess.allowRootAccess(getTestRootDisposable(),
urlToPath(convertFromUrl(FlexSchemaHandler.class.getResource("z.xsd"))),
urlToPath(convertFromUrl(FlexStylesIndexableSetContributor.class.getResource("FlexStyles.as"))));
super.setUp();
}
@NotNull
@Override
protected String getTestRoot() {
return "pushDown/";
}
@Override
protected String getTestDataPath() {
return FlexTestUtils.getTestDataPath("");
}
@Override
protected ModuleType getModuleType() {
return FlexModuleType.getInstance();
}
@Override
protected void setUpJdk() {
FlexTestUtils.setupFlexSdk(getModule(), getTestName(false), getClass());
}
private void doTestPushDown(final String from, final int docCommentPolicy, final boolean makeAbstract, final String... toPushDown)
throws Exception {
doTest(new PerformAction() {
@Override
public void performAction(VirtualFile rootDir, VirtualFile rootAfter) throws Exception {
FlexPushDownTest.this.performAction(from, docCommentPolicy, makeAbstract, toPushDown);
}
}, false);
}
private void performAction(String from, int docCommentPolicy, boolean makeAbstract, final String[] toPushDown) {
final JSClass sourceClass =
(JSClass)JSDialectSpecificHandlersFactory.forLanguage(JavaScriptSupportLoader.ECMA_SCRIPT_L4).getClassResolver()
.findClassByQName(from, GlobalSearchScope.projectScope(getProject()));
assertNotNull("source class not found: " + from, sourceClass);
assertTrue(sourceClass.getQualifiedName() + " has no inheritors",
!JSInheritanceUtil.findDirectSubClasses(sourceClass, false).isEmpty());
final List<JSMemberInfo> memberInfos = FlexPullUpTest.getMemberInfos(toPushDown, sourceClass, makeAbstract);
JSMemberInfo[] infosArray = JSMemberInfo.getSelected(memberInfos, sourceClass, Conditions.alwaysTrue());
new JSPushDownProcessor(myProject, infosArray, sourceClass, docCommentPolicy) {
@Override
@NotNull
protected UsageInfo[] findUsages() {
// ensure stable order
final UsageInfo[] usages = super.findUsages();
Arrays.sort(usages,
(o1, o2) -> ((JSClass)o1.getElement()).getQualifiedName().compareTo(((JSClass)o2.getElement()).getQualifiedName()));
return usages;
}
}.run();
myProject.getComponent(PostprocessReformattingAspect.class).doPostponedFormatting();
FileDocumentManager.getInstance().saveAllDocuments();
}
private void doTestConflicts(final String from, String[] expectedConflicts, final String... toPushDown) throws Exception {
try {
doTestPushDown(from, DocCommentPolicy.MOVE, false, toPushDown);
fail("conflicts expected : " + StringUtil.join(expectedConflicts, ";"));
}
catch (BaseRefactoringProcessor.ConflictsInTestsException e) {
assertSameElements(e.getMessages(), expectedConflicts);
}
}
@JSTestOptions(JSTestOption.WithFlexSdk)
public void testClass() throws Exception {
doTestPushDown("Super", DocCommentPolicy.MOVE, false, "foo", "bar", "t", "uu", "v");
}
public void testSuperMethodCall() throws Exception {
doTestPushDown("Super", DocCommentPolicy.MOVE, false, "foo");
}
public void testImplements() throws Exception {
doTestPushDown("Super", DocCommentPolicy.MOVE, false, "IFoo");
}
public void testInterface() throws Exception {
doTestPushDown("ISuper", DocCommentPolicy.MOVE, false, "foo");
}
public void testAbstractize1() throws Exception {
doTestPushDown("ISuper", DocCommentPolicy.ASIS, true, "foo");
}
public void testAbstractize2() throws Exception {
doTestPushDown("ISuper", DocCommentPolicy.COPY, true, "foo");
}
public void testFromMxml() throws Exception {
doTestPushDown("Super", DocCommentPolicy.COPY, false, "foo", "IFoo", "v1", "v3", "v4", "instance");
}
public void testConflicts1() throws Exception {
String[] conflicts =
new String[]{"Property prop uses field v, which is pushed down", "Constructor Super() uses method foo(), which is pushed down",
"Method Super.i() with internal visibility won't be accessible from method foo()",
"Method Super.prv() with private visibility won't be accessible from method foo()",
"Class Aux1 with internal visibility won't be accessible from method foo()",
"Inner class Aux2 won't be accessible from method foo()"};
doTestConflicts("Super", conflicts, "foo", "v");
}
public void testProperty() throws Exception {
doTestPushDown("Super", DocCommentPolicy.ASIS, false, "opacity", "_opacity");
}
public void testConflicts2() throws Exception {
String[] conflicts =
new String[]{"Method Interface1.foo() is already overridden in class Impl. Method will not be pushed down to that class."};
doTestConflicts("Interface1", conflicts, "foo");
}
@JSTestOptions({JSTestOption.WithFlexFacet, JSTestOption.WithGumboSdk})
public void testVector() throws Exception {
doTestPushDown("foo.From", DocCommentPolicy.ASIS, false, "foo");
}
@JSTestOptions({JSTestOption.WithFlexFacet, JSTestOption.WithGumboSdk})
public void testVector2() throws Exception {
doTestPushDown("IFoo", DocCommentPolicy.ASIS, false, "abc");
}
@JSTestOptions({JSTestOption.WithFlexFacet, JSTestOption.WithGumboSdk})
public void testVector3() throws Exception {
doTestPushDown("IFoo", DocCommentPolicy.ASIS, false, "abc");
}
}