package com.intellij.lang.javascript.flex.projectStructure.options;
import com.intellij.flex.FlexCommonUtils;
import com.intellij.flex.model.bc.*;
import com.intellij.lang.javascript.flex.FlexUtils;
import com.intellij.lang.javascript.flex.projectStructure.FlexProjectLevelCompilerOptionsHolder;
import com.intellij.lang.javascript.flex.projectStructure.model.*;
import com.intellij.lang.javascript.flex.run.FlashRunConfigurationForm;
import com.intellij.lang.javascript.flex.sdk.FlexSdkUtils;
import com.intellij.lang.javascript.flex.sdk.FlexmojosSdkType;
import com.intellij.lang.javascript.psi.ecmal4.JSClass;
import com.intellij.lang.javascript.psi.impl.PublicInheritorFilter;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.util.NullableComputable;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.ui.ListCellRendererWrapper;
import com.intellij.ui.SimpleColoredText;
import com.intellij.ui.SimpleTextAttributes;
import com.intellij.util.ArrayUtil;
import com.intellij.util.PathUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
* @author ksafonov
*/
public class BCUtils {
private static LinkageType[] FLEX_LIB_LINKAGES = {LinkageType.Default, LinkageType.Merged, LinkageType.External};
private static LinkageType[] FLEX_MOBILE_APP_LINKAGES = {LinkageType.Default};
private static LinkageType[] FLEX_WEB_OR_DESKTOP_APP_LINKAGES = {LinkageType.Default, LinkageType.Merged, LinkageType.RSL};
private static LinkageType[] AS_LINKAGES = {LinkageType.Default};
private static Logger LOG = Logger.getInstance(BCUtils.class);
public static boolean isTransitiveDependency(final LinkageType linkageType) {
return linkageType == LinkageType.Include;
}
public static String getWrapperFileName(final FlexBuildConfiguration bc) {
return FileUtil.getNameWithoutExtension(PathUtil.getFileName(bc.getActualOutputFilePath())) + ".html";
}
public static String getGeneratedAirDescriptorName(final FlexBuildConfiguration bc, final AirPackagingOptions packagingOptions) {
final String suffix = packagingOptions instanceof AirDesktopPackagingOptions
? "-descriptor.xml"
: packagingOptions instanceof AndroidPackagingOptions ? "-android-descriptor.xml"
: "-ios-descriptor.xml";
return FileUtil.getNameWithoutExtension(PathUtil.getFileName(bc.getActualOutputFilePath())) + suffix;
}
@Nullable
public static String getBCSpecifier(final FlexBuildConfiguration bc) {
if (!bc.isTempBCForCompilation()) return null;
if (isFlexUnitBC(bc)) return "flexunit";
if (isRLMTemporaryBC(bc)) return "module " + StringUtil.getShortName(bc.getMainClass());
if (isRuntimeStyleSheetBC(bc)) return PathUtil.getFileName(bc.getMainClass());
return StringUtil.getShortName(bc.getMainClass());
}
public static boolean isFlexUnitBC(final FlexBuildConfiguration bc) {
return bc.isTempBCForCompilation() && bc.getMainClass().endsWith(FlexCommonUtils.FLEX_UNIT_LAUNCHER);
}
public static boolean canHaveRLMsAndRuntimeStylesheets(final FlexBuildConfiguration bc) {
return FlexCommonUtils.canHaveRLMsAndRuntimeStylesheets(bc.getOutputType(), bc.getTargetPlatform());
}
public static boolean isRLMTemporaryBC(final FlexBuildConfiguration bc) {
return bc.isTempBCForCompilation() && bc.getOutputType() == OutputType.RuntimeLoadedModule;
}
public static boolean isRuntimeStyleSheetBC(final FlexBuildConfiguration bc) {
return bc.isTempBCForCompilation() && bc.getMainClass().toLowerCase().endsWith(".css");
}
public static boolean canHaveResourceFiles(final BuildConfigurationNature nature) {
return nature.isApp();
}
public static LinkageType[] getSuitableFrameworkLinkages(BuildConfigurationNature nature) {
return nature.pureAS
? AS_LINKAGES
: nature.isLib()
? FLEX_LIB_LINKAGES
: nature.isMobilePlatform()
? FLEX_MOBILE_APP_LINKAGES
: FLEX_WEB_OR_DESKTOP_APP_LINKAGES;
}
/**
* If <code>LinkageType.Default</code> is returned then use {@link FlexCommonUtils#getDefaultFrameworkLinkage(String, BuildConfigurationNature)} to get real value.
*
* @return <code>null</code> if entry should not be included at all
*/
@Nullable
public static LinkageType getSdkEntryLinkageType(String swcPath, FlexBuildConfiguration bc) {
final Sdk sdk = bc.getSdk();
LOG.assertTrue(sdk != null);
return FlexCommonUtils.getSdkEntryLinkageType(sdk.getHomePath(), swcPath, bc.getNature(), bc.getDependencies().getTargetPlayer(),
bc.getDependencies().getComponentSet());
}
public static boolean isApplicableForDependency(BuildConfigurationNature dependantNature, OutputType dependencyOutputType) {
if (dependantNature.isLib()) {
return dependencyOutputType == OutputType.Library;
}
else {
return true;
}
}
public static void updateAvailableTargetPlayers(Sdk currentSdk, final JComboBox targetPlayerCombo) {
if (currentSdk != null && currentSdk.getSdkType() instanceof FlexmojosSdkType) return;
final String sdkHome = currentSdk == null ? null : currentSdk.getHomePath();
final String playerFolderPath = sdkHome == null ? null : sdkHome + "/frameworks/libs/player";
if (playerFolderPath != null) {
final VirtualFile playerDir = ApplicationManager.getApplication().runWriteAction((NullableComputable<VirtualFile>)() -> {
final VirtualFile playerFolder = LocalFileSystem.getInstance().refreshAndFindFileByPath(playerFolderPath);
if (playerFolder != null && playerFolder.isDirectory()) {
playerFolder.refresh(false, true);
return playerFolder;
}
return null;
});
if (playerDir != null) {
final Collection<String> availablePlayers = new ArrayList<>(2);
FlexSdkUtils.processPlayerglobalSwcFiles(playerDir, playerglobalSwcFile -> {
availablePlayers.add(playerglobalSwcFile.getParent().getName());
return true;
});
final Object selectedItem = targetPlayerCombo.getSelectedItem();
final String[] availablePlayersArray = ArrayUtil.toStringArray(availablePlayers);
targetPlayerCombo.setModel(new DefaultComboBoxModel(availablePlayersArray));
//noinspection SuspiciousMethodCalls
if (selectedItem != null && availablePlayers.contains(selectedItem)) {
targetPlayerCombo.setSelectedItem(selectedItem);
}
else {
targetPlayerCombo.setSelectedItem(FlexCommonUtils.getMaximumVersion(availablePlayersArray));
}
}
}
else {
targetPlayerCombo.setModel(new DefaultComboBoxModel(ArrayUtil.EMPTY_STRING_ARRAY));
}
}
public static PublicInheritorFilter getMainClassFilter(@NotNull Module module,
@Nullable FlexBuildConfiguration bc,
final boolean rlm,
final boolean includeTests,
boolean caching) {
final String baseClass = rlm ? FlashRunConfigurationForm.MODULE_BASE_CLASS_NAME
: FlashRunConfigurationForm.SPRITE_CLASS_NAME;
final GlobalSearchScope filterScope = bc == null
? module.getModuleWithDependenciesAndLibrariesScope(includeTests)
: FlexUtils.getModuleWithDependenciesAndLibrariesScope(module, bc, includeTests);
return new PublicInheritorFilter(module.getProject(), baseClass, filterScope, true, caching);
}
public static boolean isValidMainClass(final Module module,
@Nullable final FlexBuildConfiguration buildConfiguration,
final JSClass clazz,
final boolean includeTests) {
return getMainClassFilter(module, buildConfiguration, false, includeTests, false).value(clazz);
}
public static SimpleColoredText renderBuildConfiguration(@NotNull FlexBuildConfiguration bc,
@Nullable String moduleName) {
return renderBuildConfiguration(bc, moduleName, false);
}
public static SimpleColoredText renderBuildConfiguration(@NotNull FlexBuildConfiguration bc,
@Nullable String moduleName,
boolean bold) {
SimpleColoredText text = new SimpleColoredText();
text.append(bc.getShortText(), bold ? SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES : SimpleTextAttributes.REGULAR_ATTRIBUTES);
text.append(" (" + bc.getDescription() + ")", SimpleTextAttributes.GRAY_ATTRIBUTES);
if (moduleName != null) {
text.append(" - " + moduleName, SimpleTextAttributes.REGULAR_ATTRIBUTES);
}
return text;
}
public static SimpleColoredText renderMissingBuildConfiguration(@NotNull String bcName, @Nullable String moduleName) {
return moduleName != null
? new SimpleColoredText(bcName + " - " + moduleName, SimpleTextAttributes.ERROR_ATTRIBUTES)
: new SimpleColoredText(bcName, SimpleTextAttributes.ERROR_ATTRIBUTES);
}
public static String suggestRLMOutputPath(final String mainClass) {
return mainClass.replace('.', '/') + ".swf";
}
public static void initTargetPlatformCombo(final JComboBox targetPlatformCombo) {
targetPlatformCombo.setModel(new DefaultComboBoxModel(TargetPlatform.values()));
targetPlatformCombo.setRenderer(new ListCellRendererWrapper<TargetPlatform>() {
public void customize(JList list, TargetPlatform value, int index, boolean selected, boolean hasFocus) {
setText(value.getPresentableText());
setIcon(value.getIcon());
}
});
}
public static void initOutputTypeCombo(final JComboBox outputTypeCombo) {
outputTypeCombo.setModel(new DefaultComboBoxModel(OutputType.values()));
outputTypeCombo.setRenderer(new ListCellRendererWrapper<OutputType>() {
public void customize(JList list, OutputType value, int index, boolean selected, boolean hasFocus) {
setText(value.getPresentableText());
}
});
}
public static List<String> getThemes(final Module module, final FlexBuildConfiguration bc) {
final Sdk sdk = bc.getSdk();
if (sdk == null) return Collections.emptyList();
final CompilerOptionInfo info = CompilerOptionInfo.getOptionInfo("compiler.theme");
String value = bc.getCompilerOptions().getOption(info.ID);
if (value == null) value = FlexBuildConfigurationManager.getInstance(module).getModuleLevelCompilerOptions().getOption(info.ID);
if (value == null) {
value = FlexProjectLevelCompilerOptionsHolder.getInstance(module.getProject()).getProjectLevelCompilerOptions().getOption(info.ID);
}
if (value == null) value = info.getDefaultValue(sdk.getVersionString(), bc.getNature(), bc.getDependencies().getComponentSet());
return value == null
? Collections.emptyList()
: StringUtil.split(FlexUtils.replacePathMacros(value, module, sdk.getHomePath()), CompilerOptionInfo.LIST_ENTRIES_SEPARATOR);
}
}