package com.intellij.flex.uiDesigner;
import com.intellij.flex.util.FlexTestUtils;
import com.intellij.flex.model.bc.BuildConfigurationNature;
import com.intellij.flex.model.bc.OutputType;
import com.intellij.flex.model.bc.TargetPlatform;
import com.intellij.flex.uiDesigner.libraries.LibraryManager;
import com.intellij.flex.uiDesigner.mxml.ProjectComponentReferenceCounter;
import com.intellij.lang.javascript.flex.projectStructure.model.impl.Factory;
import com.intellij.lang.javascript.flex.sdk.FlexSdkType2;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.progress.EmptyProgressIndicator;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.projectRoots.ProjectJdkTable;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.projectRoots.SdkModificator;
import com.intellij.openapi.projectRoots.impl.ProjectJdkImpl;
import com.intellij.openapi.roots.OrderRootType;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vfs.JarFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.xml.XmlFile;
import junit.framework.AssertionFailedError;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
abstract class AppTestBase extends FlashUIDesignerBaseTestCase {
protected TestClient client;
protected TestSocketInputHandler socketInputHandler;
protected String flexSdkRootPath;
protected final List<Pair<VirtualFile, VirtualFile>> libs = new ArrayList<>();
protected String getSourceBasePath() {
return "common";
}
private VirtualFile testDir;
protected final VirtualFile getTestDir() {
if (testDir == null) {
testDir = DesignerTests.getFile("src", getSourceBasePath());
}
return testDir;
}
protected final VirtualFile getSource(String relativePath) {
VirtualFile file = getTestDir().findFileByRelativePath(relativePath);
assertNotNull(file);
return file;
}
@Override
protected void setUpJdk() {
final String flexVersion = getFlexVersion();
flexSdkRootPath = DesignerTests.getTestDataPath() + "/lib/flex-sdk/" + flexVersion;
Flex annotation = getFlexAnnotation();
doSetupFlexSdk(myModule, flexSdkRootPath, annotation == null ? TargetPlatform.Desktop : annotation.platform(), flexVersion);
}
protected Disposable getSdkParentDisposable() {
return ApplicationManager.getApplication();
}
private void doSetupFlexSdk(final Module module, final String flexSdkRootPath, final TargetPlatform targetPlatform, final String sdkVersion) {
final String sdkName = generateSdkName(sdkVersion);
Sdk sdk = ProjectJdkTable.getInstance().findJdk(sdkName);
if (sdk == null) {
ApplicationManager.getApplication().runWriteAction(() -> {
FlexSdkType2 sdkType = FlexSdkType2.getInstance();
Sdk sdk1 = new ProjectJdkImpl(sdkName, sdkType, flexSdkRootPath, "");
ProjectJdkTable.getInstance().addJdk(sdk1);
Disposer.register(getSdkParentDisposable(), new Disposable() {
@Override
public void dispose() {
ApplicationManager.getApplication().runWriteAction(() -> {
ProjectJdkTable sdkTable = ProjectJdkTable.getInstance();
sdkTable.removeJdk(sdkTable.findJdk(sdkName));
});
}
});
final SdkModificator modificator = sdk1.getSdkModificator();
modificator.setVersionString(FlexSdkType2.getInstance().getVersionString(sdk1.getHomePath()));
modifySdk(sdk1, modificator);
modificator.commitChanges();
});
}
FlexTestUtils.modifyBuildConfiguration(module, bc -> {
bc.setNature(new BuildConfigurationNature(targetPlatform, false, getOutputType()));
bc.getDependencies().setSdkEntry(Factory.createSdkEntry(sdkName));
});
}
protected OutputType getOutputType() {
return OutputType.Application;
}
protected String generateSdkName(String sdkVersion) {
return "test-" + sdkVersion;
}
protected void modifySdk(Sdk sdk, SdkModificator sdkModificator) {
final VirtualFile sdkHome = sdk.getHomeDirectory();
assert sdkHome != null;
final VirtualFile frameworksDir = sdkHome.findChild("frameworks");
assert frameworksDir != null;
sdkModificator.addRoot(DesignerTests.getFile("lib", "playerglobal"), OrderRootType.CLASSES);
FlexSdkType2.addFlexSdkSwcRoots(sdkModificator, frameworksDir);
}
@SuppressWarnings("ConstantConditions")
protected void addLibrary(SdkModificator sdkModificator, String path) {
VirtualFile virtualFile = path.charAt(0) != '/' ? DesignerTests.getFile("lib", path) : DesignerTests.getFile(path);
VirtualFile jarFile = JarFileSystem.getInstance().getJarRootForLocalFile(virtualFile);
assert jarFile != null;
libs.add(new Pair<>(virtualFile, jarFile));
sdkModificator.addRoot(jarFile, OrderRootType.CLASSES);
}
protected String getFlexVersion() {
try {
Flex annotation = getClass().getMethod(getName()).getAnnotation(Flex.class);
if (annotation == null || annotation.version().isEmpty()) {
annotation = getClass().getAnnotation(Flex.class);
}
assert annotation != null && !annotation.version().isEmpty();
return annotation.version();
}
catch (NoSuchMethodException e) {
throw new AssertionFailedError(e.getMessage());
}
}
private Flex getFlexAnnotation() {
try {
return getClass().getMethod(getName()).getAnnotation(Flex.class);
}
catch (NoSuchMethodException e) {
throw new AssertionFailedError(e.getMessage());
}
}
protected boolean isRequireLocalStyleHolder() {
Flex annotation = getFlexAnnotation();
return annotation != null && annotation.requireLocalStyleHolder();
}
protected void assertAfterInitLibrarySets(List<XmlFile> unregisteredDocumentReferences) throws IOException {
}
protected VirtualFile[] configureByFiles(String... paths) throws Exception {
final VirtualFile[] files = new VirtualFile[paths.length];
for (int i = 0; i < paths.length; i++) {
VirtualFile file = getSource(paths[i]);
assertNotNull(file);
files[i] = file;
}
return configureByFiles(null, files, null);
}
@Override
protected VirtualFile[] configureByFiles(@Nullable VirtualFile rawProjectRoot,
VirtualFile[] files,
@Nullable VirtualFile[] auxiliaryFiles) throws Exception {
final VirtualFile[] sourceFiles = super.configureByFiles(rawProjectRoot, files, auxiliaryFiles);
launchAndInitializeApplication();
return sourceFiles;
}
private void launchAndInitializeApplication() throws Exception {
if (DesignerApplicationManager.getInstance().isApplicationClosed()) {
changeServicesImplementation();
new DesignerApplicationLauncher(myModule, new DesignerApplicationLauncher.PostTask() {
@Override
public boolean run(Module module,
ProjectComponentReferenceCounter projectComponentReferenceCounter,
ProgressIndicator indicator,
ProblemsHolder problemsHolder) {
assertTrue(DocumentProblemManager.getInstance().toString(problemsHolder.getProblems()), problemsHolder.isEmpty());
client = (TestClient)Client.getInstance();
client.flush();
try {
assertAfterInitLibrarySets(projectComponentReferenceCounter.unregistered);
}
catch (IOException e) {
throw new AssertionError(e);
}
return true;
}
}).run(new EmptyProgressIndicator());
}
else {
client = (TestClient)Client.getInstance();
ProblemsHolder problemsHolder = new ProblemsHolder();
ProjectComponentReferenceCounter projectComponentReferenceCounter = LibraryManager.getInstance().registerModule(myModule, problemsHolder, isRequireLocalStyleHolder());
assertTrue(problemsHolder.isEmpty());
assertAfterInitLibrarySets(projectComponentReferenceCounter.unregistered);
}
socketInputHandler = (TestSocketInputHandler)SocketInputHandler.getInstance();
applicationLaunchedAndInitialized();
}
protected abstract void changeServicesImplementation();
protected void applicationLaunchedAndInitialized() {
}
@Override
protected void tearDown() throws Exception {
try {
if (client != null) {
client.closeProject(myProject);
}
}
finally {
super.tearDown();
}
}
}