package com.intellij.flex.highlighting; import com.intellij.flex.codeInsight.FlexNavigationTest; import com.intellij.flex.model.bc.BuildConfigurationNature; import com.intellij.flex.model.bc.LinkageType; import com.intellij.flex.model.bc.OutputType; import com.intellij.flex.model.bc.TargetPlatform; import com.intellij.flex.util.FlexTestUtils; import com.intellij.ide.util.gotoByName.GotoClassModel2; import com.intellij.javascript.flex.css.FlexStylesIndexableSetContributor; import com.intellij.javascript.flex.mxml.schema.FlexSchemaHandler; import com.intellij.lang.javascript.JSDaemonAnalyzerTestCase; import com.intellij.lang.javascript.JSTestOption; import com.intellij.lang.javascript.JSTestOptions; import com.intellij.lang.javascript.flex.FlexModuleType; import com.intellij.lang.javascript.flex.projectStructure.model.*; import com.intellij.openapi.application.WriteAction; import com.intellij.openapi.module.ModifiableModuleModel; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.module.ModuleType; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.roots.ModuleRootModificationUtil; import com.intellij.openapi.util.Pair; import com.intellij.openapi.vfs.JarFileSystem; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.newvfs.impl.VfsRootAccess; import com.intellij.psi.PsiElement; import com.intellij.testFramework.PsiTestUtil; import com.intellij.util.Consumer; import com.intellij.util.ThrowableRunnable; import static com.intellij.openapi.vfs.VfsUtilCore.convertFromUrl; import static com.intellij.openapi.vfs.VfsUtilCore.urlToPath; @SuppressWarnings("ConstantConditions") public class FlexScopeTest extends JSDaemonAnalyzerTestCase { private boolean myIsAddDirToTests = false; @Override public void setUp() throws Exception { VfsRootAccess.allowRootAccess(getTestRootDisposable(), urlToPath(convertFromUrl(FlexSchemaHandler.class.getResource("z.xsd"))), urlToPath(convertFromUrl(FlexStylesIndexableSetContributor.class.getResource("FlexStyles.as")))); super.setUp(); } @Override protected ModuleType getModuleType() { return FlexModuleType.getInstance(); } @Override protected void setUpJdk() { FlexTestUtils.setupFlexSdk(myModule, getTestName(false), getClass()); } protected String getBasePath() { return "/flex_scope/"; } @Override protected String getTestDataPath() { return FlexTestUtils.getTestDataPath(""); } protected String getExtension() { return "as"; } public void testModuleLibrary() throws Exception { // classes from library are unresolved doHighlightingTest("_1"); // add dependency on missing library FlexTestUtils.addFlexLibrary(false, myModule, "moduleLib", true, getTestDataPath() + getBasePath(), "Lib", null, null); doHighlightingTest("_2"); // create another build configuration with no dependency on library FlexTestUtils.modifyConfigs(myProject, e -> { final ModifiableFlexBuildConfiguration bc = e.createConfiguration(myModule); bc.setName("Second"); }); doHighlightingTest("_2"); // switch to it final FlexBuildConfigurationManager bcManager = FlexBuildConfigurationManager.getInstance(myModule); bcManager.setActiveBuildConfiguration(bcManager.findConfigurationByName("Second")); doHighlightingTest("_1"); // switch back bcManager.setActiveBuildConfiguration(bcManager.findConfigurationByName("Unnamed")); doHighlightingTest("_2"); } public void testBcDependency() throws Exception { // module uses classes from other (non-existing) module doHighlightingTest("_1"); final Module module2 = FlexTestUtils.createModule(myProject, "module2", getVirtualFile(getBasePath() + "Module2")); // create other module, don't add dependency doHighlightingTest("_1"); ModuleRootModificationUtil.addDependency(myModule, module2); doHighlightingTest("_1"); // now add bc-to-bc dependency, highlighting should not change because app-on-app dependency is ignored WriteAction.run(() -> FlexTestUtils.modifyConfigs(myProject, editor -> { final ModifiableFlexBuildConfiguration dependentBc = editor.getConfigurations(myModule)[0]; final ModifiableFlexBuildConfiguration dependencyBc = editor.getConfigurations(module2)[0]; final ModifiableBuildConfigurationEntry dependencyEntry = editor.createBcEntry(dependentBc.getDependencies(), dependencyBc, null); dependentBc.getDependencies().getModifiableEntries().add(dependencyEntry); })); doHighlightingTest("_1"); // dependency with linkage type "Loaded" doesn't change highlighting as well FlexTestUtils.modifyConfigs(myProject, editor -> { final ModifiableFlexBuildConfiguration dependentBc = editor.getConfigurations(myModule)[0]; dependentBc.getDependencies().getModifiableEntries().get(0).getDependencyType().setLinkageType(LinkageType.LoadInRuntime); editor.getConfigurations(module2)[0].setOutputType(OutputType.RuntimeLoadedModule); }); doHighlightingTest("_1"); // app-on-lib dependency affects highlighting FlexTestUtils.modifyConfigs(myProject, editor -> { final ModifiableFlexBuildConfiguration dependentBc = editor.getConfigurations(myModule)[0]; dependentBc.getDependencies().getModifiableEntries().get(0).getDependencyType().setLinkageType(LinkageType.External); editor.getConfigurations(module2)[0].setOutputType(OutputType.Library); }); doHighlightingTest("_2"); // create another build configuration with no dependency on second BC FlexTestUtils.modifyConfigs(myProject, e -> { final ModifiableFlexBuildConfiguration bc = e.createConfiguration(myModule); bc.setName("Second"); }); doHighlightingTest("_2"); // switch to it final FlexBuildConfigurationManager bcManager = FlexBuildConfigurationManager.getInstance(myModule); bcManager.setActiveBuildConfiguration(bcManager.findConfigurationByName("Second")); doHighlightingTest("_1"); // switch back bcManager.setActiveBuildConfiguration(bcManager.findConfigurationByName("Unnamed")); doHighlightingTest("_2"); } @JSTestOptions(JSTestOption.WithFlexSdk) public void testBcDependencyInSameModule() throws Exception { WriteAction.run(() -> FlexTestUtils.modifyConfigs(myProject, editor -> { final ModifiableFlexBuildConfiguration bc1 = editor.getConfigurations(myModule)[0]; final ModifiableFlexBuildConfiguration bc2 = editor.createConfiguration(myModule); bc2.setNature(new BuildConfigurationNature(TargetPlatform.Web, false, OutputType.Library)); bc2.setName("2"); final ModifiableBuildConfigurationEntry entry = editor.createBcEntry(bc1.getDependencies(), bc2, null); bc1.getDependencies().getModifiableEntries().add(entry); })); doHighlightingTest(""); } private void doHighlightingTest(final String suffix) throws Exception { doHighlightingTest(suffix, "as"); } private void doHighlightingTest(final String suffix, String extension) throws Exception { doTest(getBasePath() + getTestName(false) + suffix + "." + extension, true, false, true); } public void testNavigationElement() throws Exception { configureByFile(getBasePath() + getTestName(false) + ".as"); Pair<Sdk, Sdk> sdks = prepareTwoSdks(); final FlexBuildConfigurationManager bcManager = FlexBuildConfigurationManager.getInstance(myModule); bcManager.setActiveBuildConfiguration(bcManager.findConfigurationByName("1")); VirtualFile sourceFile1 = LocalFileSystem.getInstance() .findFileByPath(sdks.first.getHomePath() + "/frameworks/projects/spark/src/spark/components/Application.as"); FlexNavigationTest.doTest(myEditor, sourceFile1, null, null, belongsToSdk(sdks.first)); bcManager.setActiveBuildConfiguration(bcManager.findConfigurationByName("2")); VirtualFile sourceFile2 = LocalFileSystem.getInstance() .findFileByPath(sdks.second.getHomePath() + "/frameworks/projects/spark/src/spark/components/Application.as"); FlexNavigationTest.doTest(myEditor, sourceFile2, null, null, belongsToSdk(sdks.second)); } private static Consumer<PsiElement> belongsToSdk(final Sdk sdk) { return psiElement -> { VirtualFile containingFile = psiElement.getContainingFile().getVirtualFile(); if (containingFile.getFileSystem() instanceof JarFileSystem) { containingFile = JarFileSystem.getInstance().getVirtualFileForJar(containingFile); } assertTrue(VfsUtilCore.isAncestor(sdk.getHomeDirectory(), containingFile, true)); }; } public void testGotoClass() throws Exception { prepareTwoSdks(); GotoClassModel2 model = new GotoClassModel2(myProject); Object[] elements = model.getElementsByName("Application", true, ""); assertEquals(4, elements.length); } public Pair<Sdk, Sdk> prepareTwoSdks() { final Sdk sdk1 = FlexTestUtils.createSdk(FlexTestUtils.getPathToCompleteFlexSdk("4.5"), null, true); final Sdk sdk2 = FlexTestUtils.createSdk(FlexTestUtils.getPathToCompleteFlexSdk("4.6"), null, false); WriteAction.run(() -> FlexTestUtils.modifyConfigs(myProject, editor -> { final ModifiableFlexBuildConfiguration bc1 = editor.getConfigurations(myModule)[0]; bc1.setName("1"); FlexTestUtils.setSdk(bc1, sdk1); final ModifiableFlexBuildConfiguration bc2 = editor.createConfiguration(myModule); bc2.setNature(new BuildConfigurationNature(TargetPlatform.Web, false, OutputType.Application)); bc2.setName("2"); FlexTestUtils.setSdk(bc2, sdk2); })); return Pair.create(sdk1, sdk2); } public void testCircularDependency() throws Exception { final Sdk sdk = FlexTestUtils.createSdk(FlexTestUtils.getPathToCompleteFlexSdk("4.6"), null, true); WriteAction.run(() -> { final ModifiableModuleModel m1 = ModuleManager.getInstance(myProject).getModifiableModel(); final VirtualFile moduleDir = myProject.getBaseDir().createChildDirectory(this, "module2"); final Module module2 = m1.newModule(moduleDir.getPath(), FlexModuleType.getInstance().getId()); m1.commit(); PsiTestUtil.addSourceRoot(module2, moduleDir); FlexTestUtils.modifyConfigs(myProject, editor -> { final ModifiableFlexBuildConfiguration app1 = editor.getConfigurations(myModule)[0]; app1.setName("app1"); FlexTestUtils.setSdk(app1, sdk); final ModifiableFlexBuildConfiguration lib1 = editor.getConfigurations(module2)[0]; lib1.setNature(new BuildConfigurationNature(TargetPlatform.Web, false, OutputType.Library)); app1.setName("lib1"); FlexTestUtils.setSdk(lib1, sdk); final ModifiableFlexBuildConfiguration lib2 = editor.createConfiguration(myModule); lib2.setName("lib2"); lib2.setNature(new BuildConfigurationNature(TargetPlatform.Web, false, OutputType.Library)); FlexTestUtils.setSdk(lib2, sdk); final ModifiableBuildConfigurationEntry dep1 = editor.createBcEntry(app1.getDependencies(), lib1, null); app1.getDependencies().getModifiableEntries().add(dep1); final ModifiableBuildConfigurationEntry dep2 = editor.createBcEntry(lib1.getDependencies(), lib2, null); lib1.getDependencies().getModifiableEntries().add(dep2); }); }); doHighlightingTest(""); } public void testTransitiveDependency() throws Exception { final Module module2 = FlexTestUtils.createModule(myProject, "module2", getVirtualFile(getBasePath() + "m2")); final Module module3 = FlexTestUtils.createModule(myProject, "module3", getVirtualFile(getBasePath() + "m3")); FlexTestUtils.modifyConfigs(myProject, editor -> { final ModifiableFlexBuildConfiguration bc1 = editor.getConfigurations(myModule)[0]; final ModifiableFlexBuildConfiguration bc2 = editor.getConfigurations(module2)[0]; bc2.setOutputType(OutputType.Library); final ModifiableFlexBuildConfiguration bc3 = editor.getConfigurations(module3)[0]; bc3.setOutputType(OutputType.Library); final ModifiableFlexBuildConfiguration bc3a = editor.createConfiguration(module3); bc3a.setOutputType(OutputType.Library); bc3a.setName("bc3a"); bc1.getDependencies().getModifiableEntries().add(editor.createBcEntry(bc1.getDependencies(), bc2, null)); bc2.getDependencies().getModifiableEntries().add(editor.createBcEntry(bc2.getDependencies(), bc3, null)); bc2.getDependencies().getModifiableEntries().add(editor.createBcEntry(bc2.getDependencies(), bc3a, null)); }); FlexTestUtils .addFlexLibrary(false, module2, "Flex Lib", true, FlexTestUtils.getTestDataPath("flexlib/"), "flexlib.swc", null, null); doHighlightingTest("_1"); class Test implements ThrowableRunnable<Exception> { private final LinkageType myLinkageType1; private final LinkageType myLinkageType2; private final String mySuffix; Test(LinkageType linkageType1, LinkageType linkageType2, String suffix) { myLinkageType1 = linkageType1; myLinkageType2 = linkageType2; mySuffix = suffix; } public void run() throws Exception { FlexTestUtils.modifyConfigs(myProject, editor -> { final ModifiableFlexBuildConfiguration bc = editor.getConfigurations(module2)[0]; final ModifiableDependencyEntry e1 = bc.getDependencies().getModifiableEntries().get(0); e1.getDependencyType().setLinkageType(myLinkageType1); final ModifiableDependencyEntry e2 = bc.getDependencies().getModifiableEntries().get(1); e2.getDependencyType().setLinkageType(myLinkageType2); }); doHighlightingTest(mySuffix); } } new Test(LinkageType.Default, LinkageType.Default, "_1").run(); new Test(LinkageType.External, LinkageType.Default, "_1").run(); new Test(LinkageType.Include, LinkageType.Default, "_2").run(); new Test(LinkageType.LoadInRuntime, LinkageType.Default, "_1").run(); new Test(LinkageType.Merged, LinkageType.Default, "_1").run(); new Test(LinkageType.RSL, LinkageType.Default, "_1").run(); new Test(LinkageType.RSL, LinkageType.Include, "_2").run(); new Test(LinkageType.Include, LinkageType.Include, "_2").run(); FlexTestUtils.modifyConfigs(myProject, editor -> { final ModifiableFlexBuildConfiguration bc2 = editor.getConfigurations(module2)[0]; final ModifiableDependencyEntry entry = bc2.getDependencies().getModifiableEntries().get(2); assert entry instanceof ModifiableModuleLibraryEntry; // FlexLib entry.getDependencyType().setLinkageType(LinkageType.Include); }); new Test(LinkageType.Include, LinkageType.Include, "_3").run(); } public void testTransitiveDependency2() throws Exception { final Module module2 = FlexTestUtils.createModule(myProject, "module2", getVirtualFile(getBasePath() + "m2")); final Module module3 = FlexTestUtils.createModule(myProject, "module3", getVirtualFile(getBasePath() + "m3")); FlexTestUtils.modifyConfigs(myProject, editor -> { final ModifiableFlexBuildConfiguration bc1a = editor.getConfigurations(myModule)[0]; bc1a.setName("1"); final ModifiableFlexBuildConfiguration bc1b = editor.createConfiguration(myModule); bc1b.setName("2"); final ModifiableFlexBuildConfiguration bc2a = editor.getConfigurations(module2)[0]; bc2a.setOutputType(OutputType.Library); bc2a.setName("1"); final ModifiableFlexBuildConfiguration bc2b = editor.createConfiguration(module2); bc2b.setOutputType(OutputType.Library); bc2b.setName("2"); final ModifiableFlexBuildConfiguration bc3 = editor.getConfigurations(module3)[0]; bc3.setOutputType(OutputType.Library); bc1a.getDependencies().getModifiableEntries().add(editor.createBcEntry(bc1a.getDependencies(), bc2a, null)); bc1b.getDependencies().getModifiableEntries().add(editor.createBcEntry(bc1b.getDependencies(), bc2b, null)); final ModifiableBuildConfigurationEntry entry1 = editor.createBcEntry(bc2a.getDependencies(), bc3, null); bc2a.getDependencies().getModifiableEntries().add(entry1); entry1.getDependencyType().setLinkageType(LinkageType.Include); final ModifiableBuildConfigurationEntry entry2 = editor.createBcEntry(bc2b.getDependencies(), bc3, null); bc2b.getDependencies().getModifiableEntries().add(entry2); entry2.getDependencyType().setLinkageType(LinkageType.Merged); }); final FlexBuildConfigurationManager m = FlexBuildConfigurationManager.getInstance(myModule); m.setActiveBuildConfiguration(m.findConfigurationByName("1")); doHighlightingTest("_1"); m.setActiveBuildConfiguration(m.findConfigurationByName("2")); doHighlightingTest("_2"); } public void testMissingSdk() throws Exception { final Sdk sdk = FlexTestUtils.createSdk(FlexTestUtils.getPathToCompleteFlexSdk("4.5"), null, true); FlexTestUtils.modifyConfigs(myProject, editor -> { final ModifiableFlexBuildConfiguration bc1 = editor.getConfigurations(myModule)[0]; bc1.setName("1"); FlexTestUtils.setSdk(bc1, sdk); final ModifiableFlexBuildConfiguration bc2 = editor.createConfiguration(myModule); bc2.setName("2"); bc2.getDependencies().setSdkEntry(null); }); final FlexBuildConfigurationManager m = FlexBuildConfigurationManager.getInstance(myModule); m.setActiveBuildConfiguration(m.findConfigurationByName("1")); doHighlightingTest("_1"); m.setActiveBuildConfiguration(m.findConfigurationByName("2")); doHighlightingTest("_2"); m.setActiveBuildConfiguration(m.findConfigurationByName("1")); doHighlightingTest("_1"); } public void testTestScope() throws Exception { final Sdk sdk46 = FlexTestUtils.createSdk(FlexTestUtils.getPathToCompleteFlexSdk("4.6"), null, true); final Module module2 = FlexTestUtils.createModule(myProject, "module2", getVirtualFile(getBasePath() + "m2")); final Module module3 = FlexTestUtils.createModule(myProject, "module3", getVirtualFile(getBasePath() + "m3")); FlexTestUtils.addFlexLibrary(false, myModule, "Lib", true, getTestDataPath() + getBasePath(), "Lib", null, null, LinkageType.Test); FlexTestUtils.addFlexLibrary(false, myModule, "Lib2", true, getTestDataPath() + getBasePath(), "Lib2", null, null); FlexTestUtils.addFlexLibrary(true, myModule, "Lib3", true, getTestDataPath() + getBasePath(), "Lib3", null, null, LinkageType.Test); FlexTestUtils.addFlexLibrary(true, myModule, "Lib4", true, getTestDataPath() + getBasePath(), "Lib4", null, null); FlexTestUtils.modifyConfigs(myProject, editor -> { ModifiableFlexBuildConfiguration bc1 = editor.getConfigurations(myModule)[0]; FlexTestUtils.setSdk(bc1, sdk46); ModifiableFlexBuildConfiguration bc2 = editor.getConfigurations(module2)[0]; bc2.setOutputType(OutputType.Library); ModifiableFlexBuildConfiguration bc3 = editor.getConfigurations(module3)[0]; bc3.setOutputType(OutputType.Library); ModifiableBuildConfigurationEntry entry1 = editor.createBcEntry(bc1.getDependencies(), bc2, null); entry1.getDependencyType().setLinkageType(LinkageType.Test); bc1.getDependencies().getModifiableEntries().add(entry1); ModifiableBuildConfigurationEntry entry2 = editor.createBcEntry(bc2.getDependencies(), bc3, null); entry2.getDependencyType().setLinkageType(LinkageType.Test); bc2.getDependencies().getModifiableEntries().add(entry2); }); doHighlightingTest("_1", "as", false); doHighlightingTest("_1", "mxml", false); doHighlightingTest("_2", "as", true); doHighlightingTest("_2", "mxml", true); } public void testLibraryScope() throws Exception { final Module module2 = FlexTestUtils.createModule(myProject, "module2", getVirtualFile(getBasePath() + "m2")); FlexTestUtils.addFlexLibrary(false, myModule, "Flex Lib", true, FlexTestUtils.getTestDataPath("flexlib"), "flexlib.swc", null, null); FlexTestUtils.modifyConfigs(myProject, editor -> { ModifiableFlexBuildConfiguration bc1 = editor.getConfigurations(myModule)[0]; bc1.setOutputType(OutputType.Library); ModifiableFlexBuildConfiguration bc2 = editor.getConfigurations(module2)[0]; ModifiableBuildConfigurationEntry entry1 = editor.createBcEntry(bc2.getDependencies(), bc1, null); bc2.getDependencies().getModifiableEntries().add(entry1); }); doHighlightingTest(""); } private void doHighlightingTest(String suffix, String extension, boolean testFolder) throws Exception { boolean b = myIsAddDirToTests; try { myIsAddDirToTests = testFolder; doHighlightingTest(suffix, extension); } finally { myIsAddDirToTests = b; } } @Override protected boolean isAddDirToTests() { return myIsAddDirToTests; } }