package org.elixir_lang.parser_definition; import com.ericsson.otp.erlang.OtpErlangObject; import com.intellij.mock.MockLocalFileSystem; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.extensions.ExtensionsArea; import com.intellij.openapi.fileTypes.FileTypeRegistry; import com.intellij.openapi.fileTypes.MockFileTypeManager; import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.progress.impl.ProgressManagerImpl; import com.intellij.openapi.project.Project; import com.intellij.openapi.projectRoots.ProjectJdkTable; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.projectRoots.impl.ProjectJdkTableImpl; import com.intellij.openapi.roots.*; import com.intellij.openapi.roots.impl.*; import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.openapi.vfs.VirtualFileSystem; import com.intellij.openapi.vfs.impl.VirtualFileManagerImpl; import com.intellij.psi.*; import com.intellij.util.messages.MessageBus; import org.elixir_lang.ElixirLanguage; import org.elixir_lang.ElixirParserDefinition; import org.elixir_lang.intellij_elixir.Quoter; import org.elixir_lang.psi.impl.ElixirPsiImplUtil; import org.elixir_lang.sdk.ElixirSdkType; import org.jetbrains.annotations.NotNull; import org.picocontainer.MutablePicoContainer; import java.io.File; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.LinkedList; import java.util.List; import static org.elixir_lang.SdkType.pathIsValidSdkHome; import static org.elixir_lang.test.ElixirVersion.elixirSdkRelease; /** * Created by luke.imhoff on 8/7/14. */ @org.junit.Ignore("abstract") public abstract class ParsingTestCase extends com.intellij.testFramework.ParsingTestCase { public ParsingTestCase() { super("", "ex", new ElixirParserDefinition()); } @NotNull protected static MessageBus messageBus(@NotNull MutablePicoContainer appContainer) { return (MessageBus) appContainer.getComponentInstanceOfType(MessageBus.class); } protected void assertParsedAndQuotedAroundError() { doTest(true); assertQuotedAroundError(); } protected void assertParsedAndQuotedAroundExit() { doTest(true); assertQuotedAroundExit(); } protected void assertParsedAndQuotedCorrectly() { doTest(true); assertWithoutLocalError(); assertQuotedCorrectly(); } protected void assertParsedWithLocalErrorAndRemoteExit() { doTest(true); assertWithLocalError(); Quoter.assertExit(myFile); } protected void assertParsedWithErrors() { doTest(true); assertWithLocalError(); Quoter.assertError(myFile); } protected void assertWithLocalError() { final FileViewProvider fileViewProvider = myFile.getViewProvider(); PsiFile root = fileViewProvider.getPsi(ElixirLanguage.INSTANCE); final List<PsiElement> errorElementList = new LinkedList<PsiElement>(); root.accept( new PsiRecursiveElementWalkingVisitor() { @Override public void visitElement(PsiElement element) { if (element instanceof PsiErrorElement) { errorElementList.add(element); } super.visitElement(element); } } ); assertTrue("No PsiErrorElements found in parsed file PSI", !errorElementList.isEmpty()); } protected void assertQuotedAroundError() { assertInstanceOf(ElixirPsiImplUtil.quote(myFile), OtpErlangObject.class); Quoter.assertError(myFile); } protected void assertQuotedAroundExit() { assertInstanceOf(ElixirPsiImplUtil.quote(myFile), OtpErlangObject.class); Quoter.assertExit(myFile); } protected void assertQuotedCorrectly() { Quoter.assertQuotedCorrectly(myFile); } protected void assertWithoutLocalError() { final FileViewProvider fileViewProvider = myFile.getViewProvider(); PsiFile root = fileViewProvider.getPsi(ElixirLanguage.INSTANCE); final List<PsiElement> errorElementList = new LinkedList<PsiElement>(); root.accept( new PsiRecursiveElementWalkingVisitor() { @Override public void visitElement(PsiElement element) { if (element instanceof PsiErrorElement) { errorElementList.add(element); } super.visitElement(element); } } ); assertTrue("PsiErrorElements found in parsed file PSI", errorElementList.isEmpty()); } @Override protected String getTestDataPath() { return "testData/org/elixir_lang/parser_definition"; } /** * Whether test is running on travis-ci. * * @return {@code true} if on Travis CI; {@code false} otherwise */ protected boolean isTravis() { String travis = System.getenv("TRAVIS"); return travis != null && travis.equals("true"); } @Override protected boolean skipSpaces() { return false; } @Override protected boolean includeRanges() { return true; } @NotNull protected MessageBus messageBus() { final MutablePicoContainer appContainer = getApplication().getPicoContainer(); return ParsingTestCase.messageBus(appContainer); } @NotNull private DirectoryIndex registerDirectoryIndex(MessageBus messageBus) throws ClassNotFoundException, InvocationTargetException, InstantiationException, NoSuchMethodException, IllegalAccessException { /* MUST be registered before DirectoryIndex because DirectoryIndexImpl.markContentRootsForRefresh calls ModuleManager.getInstance(this.myProject).getModules(); */ registerModuleManager(messageBus); DirectoryIndex directoryIndex = new DirectoryIndexImpl(myProject); myProject.registerService(DirectoryIndex.class, directoryIndex); return directoryIndex; } protected void registerProjectFileIndex() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { registerProjectFileIndex(messageBus()); } private void registerProjectFileIndex(MessageBus messageBus) throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { DirectoryIndex directoryIndex = registerDirectoryIndex(messageBus); FileTypeRegistry fileTypeRegistry = new MockFileTypeManager(); myProject.registerService( ProjectFileIndex.class, new ProjectFileIndexImpl(myProject, directoryIndex, fileTypeRegistry) ); } private void registerModuleManager(MessageBus messageBus) throws ClassNotFoundException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchMethodException { Class<?> moduleManagerComponentClass = Class.forName("com.intellij.openapi.module.impl.ModuleManagerComponent"); Constructor<?> moduleManagerComponentConstructor; ModuleManager moduleManager = null; try { // IntelliJ > 2016.3 moduleManagerComponentConstructor = moduleManagerComponentClass.getConstructor( Project.class ); moduleManager = (ModuleManager) moduleManagerComponentConstructor.newInstance(myProject); } catch (NoSuchMethodException e1) { try { // IntelliJ 2016.3 moduleManagerComponentConstructor = moduleManagerComponentClass.getConstructor( Project.class, MessageBus.class ); moduleManager = (ModuleManager) moduleManagerComponentConstructor.newInstance(myProject, messageBus); } catch (NoSuchMethodException e2) { moduleManagerComponentConstructor = moduleManagerComponentClass.getConstructor( Project.class, ProgressManager.class, MessageBus.class ); moduleManager = (ModuleManager) moduleManagerComponentConstructor.newInstance( myProject, new ProgressManagerImpl(), messageBus ); } } myProject.registerService(ModuleManager.class, moduleManager); } @NotNull protected ProjectRootManager registerProjectRootManager() { ProjectRootManager projectRootManager = new ProjectRootManagerImpl(myProject); myProject.registerService(ProjectRootManager.class, projectRootManager); return projectRootManager; } @NotNull protected ElixirSdkType registerElixirSdkType() { registerExtensionPoint( com.intellij.openapi.projectRoots.SdkType.EP_NAME, com.intellij.openapi.projectRoots.SdkType.class ); registerExtension(com.intellij.openapi.projectRoots.SdkType.EP_NAME, new ElixirSdkType()); ElixirSdkType elixirSdkType = ElixirSdkType.getInstance(); assertNotNull(elixirSdkType); return elixirSdkType; } protected void setProjectSdkFromEbinDirectory() throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { setProjectSdkFromSdkHome(sdkHomeFromEbinDirectory()); } private void setProjectSdkFromSdkHome(@NotNull String sdkHome) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { MessageBus messageBus = messageBus(); registerProjectFileIndex(messageBus); ProjectRootManager projectRootManager = registerProjectRootManager(); assertTrue(pathIsValidSdkHome(sdkHome)); registerExtensionPoint(OrderRootType.EP_NAME, OrderRootType.class); registerExtension(OrderRootType.EP_NAME, new JavadocOrderRootType()); getApplication().addComponent( VirtualFileManager.class, new VirtualFileManagerImpl( new VirtualFileSystem[]{ new MockLocalFileSystem() }, messageBus ) ); ProjectJdkTable projectJdkTable = new ProjectJdkTableImpl(); registerApplicationService(ProjectJdkTable.class, projectJdkTable); registerExtensionPoint( com.intellij.openapi.projectRoots.SdkType.EP_NAME, com.intellij.openapi.projectRoots.SdkType.class ); registerExtension(com.intellij.openapi.projectRoots.SdkType.EP_NAME, new ElixirSdkType()); Sdk sdk = ElixirSdkType.createMockSdk(sdkHome, elixirSdkRelease()); projectJdkTable.addJdk(sdk); ExtensionsArea area = Extensions.getArea(myProject); registerExtensionPoint(area, ProjectExtension.EP_NAME, ProjectExtension.class); registerExtensionPoint(FilePropertyPusher.EP_NAME, FilePropertyPusher.class); myProject.addComponent(PushedFilePropertiesUpdater.class, new PushedFilePropertiesUpdaterImpl(myProject)); projectRootManager.setProjectSdk(sdk); } @NotNull protected static String ebinDirectory() { String ebinDirectory = System.getenv("ELIXIR_EBIN_DIRECTORY"); assertNotNull("ELIXIR_EBIN_DIRECTORY is not set", ebinDirectory); return ebinDirectory; } @NotNull protected static String sdkHomeFromEbinDirectory() { return sdkHomeFromEbinDirectory(ebinDirectory()) ; } @NotNull protected static String sdkHomeFromEbinDirectory(@NotNull String ebinDirectory) { return new File(ebinDirectory) .getParentFile() .getParentFile() .getParentFile() .toString(); } }