package com.intellij.lang.javascript.flex.flashbuilder;
import com.intellij.flex.FlexCommonUtils;
import com.intellij.flex.model.bc.*;
import com.intellij.lang.javascript.flex.FlexModuleBuilder;
import com.intellij.lang.javascript.flex.library.FlexLibraryProperties;
import com.intellij.lang.javascript.flex.library.FlexLibraryType;
import com.intellij.lang.javascript.flex.projectStructure.model.FlexBuildConfiguration;
import com.intellij.lang.javascript.flex.projectStructure.model.ModifiableBuildConfigurationEntry;
import com.intellij.lang.javascript.flex.projectStructure.model.ModifiableFlexBuildConfiguration;
import com.intellij.lang.javascript.flex.projectStructure.model.ModifiableModuleLibraryEntry;
import com.intellij.lang.javascript.flex.projectStructure.model.impl.Factory;
import com.intellij.lang.javascript.flex.projectStructure.model.impl.FlexProjectConfigurationEditor;
import com.intellij.lang.javascript.flex.projectStructure.options.BCUtils;
import com.intellij.lang.javascript.flex.projectStructure.ui.CreateHtmlWrapperTemplateDialog;
import com.intellij.lang.javascript.flex.sdk.FlexSdkUtils;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.PathMacros;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.impl.ProjectMacrosUtil;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.ContentEntry;
import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.roots.ModuleRootModel;
import com.intellij.openapi.roots.OrderRootType;
import com.intellij.openapi.roots.impl.libraries.LibraryEx;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.roots.libraries.LibraryTable;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.io.FileUtilRt;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.*;
import com.intellij.util.Function;
import com.intellij.util.SystemProperties;
import com.intellij.util.containers.ContainerUtil;
import gnu.trove.THashMap;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
import java.util.*;
public class FlashBuilderModuleImporter {
private static final String CORE_RESOURCES_PREFS_REL_PATH =
"/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.core.resources.prefs";
private static final String PATHVARIABLE_DOT = "pathvariable.";
private static final String SDK_THEMES_DIR_MACRO = "${SDK_THEMES_DIR}";
private static final String EXTERNAL_THEME_DIR_MACRO = "${EXTERNAL_THEME_DIR}";
private static final String EXTERNAL_THEME_DIR_REL_PATH = SystemInfo.isWindows
? "/AppData/Roaming/Adobe/Flash Builder/Themes"
: "/Library/Application Support/Adobe/Flash Builder/Themes";
private final Project myIdeaProject;
private FlexProjectConfigurationEditor myFlexConfigEditor;
private final Collection<FlashBuilderProject> myAllFBProjects;
private final FlashBuilderSdkFinder mySdkFinder;
private final Set<String> myPathVariables;
private boolean myPathVariablesInitialized = false;
public FlashBuilderModuleImporter(final Project ideaProject,
final FlexProjectConfigurationEditor flexConfigEditor,
final Collection<FlashBuilderProject> allFBProjects,
final FlashBuilderSdkFinder sdkFinder) {
myIdeaProject = ideaProject;
myFlexConfigEditor = flexConfigEditor;
myAllFBProjects = allFBProjects;
mySdkFinder = sdkFinder;
myPathVariables = new THashSet<>();
for (final FlashBuilderProject flashBuilderProject : allFBProjects) {
myPathVariables.addAll(flashBuilderProject.getUsedPathVariables());
}
}
public void setupModule(final ModifiableRootModel rootModel, final FlashBuilderProject flashBuilderProject) {
setupRoots(rootModel, flashBuilderProject);
setupBuildConfigs(rootModel, flashBuilderProject);
}
private void setupBuildConfigs(final ModuleRootModel rootModel, final FlashBuilderProject fbProject) {
final Sdk sdk = fbProject.isSdkUsed() ? mySdkFinder.findSdk(fbProject) : null;
final ModifiableFlexBuildConfiguration[] configurations = myFlexConfigEditor.getConfigurations(rootModel.getModule());
assert configurations.length == 1;
final ModifiableFlexBuildConfiguration mainBC = configurations[0];
final String bcName = suggestMainBCName(fbProject);
mainBC.setName(bcName);
final TargetPlatform targetPlatform = fbProject.getTargetPlatform();
mainBC.setTargetPlatform(targetPlatform);
mainBC.setPureAs(fbProject.isPureActionScript());
mainBC.setOutputType(fbProject.getOutputType());
final Map<String, String> compilerOptions = new THashMap<>();
if (fbProject.getOutputType() == OutputType.Application) {
mainBC.setMainClass(fbProject.getMainAppClassName());
final String shortClassName = StringUtil.getShortName(fbProject.getMainAppClassName());
mainBC.setOutputFileName(shortClassName + ".swf");
// todo dependencies.setComponentSet();
if (!mainBC.isPureAs() && fbProject.getThemeDirPathRaw() != null && sdk != null) {
setupTheme(fbProject.getThemeDirPathRaw(), mainBC.getNature(), sdk, mainBC.getDependencies().getComponentSet(), compilerOptions);
}
switch (targetPlatform) {
case Web:
if (fbProject.isUseHtmlWrapper()) {
mainBC.setUseHtmlWrapper(true);
mainBC.setWrapperTemplatePath(fbProject.getProjectRootPath() + "/" + CreateHtmlWrapperTemplateDialog.HTML_TEMPLATE_FOLDER_NAME);
}
break;
case Desktop:
setupAirDescriptor(mainBC, rootModel);
mainBC.getAirDesktopPackagingOptions().setPackageFileName(shortClassName);
if (!StringUtil.isEmpty(fbProject.getDesktopCertPath())) {
mainBC.getAirDesktopPackagingOptions().getSigningOptions().setUseTempCertificate(false);
mainBC.getAirDesktopPackagingOptions().getSigningOptions().setKeystorePath(fbProject.getDesktopCertPath());
}
FilesToPackageUtil
.setupFilesToPackage(mainBC.getAirDesktopPackagingOptions(), fbProject.getPathsExcludedFromDesktopPackaging(), rootModel);
break;
case Mobile:
setupAirDescriptor(mainBC, rootModel);
mainBC.getAndroidPackagingOptions().setEnabled(fbProject.isAndroidSupported());
mainBC.getAndroidPackagingOptions().setPackageFileName(shortClassName);
if (!StringUtil.isEmpty(fbProject.getAndroidCertPath())) {
mainBC.getAndroidPackagingOptions().getSigningOptions().setUseTempCertificate(false);
mainBC.getAndroidPackagingOptions().getSigningOptions().setKeystorePath(fbProject.getAndroidCertPath());
}
FilesToPackageUtil
.setupFilesToPackage(mainBC.getAndroidPackagingOptions(), fbProject.getPathsExcludedFromAndroidPackaging(), rootModel);
mainBC.getIosPackagingOptions().setEnabled(fbProject.isIosSupported());
mainBC.getIosPackagingOptions().setPackageFileName(shortClassName);
mainBC.getIosPackagingOptions().getSigningOptions()
.setProvisioningProfilePath(StringUtil.notNullize(fbProject.getIOSProvisioningPath()));
mainBC.getIosPackagingOptions().getSigningOptions().setKeystorePath(StringUtil.notNullize(fbProject.getIOSCertPath()));
FilesToPackageUtil.setupFilesToPackage(mainBC.getIosPackagingOptions(), fbProject.getPathsExcludedFromIOSPackaging(), rootModel);
break;
}
}
else {
mainBC.setOutputFileName(fbProject.getName() + ".swc");
}
mainBC.setOutputFolder(getAbsolutePathWithLinksHandled(fbProject, fbProject.getOutputFolderPath()));
setupRLMsAndCSSFilesToCompile(mainBC, fbProject);
if (sdk != null) {
mainBC.getDependencies().setSdkEntry(Factory.createSdkEntry(sdk.getName()));
final String sdkHome = sdk.getHomePath();
if (targetPlatform == TargetPlatform.Web && sdkHome != null) {
mainBC.getDependencies().setTargetPlayer(FlexSdkUtils.getTargetPlayer(fbProject.getTargetPlayerVersion(), sdkHome));
}
}
// todo dependencies.setFrameworkLinkage();
setupDependencies(mainBC, fbProject);
final String fbOptions = fbProject.getAdditionalCompilerOptions();
setupLocales(fbOptions, compilerOptions);
setupNamespacesAndManifests(rootModel, fbProject, compilerOptions);
setupFilesToIncludeInSwc(rootModel, mainBC, fbProject.getFilesIncludedInSwc());
mainBC.getCompilerOptions().setAllOptions(compilerOptions);
// todo parse options, replace "-a b" to "-a=b", move some to dedicated fields
final String ideaOptions = FlexCommonUtils.removeOptions(fbOptions, "locale", "compiler.locale", "source-path", "compiler.source-path");
mainBC.getCompilerOptions().setAdditionalOptions(ideaOptions);
if (mainBC.getOutputType() == OutputType.Application) {
FlexModuleBuilder.createRunConfiguration(rootModel.getModule(), mainBC);
}
setupOtherAppsAndModules(rootModel, mainBC, fbProject);
}
private void setupRLMsAndCSSFilesToCompile(final ModifiableFlexBuildConfiguration mainBC, final FlashBuilderProject fbProject) {
if (BCUtils.canHaveRLMsAndRuntimeStylesheets(mainBC) && !fbProject.getCssFilesToCompile().isEmpty()) {
final Collection<String> cssPaths = new ArrayList<>();
for (final String path : fbProject.getCssFilesToCompile()) {
final String cssPath = getAbsolutePathWithLinksHandled(fbProject, path);
final VirtualFile cssFile = LocalFileSystem.getInstance().findFileByPath(cssPath);
if (cssFile != null) {
cssPaths.add(cssFile.getPath());
}
else if (ApplicationManager.getApplication().isUnitTestMode()) {
cssPaths.add(cssPath);
}
}
mainBC.setCssFilesToCompile(cssPaths);
}
}
private static void setupLocales(final String fbOptions, final Map<String, String> compilerOptions) {
final List<String> locales = FlexCommonUtils.getOptionValues(fbOptions, "locale", "compiler.locale");
final StringBuilder localesBuf = new StringBuilder();
for (String locale : locales) {
if (localesBuf.length() > 0) {
localesBuf.append(CompilerOptionInfo.LIST_ENTRIES_SEPARATOR);
}
localesBuf.append(locale);
}
compilerOptions.put("compiler.locale", localesBuf.toString());
}
private void setupNamespacesAndManifests(final ModuleRootModel rootModel,
final FlashBuilderProject fbProject,
final Map<String, String> compilerOptions) {
if (!fbProject.getNamespacesAndManifestPaths().isEmpty()) {
final StringBuilder nsBuf = new StringBuilder();
for (Pair<String, String> nsAndManifestPath : fbProject.getNamespacesAndManifestPaths()) {
final String manifestPath = nsAndManifestPath.second;
VirtualFile manifestFile = null;
for (final VirtualFile sourceRoot : rootModel.getSourceRoots()) {
if ((manifestFile = sourceRoot.findFileByRelativePath(manifestPath)) != null) {
break;
}
}
final String resolvedManifestPath = manifestFile != null ? manifestFile.getPath()
: getAbsolutePathWithLinksHandled(fbProject, manifestPath);
if (nsBuf.length() > 0) {
nsBuf.append(CompilerOptionInfo.LIST_ENTRIES_SEPARATOR);
}
nsBuf.append(nsAndManifestPath.first).append(CompilerOptionInfo.LIST_ENTRY_PARTS_SEPARATOR);
nsBuf.append(resolvedManifestPath);
}
compilerOptions.put("compiler.namespaces.namespace", nsBuf.toString());
}
}
private static void setupFilesToIncludeInSwc(final ModuleRootModel rootModel,
final ModifiableFlexBuildConfiguration bc,
final Collection<String> paths) {
if (bc.getOutputType() == OutputType.Library) {
bc.getCompilerOptions().setFilesToIncludeInSWC(ContainerUtil.mapNotNull(paths, path -> {
for (VirtualFile srcRoot : rootModel.getSourceRoots()) {
final VirtualFile assetFile = LocalFileSystem.getInstance().findFileByPath(srcRoot.getPath() + "/" + path);
if (assetFile != null) {
return assetFile.getPath();
}
}
return null;
}));
}
}
private static void setupTheme(final String themeDirPathRaw,
final BuildConfigurationNature nature,
final Sdk sdk,
final ComponentSet componentSet,
final Map<String, String> compilerOptions) {
String themeDirPath = null;
if (themeDirPathRaw.startsWith(EXTERNAL_THEME_DIR_MACRO)) {
themeDirPath =
SystemProperties.getUserHome() + EXTERNAL_THEME_DIR_REL_PATH + themeDirPathRaw.substring(EXTERNAL_THEME_DIR_MACRO.length());
}
else if (themeDirPathRaw.startsWith(SDK_THEMES_DIR_MACRO)) {
themeDirPath = sdk.getHomePath() + themeDirPathRaw.substring(SDK_THEMES_DIR_MACRO.length());
}
if (themeDirPath != null) {
final File themeDir = new File(themeDirPath);
if (themeDir.isDirectory()) {
final String themeFilePath = findThemeFilePath(themeDir);
if (themeFilePath != null) {
final String themePathWithMacro = themeFilePath.replace(sdk.getHomePath(), CompilerOptionInfo.FLEX_SDK_MACRO);
if ("${SDK_THEMES_DIR}/frameworks/themes/Halo".equals(themeDirPathRaw)) {
compilerOptions.put("compiler.theme", themePathWithMacro);
}
else if ("${SDK_THEMES_DIR}/frameworks/themes/AeonGraphical".equals(themeDirPathRaw)) {
final String haloTheme = CompilerOptionInfo.FLEX_SDK_MACRO + "/frameworks/themes/Halo/halo.swc";
compilerOptions.put("compiler.theme", haloTheme + CompilerOptionInfo.LIST_ENTRIES_SEPARATOR + themePathWithMacro);
}
else {
final CompilerOptionInfo themeInfo = CompilerOptionInfo.getOptionInfo("compiler.theme");
final String defaultTheme = themeInfo.getDefaultValue(sdk.getVersionString(), nature, componentSet);
if (defaultTheme.isEmpty()) {
compilerOptions.put("compiler.theme", themePathWithMacro);
}
else {
compilerOptions.put("compiler.theme", defaultTheme + CompilerOptionInfo.LIST_ENTRIES_SEPARATOR + themePathWithMacro);
}
}
}
}
}
}
@Nullable
private static String findThemeFilePath(final File themeDir) {
final String fileName = ContainerUtil.find(themeDir.list(),
path -> FileUtilRt.extensionEquals(path, "css") || FileUtilRt.extensionEquals(path, "swc"));
return fileName == null ? null : FileUtil.toSystemIndependentName(themeDir + "/" + fileName);
}
private static void setupAirDescriptor(final ModifiableFlexBuildConfiguration bc, final ModuleRootModel rootModel) {
if (bc.getTargetPlatform() == TargetPlatform.Desktop) {
bc.getAirDesktopPackagingOptions().setUseGeneratedDescriptor(true);
}
else {
bc.getAndroidPackagingOptions().setUseGeneratedDescriptor(true);
bc.getIosPackagingOptions().setUseGeneratedDescriptor(true);
}
final String descriptorRelPath = bc.getMainClass().replace('.', '/') + "-app.xml";
for (VirtualFile srcRoot : rootModel.getSourceRoots()) {
if (srcRoot.findFileByRelativePath(descriptorRelPath) != null) {
if (bc.getTargetPlatform() == TargetPlatform.Desktop) {
bc.getAirDesktopPackagingOptions().setUseGeneratedDescriptor(false);
bc.getAirDesktopPackagingOptions().setCustomDescriptorPath(srcRoot.getPath() + "/" + descriptorRelPath);
}
else {
bc.getAndroidPackagingOptions().setUseGeneratedDescriptor(false);
bc.getAndroidPackagingOptions().setCustomDescriptorPath(srcRoot.getPath() + "/" + descriptorRelPath);
bc.getIosPackagingOptions().setUseGeneratedDescriptor(false);
bc.getIosPackagingOptions().setCustomDescriptorPath(srcRoot.getPath() + "/" + descriptorRelPath);
}
break;
}
}
}
private void setupOtherAppsAndModules(final ModuleRootModel rootModel,
final ModifiableFlexBuildConfiguration mainBC,
final FlashBuilderProject fbProject) {
final Collection<ModifiableFlexBuildConfiguration> allApps = new ArrayList<>();
allApps.add(mainBC);
for (String mainClass : fbProject.getApplicationClassNames()) {
final ModifiableFlexBuildConfiguration bc = myFlexConfigEditor.copyConfiguration(mainBC, mainBC.getNature());
final String shortClassName = StringUtil.getShortName(mainClass);
bc.setName(shortClassName);
bc.setMainClass(mainClass);
bc.setOutputFileName(shortClassName + ".swf");
if (bc.getTargetPlatform() == TargetPlatform.Desktop) {
setupAirDescriptor(bc, rootModel);
bc.getAirDesktopPackagingOptions().setPackageFileName(shortClassName);
}
if (bc.getTargetPlatform() == TargetPlatform.Mobile) {
setupAirDescriptor(bc, rootModel);
bc.getAndroidPackagingOptions().setPackageFileName(shortClassName);
bc.getIosPackagingOptions().setPackageFileName(shortClassName);
}
FlexModuleBuilder.createRunConfiguration(rootModel.getModule(), bc);
allApps.add(bc);
}
if (BCUtils.canHaveRLMsAndRuntimeStylesheets(mainBC)) {
setupModules(rootModel, allApps, fbProject);
}
}
private void setupModules(final ModuleRootModel rootModel,
final Collection<ModifiableFlexBuildConfiguration> apps,
final FlashBuilderProject fbProject) {
for (final FlashBuilderProject.FBRLMInfo rlm : fbProject.getModules()) {
ModifiableFlexBuildConfiguration hostApp = apps.iterator().next();
if (rlm.OPTIMIZE) {
final String hostAppMainClass = getMainClassFqn(fbProject, rlm.OPTIMIZE_FOR, rootModel.getSourceRootUrls());
for (ModifiableFlexBuildConfiguration appBC : apps) {
if (hostAppMainClass.equals(appBC.getMainClass())) {
hostApp = appBC;
break;
}
}
}
final Collection<FlexBuildConfiguration.RLMInfo> rlms = new ArrayList<>(hostApp.getRLMs());
final String rlmMainClass = getMainClassFqn(fbProject, rlm.MAIN_CLASS_PATH, rootModel.getSourceRootUrls());
rlms.add(new FlexBuildConfiguration.RLMInfo(rlmMainClass, rlm.OUTPUT_PATH, rlm.OPTIMIZE));
hostApp.setRLMs(rlms);
}
}
private static String suggestMainBCName(final FlashBuilderProject fbProject) {
return fbProject.getOutputType() == OutputType.Application && !fbProject.getMainAppClassName().isEmpty()
? StringUtil.getShortName(fbProject.getMainAppClassName())
: fbProject.getName();
}
private String getMainClassFqn(final FlashBuilderProject flashBuilderProject,
final String mainClassPath,
final String[] sourceRootUrls) {
final String mainClassPathUrl = VfsUtilCore.pathToUrl(getAbsolutePathWithLinksHandled(flashBuilderProject, mainClassPath));
for (final String sourceRootUrl : sourceRootUrls) {
if (mainClassPathUrl.startsWith(sourceRootUrl + "/")) {
return FlashBuilderProjectLoadUtil.getClassName(mainClassPathUrl.substring(sourceRootUrl.length() + 1));
}
}
return FlashBuilderProjectLoadUtil.getClassName(mainClassPathUrl.substring(mainClassPathUrl.lastIndexOf('/') + 1));
}
private void setupRoots(final ModifiableRootModel rootModel, final FlashBuilderProject fbProject) {
final String mainContentEntryUrl = VfsUtilCore.pathToUrl(fbProject.getProjectRootPath());
final ContentEntry mainContentEntry = rootModel.addContentEntry(mainContentEntryUrl);
final Collection<ContentEntry> otherContentEntries = new ArrayList<>();
final Collection<String> sourcePaths = fbProject.getSourcePaths();
if (sourcePaths.isEmpty()) {
final VirtualFile contentRoot = mainContentEntry.getFile();
final String mainClass = fbProject.getMainAppClassName();
if (contentRoot != null &&
!StringUtil.isEmpty(mainClass) &&
(contentRoot.findChild(mainClass + ".mxml") != null || contentRoot.findChild(mainClass + ".as") != null)) {
mainContentEntry.addSourceFolder(mainContentEntry.getUrl(), false);
}
}
else {
final List<String> locales = FlexCommonUtils.getOptionValues(fbProject.getAdditionalCompilerOptions(), "locale", "compiler.locale");
final List<String> moreSourcePaths =
FlexCommonUtils.getOptionValues(fbProject.getAdditionalCompilerOptions(), "source-path", "compiler.source-path");
for (final String rawSourcePath : sourcePaths) {
if (rawSourcePath.contains(FlexCommonUtils.LOCALE_TOKEN)) {
for (String locale : locales) {
handleRawSourcePath(rootModel, fbProject, mainContentEntryUrl, mainContentEntry, otherContentEntries,
rawSourcePath.replace(FlexCommonUtils.LOCALE_TOKEN, locale));
}
}
else {
handleRawSourcePath(rootModel, fbProject, mainContentEntryUrl, mainContentEntry, otherContentEntries, rawSourcePath);
}
}
for (String sourcePath : moreSourcePaths) {
if (sourcePath.contains(FlexCommonUtils.LOCALE_TOKEN)) {
for (String locale : locales) {
final String path = getPathToSourceRootSetInAdditionalOptions(sourcePath.replace(FlexCommonUtils.LOCALE_TOKEN, locale),
mainContentEntryUrl, mainContentEntry);
if (path != null) {
handleRawSourcePath(rootModel, fbProject, mainContentEntryUrl, mainContentEntry, otherContentEntries, path);
}
}
}
else {
final String path = getPathToSourceRootSetInAdditionalOptions(sourcePath, mainContentEntryUrl, mainContentEntry);
if (path != null) {
handleRawSourcePath(rootModel, fbProject, mainContentEntryUrl, mainContentEntry, otherContentEntries, path);
}
}
}
}
}
@Nullable
private static String getPathToSourceRootSetInAdditionalOptions(final String rawPath,
final String mainContentEntryUrl,
final ContentEntry mainContentEntry) {
// sourcePath can be absolute or relative to project root or relative to main source root
String path = rawPath;
if (new File(path).isDirectory()) return path;
path = VfsUtilCore.urlToPath(mainContentEntryUrl) + "/" + rawPath;
if (new File(path).isDirectory()) return path;
if (mainContentEntry.getSourceFolders().length > 0) {
path = VfsUtilCore.urlToPath(mainContentEntry.getSourceFolders()[0].getUrl()) + "/" + rawPath;
if (new File(path).isDirectory()) return path;
}
return null;
}
private void handleRawSourcePath(final ModifiableRootModel rootModel,
final FlashBuilderProject fbProject,
final String mainContentEntryUrl,
final ContentEntry mainContentEntry,
final Collection<ContentEntry> otherContentEntries,
final String rawSourcePath) {
final String sourcePath = getAbsolutePathWithLinksHandled(fbProject, rawSourcePath);
final String sourceUrl = VfsUtilCore.pathToUrl(sourcePath);
if (FileUtil.isAncestor(new File(VfsUtilCore.urlToPath(mainContentEntryUrl)), new File(VfsUtilCore.urlToPath(sourceUrl)), false)) {
addSourceRoot(mainContentEntry, sourceUrl);
}
else {
for (final ContentEntry otherContentEntry : otherContentEntries) {
if (FileUtil.isAncestor(new File(VfsUtilCore.urlToPath(mainContentEntryUrl)), new File(VfsUtilCore.urlToPath(sourceUrl)), false)) {
addSourceRoot(otherContentEntry, sourceUrl);
return;
}
}
final ContentEntry newContentEntry = rootModel.addContentEntry(sourceUrl);
addSourceRoot(newContentEntry, sourceUrl);
otherContentEntries.add(newContentEntry);
}
}
private static void addSourceRoot(final ContentEntry contentEntry, final String sourceUrl) {
final VirtualFile srcDir = LocalFileSystem.getInstance().findFileByPath(VfsUtilCore.urlToPath(sourceUrl));
final Ref<Boolean> testClassesFound = Ref.create(false);
final Ref<Boolean> nonTestClassesFound = Ref.create(false);
if (srcDir != null && !"src".equals(srcDir.getName())) {
VfsUtilCore.visitChildrenRecursively(srcDir, new VirtualFileVisitor() {
@NotNull
public Result visitFileEx(@NotNull final VirtualFile file) {
if (nonTestClassesFound.get()) {
return SKIP_CHILDREN;
}
if (file.isDirectory()) {
if ("flexUnitTests".equals(file.getName())) {
testClassesFound.set(true);
return SKIP_CHILDREN;
}
return CONTINUE;
}
else {
final String ext = StringUtil.notNullize(file.getExtension()).toLowerCase();
if ("mxml".equals(ext) || "fxg".equals(ext)) {
nonTestClassesFound.set(true);
}
else if ("as".equals(ext)) {
if (file.getNameWithoutExtension().endsWith("Test") || file.getName().contains("Test") && file.getName().contains("Suite")) {
testClassesFound.set(true);
}
else {
nonTestClassesFound.set(true);
}
}
return CONTINUE;
}
}
});
}
final boolean isTest = testClassesFound.get() && !nonTestClassesFound.get();
contentEntry.addSourceFolder(sourceUrl, isTest);
}
private void setupDependencies(final ModifiableFlexBuildConfiguration bc, final FlashBuilderProject fbProject) {
OUTER:
for (final String libraryPathOrig : fbProject.getLibraryPaths()) {
for (FlashBuilderProject otherProject : myAllFBProjects) {
if (otherProject != fbProject && libraryPathOrig.startsWith("/" + otherProject.getName() + "/")) {
final ModifiableBuildConfigurationEntry bcEntry =
myFlexConfigEditor.createBcEntry(bc.getDependencies(), otherProject.getName(), suggestMainBCName(otherProject));
bc.getDependencies().getModifiableEntries().add(0, bcEntry);
continue OUTER;
}
}
final LibraryTable.ModifiableModel libraryModel = myFlexConfigEditor.getLibraryModel(bc.getDependencies());
final Library library = libraryModel.createLibrary(null, FlexLibraryType.FLEX_LIBRARY);
final LibraryEx.ModifiableModelEx libraryModifiableModel = ((LibraryEx.ModifiableModelEx)library.getModifiableModel());
final String libraryId = UUID.randomUUID().toString();
libraryModifiableModel.setProperties(new FlexLibraryProperties(libraryId));
final String libraryPath = getAbsolutePathWithLinksHandled(fbProject, libraryPathOrig);
if (libraryPath.toLowerCase().endsWith(".swc") || libraryPath.toLowerCase().endsWith(".ane")) {
libraryModifiableModel.addRoot(VirtualFileManager.constructUrl(JarFileSystem.PROTOCOL, libraryPath) + JarFileSystem.JAR_SEPARATOR,
OrderRootType.CLASSES);
}
else {
libraryModifiableModel.addJarDirectory(VfsUtilCore.pathToUrl(libraryPath), false);
}
for (final String librarySourcePath : fbProject.getLibrarySourcePaths(libraryPathOrig)) {
libraryModifiableModel.addRoot(VfsUtilCore.pathToUrl(getAbsolutePathWithLinksHandled(fbProject, librarySourcePath)),
OrderRootType.SOURCES);
}
ApplicationManager.getApplication().runWriteAction(() -> libraryModifiableModel.commit());
final ModifiableModuleLibraryEntry libraryEntry = myFlexConfigEditor.createModuleLibraryEntry(bc.getDependencies(), libraryId);
libraryEntry.getDependencyType().setLinkageType(LinkageType.Merged); // todo set correct linkage!
bc.getDependencies().getModifiableEntries().add(libraryEntry);
}
}
/**
* First call of this method should be later than mySdkFinder.findSdk()
*/
private String getAbsolutePathWithLinksHandled(final FlashBuilderProject project, final String path) {
if (!myPathVariablesInitialized) {
initPathVariables();
myPathVariablesInitialized = true;
}
final int slashIndex = path.indexOf('/');
final String potentialLink = slashIndex >= 0 ? path.substring(0, slashIndex) : path;
if (potentialLink.startsWith("${") && potentialLink.endsWith("}")) {
final String pathVarName = potentialLink.substring(2, potentialLink.length() - 1);
final PathMacros pathMacros = PathMacros.getInstance();
final String pathValue = pathMacros.getValue(pathVarName);
if (pathValue != null) {
return pathValue + (slashIndex >= 0 ? path.substring(slashIndex) : "");
}
else {
return "$" + pathVarName + "$" + (slashIndex >= 0 ? path.substring(slashIndex) : "");
}
}
else {
final Map<String, String> linkedResources = project.getLinkedResources();
if (!linkedResources.isEmpty()) {
final String linkValue = linkedResources.get(potentialLink);
if (linkValue != null) {
final PathMacros pathMacros = PathMacros.getInstance();
if (pathMacros.getValue(potentialLink) == null) {
pathMacros.setMacro(potentialLink, linkValue);
}
return linkValue + (slashIndex >= 0 ? path.substring(slashIndex) : "");
}
}
}
final boolean absolute = FileUtil.isAbsolute(path) && (SystemInfo.isWindows || new File(path).exists());
return absolute ? path : project.getProjectRootPath() + (slashIndex == 0 ? "" : "/") + path;
}
private void initPathVariables() {
final PathMacros pathMacros = PathMacros.getInstance();
final Map<String, String> myEclipsePathVariables = loadEclipsePathVariables(mySdkFinder.getWorkspacePath());
for (final String pathVariable : myPathVariables) {
final String pathValue = myEclipsePathVariables.get(pathVariable);
if (pathValue != null) {
pathMacros.setMacro(pathVariable, pathValue);
}
}
ProjectMacrosUtil.checkNonIgnoredMacros(myIdeaProject, myPathVariables);
}
private static Map<String, String> loadEclipsePathVariables(final String workspacePath) {
final Map<String, String> eclipsePathVariables = new THashMap<>();
final VirtualFile prefsFile = LocalFileSystem.getInstance().findFileByPath(workspacePath + CORE_RESOURCES_PREFS_REL_PATH);
if (prefsFile == null) return eclipsePathVariables;
final Properties properties = new Properties();
try {
properties.load(prefsFile.getInputStream());
for (final Map.Entry<Object, Object> entry : properties.entrySet()) {
final String key = (String)entry.getKey();
if (key.startsWith(PATHVARIABLE_DOT)) {
eclipsePathVariables.put(key.substring(PATHVARIABLE_DOT.length()), (String)entry.getValue());
}
}
}
catch (IOException e) {/*ignore*/}
return eclipsePathVariables;
}
}