| package org.jetbrains.android.sdk; |
| |
| import com.intellij.codeInsight.navigation.actions.GotoDeclarationAction; |
| import com.intellij.openapi.editor.LogicalPosition; |
| import com.intellij.openapi.projectRoots.ProjectJdkTable; |
| import com.intellij.openapi.projectRoots.Sdk; |
| import com.intellij.openapi.projectRoots.SdkModificator; |
| import com.intellij.openapi.roots.*; |
| import com.intellij.openapi.util.io.FileUtil; |
| import com.intellij.openapi.vfs.JarFileSystem; |
| import com.intellij.openapi.vfs.LocalFileSystem; |
| import com.intellij.openapi.vfs.VirtualFile; |
| import com.intellij.psi.JavaPsiFacade; |
| import com.intellij.psi.PsiClass; |
| import com.intellij.psi.PsiElement; |
| import com.intellij.psi.PsiFile; |
| import com.intellij.psi.search.GlobalSearchScope; |
| import com.intellij.psi.xml.XmlAttributeValue; |
| import org.jetbrains.android.AndroidSdkResolveScopeProvider; |
| import org.jetbrains.android.AndroidTestCase; |
| import org.jetbrains.android.augment.AndroidPsiElementFinder; |
| import org.jetbrains.android.dom.wrappers.FileResourceElementWrapper; |
| import org.jetbrains.android.dom.wrappers.LazyValueResourceElementWrapper; |
| import org.jetbrains.annotations.NonNls; |
| import org.jetbrains.annotations.Nullable; |
| |
| /** |
| * @author Eugene.Kudelevsky |
| */ |
| public class AndroidSdkSourcesBrowsingTest extends AndroidTestCase { |
| @NonNls private static final String BASE_PATH = "sdkSourcesBrowsing/"; |
| @NonNls private static final String SDK_SOURCES_PATH_PREFIX = '/' + BASE_PATH + "sdk_sources_"; |
| @NonNls private static final String MODULE_DIR = "module"; |
| public static final String SDK_SOURCES_TARGET_PATH = "/sdk_sources"; |
| |
| public void testSdkWithEmptySources() throws Exception { |
| configureAndroidSdkWithSources(SDK_SOURCES_PATH_PREFIX + "1"); |
| |
| final VirtualFile f = myFixture.copyFileToProject(BASE_PATH + "MyActivity1.java", MODULE_DIR + "/src/p1/p2/MyActivity.java"); |
| myFixture.configureFromExistingVirtualFile(f); |
| myFixture.checkHighlighting(false, false, false); |
| } |
| |
| public void testNavigationToSources() throws Exception { |
| final String sdkSourcesPath = configureAndroidSdkWithSources(SDK_SOURCES_PATH_PREFIX + "2"); |
| |
| final VirtualFile f = myFixture.copyFileToProject(BASE_PATH + "MyActivity2.java", MODULE_DIR + "/src/p1/p2/MyActivity.java"); |
| myFixture.configureFromExistingVirtualFile(f); |
| |
| PsiElement element = GotoDeclarationAction.findTargetElement( |
| myFixture.getProject(), myFixture.getEditor(), |
| myFixture.getEditor().getCaretModel().getOffset()); |
| assertNotNull(element); |
| element = element.getNavigationElement(); |
| assertNotNull(element); |
| final PsiFile activityPsiFile = element.getContainingFile(); |
| assertNotNull(activityPsiFile); |
| final VirtualFile activityVFile = activityPsiFile.getVirtualFile(); |
| assertNotNull(activityVFile); |
| |
| final String expectedActivityFilePath = FileUtil.toSystemIndependentName(sdkSourcesPath + "/android/app/Activity.java"); |
| assertTrue("Expected: " + expectedActivityFilePath + "\nActual: " + activityVFile.getPath(), |
| FileUtil.pathsEqual(expectedActivityFilePath, activityVFile.getPath())); |
| } |
| |
| public void testSdkSourcesHighlighting1() throws Exception { |
| myFixture.allowTreeAccessForAllFiles(); |
| final String sdkSourcesPath = configureMockSdk(); |
| final VirtualFile file = LocalFileSystem.getInstance().findFileByPath(sdkSourcesPath + "/android/app/Activity.java"); |
| assertNotNull(file); |
| myFixture.configureFromExistingVirtualFile(file); |
| myFixture.checkHighlighting(false, false, false); |
| } |
| |
| public void testSdkSourcesHighlighting2() throws Exception { |
| myFixture.allowTreeAccessForAllFiles(); |
| final String sdkSourcesPath = configureMockSdk(); |
| final VirtualFile file = LocalFileSystem.getInstance().findFileByPath(sdkSourcesPath + "/android/app/ActivityThread.java"); |
| assertNotNull(file); |
| myFixture.configureFromExistingVirtualFile(file); |
| myFixture.checkHighlighting(false, false, false); |
| } |
| |
| public void testSdkSourcesHighlighting3() throws Exception { |
| myFixture.allowTreeAccessForAllFiles(); |
| final String sdkSourcesPath = configureMockSdk(); |
| final VirtualFile file = LocalFileSystem.getInstance().findFileByPath(sdkSourcesPath + "/util/UtilClass.java"); |
| assertNotNull(file); |
| myFixture.configureFromExistingVirtualFile(file); |
| myFixture.checkHighlighting(false, false, false); |
| } |
| |
| public void testProjectSourcesHighlighting() throws Exception { |
| myFixture.allowTreeAccessForAllFiles(); |
| configureMockSdk(); |
| final VirtualFile f = myFixture.copyFileToProject(BASE_PATH + "MyActivity3.java", MODULE_DIR + "/src/p1/p2/MyActivity.java"); |
| myFixture.configureFromExistingVirtualFile(f); |
| myFixture.checkHighlighting(false, false, false); |
| } |
| |
| public void testNavigationToResources1() throws Exception { |
| doTestNavigationToResource(new LogicalPosition(19, 35), 1, XmlAttributeValue.class); |
| } |
| |
| public void testNavigationToResources2() throws Exception { |
| doTestNavigationToResource(new LogicalPosition(20, 35), 2, XmlAttributeValue.class); |
| } |
| |
| public void testNavigationToResources3() throws Exception { |
| doTestNavigationToResource(new LogicalPosition(21, 35), 1, XmlAttributeValue.class); |
| } |
| |
| public void testNavigationToResources4() throws Exception { |
| doTestNavigationToResource(new LogicalPosition(22, 35), 1, XmlAttributeValue.class); |
| } |
| |
| public void testNavigationToResources5() throws Exception { |
| doTestNavigationToResource(new LogicalPosition(24, 43), 1, XmlAttributeValue.class); |
| } |
| |
| public void testNavigationToResources6() throws Exception { |
| doTestNavigationToResource(new LogicalPosition(25, 43), 2, XmlAttributeValue.class); |
| } |
| |
| public void testNavigationToResources7() throws Exception { |
| doTestNavigationToResource(new LogicalPosition(26, 43), 1, XmlAttributeValue.class); |
| } |
| |
| public void testNavigationToResources8() throws Exception { |
| doTestNavigationToResource(new LogicalPosition(27, 43), 1, XmlAttributeValue.class); |
| } |
| |
| public void testNavigationToResources9() throws Exception { |
| doTestNavigationToResource(new LogicalPosition(29, 46), 1, FileResourceElementWrapper.class); |
| } |
| |
| public void testNavigationToResources10() throws Exception { |
| doTestNavigationToResource(new LogicalPosition(30, 46), 1, FileResourceElementWrapper.class); |
| } |
| |
| public void testFindingInternalResourceClasses() throws Exception { |
| configureMockSdk(); |
| final JdkOrderEntry jdkOrderEntry = findJdkOrderEntry(); |
| assertNotNull(jdkOrderEntry); |
| final GlobalSearchScope scope = new AndroidSdkResolveScopeProvider().getScope(getProject(), jdkOrderEntry); |
| assertNotNull(scope); |
| final JavaPsiFacade facade = JavaPsiFacade.getInstance(getProject()); |
| |
| assertNotNull(facade.findClass(AndroidPsiElementFinder.INTERNAL_R_CLASS_QNAME, scope)); |
| assertNotNull(facade.findClass(AndroidPsiElementFinder.INTERNAL_R_CLASS_QNAME + ".string", scope)); |
| |
| PsiClass[] classes = facade.findClasses(AndroidPsiElementFinder.INTERNAL_R_CLASS_QNAME, scope); |
| assertEquals(1, classes.length); |
| classes = facade.findClasses(AndroidPsiElementFinder.INTERNAL_R_CLASS_QNAME + ".string", scope); |
| assertEquals(1, classes.length); |
| } |
| |
| public void testNoDuplicateAndroidSdkClassesFound() throws Exception { |
| configureMockSdk(); |
| PsiClass[] classes = myFixture.getJavaFacade().findClasses( |
| "android.app.Activity", GlobalSearchScope.allScope(myFixture.getProject())); |
| assertEquals(1, classes.length); |
| } |
| |
| @Nullable |
| private JdkOrderEntry findJdkOrderEntry() { |
| for (OrderEntry entry : ModuleRootManager.getInstance(myModule).getOrderEntries()) { |
| if (entry instanceof JdkOrderEntry) { |
| return (JdkOrderEntry)entry; |
| } |
| } |
| return null; |
| } |
| |
| private void doTestNavigationToResource(LogicalPosition position, int expectedCount, Class<?> aClass) { |
| myFixture.allowTreeAccessForAllFiles(); |
| final String sdkSourcesPath = configureMockSdk(); |
| |
| final VirtualFile file = LocalFileSystem.getInstance().findFileByPath(sdkSourcesPath + "/android/app/Activity.java"); |
| myFixture.configureFromExistingVirtualFile(file); |
| |
| myFixture.getEditor().getCaretModel().moveToLogicalPosition(position); |
| |
| PsiElement[] elements = GotoDeclarationAction.findAllTargetElements( |
| myFixture.getProject(), myFixture.getEditor(), |
| myFixture.getEditor().getCaretModel().getOffset()); |
| assertEquals(expectedCount, elements.length); |
| |
| for (PsiElement element : elements) { |
| assertInstanceOf(LazyValueResourceElementWrapper.computeLazyElement(element), aClass); |
| } |
| } |
| |
| private String configureMockSdk() { |
| final String mockSdkPath = BASE_PATH + "mock_sdk"; |
| final VirtualFile mockSdkSourcesDir = myFixture.copyDirectoryToProject(mockSdkPath + "/sources", SDK_SOURCES_TARGET_PATH); |
| VirtualFile classesJarFile = JarFileSystem.getInstance(). |
| findFileByPath(getTestDataPath() + "/" + mockSdkPath + "/classes.jar!/"); |
| assert classesJarFile != null; |
| Sdk sdk = ProjectJdkTable.getInstance().createSdk("android_mock_sdk", AndroidSdkType.getInstance()); |
| SdkModificator modificator = sdk.getSdkModificator(); |
| final AndroidSdkAdditionalData data = new AndroidSdkAdditionalData(sdk); |
| data.setBuildTargetHashString("android-17"); |
| modificator.setSdkAdditionalData(data); |
| final String testSdkPath = getTestSdkPath(); |
| modificator.setHomePath(testSdkPath); |
| modificator.removeAllRoots(); |
| modificator.addRoot(classesJarFile, OrderRootType.CLASSES); |
| modificator.addRoot(mockSdkSourcesDir, OrderRootType.SOURCES); |
| final VirtualFile resDir = LocalFileSystem.getInstance().findFileByPath(testSdkPath + "/platforms/android-1.5/data/res"); |
| modificator.addRoot(resDir, OrderRootType.CLASSES); |
| modificator.commitChanges(); |
| ModuleRootModificationUtil.setModuleSdk(myModule, sdk); |
| return mockSdkSourcesDir.getPath(); |
| } |
| |
| private String configureAndroidSdkWithSources(String... sdkSourcesPaths) { |
| addAndroidSdk(myModule, getTestSdkPath(), getPlatformDir()); |
| final VirtualFile sdkSourcesDir = myFixture.copyDirectoryToProject(sdkSourcesPaths[0], SDK_SOURCES_TARGET_PATH); |
| |
| for (int i = 1; i < sdkSourcesPaths.length; i++) { |
| myFixture.copyDirectoryToProject(sdkSourcesPaths[i], SDK_SOURCES_TARGET_PATH); |
| } |
| assert sdkSourcesDir.isDirectory(); |
| final Sdk sdk = ModuleRootManager.getInstance(myFixture.getModule()).getSdk(); |
| assert sdk != null; |
| final SdkModificator modificator = sdk.getSdkModificator(); |
| modificator.addRoot(sdkSourcesDir, OrderRootType.SOURCES); |
| modificator.commitChanges(); |
| return sdkSourcesDir.getPath(); |
| } |
| |
| @Override |
| protected boolean isToAddSdk() { |
| return false; |
| } |
| |
| @Override |
| protected String getContentRootPath() { |
| return "/" + MODULE_DIR; |
| } |
| } |