@Override public NewArtifactConfiguration createArtifact() { final AndroidFacet facet = myFacets.size() == 1 ? myFacets.get(0) : AndroidArtifactUtil.chooseAndroidApplicationModule(myProject, myFacets); if (facet == null) { return null; } final CompositePackagingElement<?> rootElement = AndroidApplicationArtifactType.this.createRootElement(facet.getModule().getName()); rootElement.addFirstChild(new AndroidFinalPackageElement(myProject, facet)); return new NewArtifactConfiguration( rootElement, facet.getModule().getName(), AndroidApplicationArtifactType.this); }
@NotNull static String doValidatePackageName( boolean library, @NotNull String candidate, @Nullable ModulesProvider modulesProvider) { if (candidate.length() == 0) { return AndroidBundle.message("specify.package.name.error"); } if (!AndroidUtils.isValidAndroidPackageName(candidate)) { return candidate; } if (!AndroidCommonUtils.contains2Identifiers(candidate)) { return AndroidBundle.message("package.name.must.contain.2.ids.error"); } if (!library) { for (Module module : modulesProvider.getModules()) { final AndroidFacet facet = AndroidFacet.getInstance(module); if (facet != null && !facet.isLibraryProject()) { final Manifest manifest = facet.getManifest(); if (manifest != null) { final String packageName = manifest.getPackage().getValue(); if (candidate.equals(packageName)) { return "Package name '" + packageName + "' is already used by module '" + module.getName() + "'"; } } } } } return ""; }
private static void doCollectResourceDirs( AndroidFacet facet, boolean collectResCacheDirs, List<String> result, CompileContext context) { final Module module = facet.getModule(); if (collectResCacheDirs) { final AndroidPlatform platform = facet.getConfiguration().getAndroidPlatform(); final int platformToolsRevision = platform != null ? platform.getSdk().getPlatformToolsRevision() : -1; if (platformToolsRevision < 0 || platformToolsRevision > 7) { // png cache is supported since platform-tools-r8 final String resCacheDirOsPath = findResourcesCacheDirectory(module, false, context); if (resCacheDirOsPath != null) { result.add(resCacheDirOsPath); } else { LOG.info("PNG cache not found for module " + module.getName()); } } } final VirtualFile resourcesDir = AndroidAptCompiler.getResourceDirForApkCompiler(module, facet); if (resourcesDir != null) { result.add(resourcesDir.getPath()); } }
/** * Create a variation (copy) of a given resource file (of a given type). * * @param xmlFile the XML resource file to fork * @param myNewFolder the resource folder to create, or null to ask the user * @param open if true, open the file after creating it */ public static void forkResourceFile( @NotNull final XmlFile xmlFile, @Nullable String myNewFolder, boolean open) { VirtualFile file = xmlFile.getVirtualFile(); if (file == null) { return; } Module module = AndroidPsiUtils.getModuleSafely(xmlFile); if (module == null) { return; } ResourceFolderType folderType = ResourceHelper.getFolderType(xmlFile); if (folderType == null || folderType == ResourceFolderType.VALUES) { return; } Configuration configuration = null; if (folderType == ResourceFolderType.LAYOUT) { AndroidFacet facet = AndroidFacet.getInstance(module); if (facet != null) { configuration = facet.getConfigurationManager().getConfiguration(file); } } // Suppress: IntelliJ claims folderType can be null here, but it can't (and inserting assert // folderType != null is correctly // identified as redundant) //noinspection ConstantConditions forkResourceFile(module, folderType, file, xmlFile, myNewFolder, configuration, open); }
/** * Returns the manifest file for the given module * * @param module module to search the manifest document for * @return manifest doc for the given module */ public Manifest getManifestForModule(final Module module) { if (module == null || AndroidFacet.getInstance(module) == null) { return null; } return AndroidFacet.getInstance(module).getManifest(); }
/** * Returns the given module's apk path * * @param module android module used to get the facet and the apk file path * @return file path of the android apk for the given module */ public String getAndroidApkPath(Module module) { if (module == null || AndroidFacet.getInstance(module) == null) { return null; } return AndroidRootUtil.getApkPath(AndroidFacet.getInstance(module)); }
/** * return the given manifest Path * * @param module * @return */ public String getAndroidManifestPath(Module module) { if (module == null || AndroidFacet.getInstance(module) == null) { return null; } return AndroidRootUtil.getManifestFile(AndroidFacet.getInstance(module)).getPath(); }
private static void createValueResource( @NotNull PsiFile file, @NotNull AndroidFacet facet, @NotNull PsiDirectory dir, @NotNull final String resName, @NotNull final String value, @NotNull final ResourceType type, @NotNull final String oldTagText) { final String filename = file.getName(); final List<String> dirNames = Collections.singletonList(dir.getName()); final Module module = facet.getModule(); final AtomicReference<PsiElement> openAfter = new AtomicReference<PsiElement>(); final WriteCommandAction<Void> action = new WriteCommandAction<Void>( facet.getModule().getProject(), "Override Resource " + resName, file) { @Override protected void run(@NotNull Result<Void> result) { List<ResourceElement> elements = Lists.newArrayListWithExpectedSize(1); // AndroidResourceUtil.createValueResource will create a new resource value in the given // resource // folder (and record the corresponding tags added in the elements list passed into it). // However, it only creates a new element and sets the name attribute on it; it does not // transfer attributes, child content etc. Therefore, we use this utility method first // to // create the corresponding tag, and then *afterwards* we will replace the tag with a // text copy // from the resource tag we are overriding. We do this all under a single write lock // such // that it becomes a single atomic operation. AndroidResourceUtil.createValueResource( module, resName, type, filename, dirNames, value, elements); if (elements.size() == 1) { final XmlTag tag = elements.get(0).getXmlTag(); if (tag != null && tag.isValid()) { try { XmlTag tagFromText = XmlElementFactory.getInstance(tag.getProject()).createTagFromText(oldTagText); PsiElement replaced = tag.replace(tagFromText); openAfter.set(replaced); } catch (IncorrectOperationException e) { // The user tried to override an invalid XML fragment: don't attempt to do a // replacement in that case openAfter.set(tag); } } } } }; action.execute(); PsiElement tag = openAfter.get(); if (tag != null) { NavigationUtil.openFileWithPsiElement(tag, true, true); } }
@Override public void apply( @NotNull PsiElement startElement, @NotNull PsiElement endElement, @NotNull AndroidQuickfixContexts.Context context) { PsiFile file = startElement.getContainingFile(); if (file instanceof XmlFile) { ResourceFolderType folderType = ResourceHelper.getFolderType(file); if (folderType != null) { if (folderType != ResourceFolderType.VALUES) { forkResourceFile((XmlFile) file, myFolder, true); } else { XmlTag tag = getValueTag(PsiTreeUtil.getParentOfType(startElement, XmlTag.class, false)); if (tag != null) { AndroidFacet facet = AndroidFacet.getInstance(startElement); if (facet != null) { PsiDirectory dir = null; if (myFolder != null) { PsiDirectory resFolder = findRes(file); if (resFolder != null) { dir = resFolder.findSubdirectory(myFolder); if (dir == null) { dir = resFolder.createSubdirectory(myFolder); } } } forkResourceValue(startElement.getProject(), tag, file, facet, dir); } } } } } }
@Override protected boolean isAvailableForFile(PsiFile file) { return file instanceof XmlFile && AndroidFacet.getInstance(file) != null && DomManager.getDomManager(file.getProject()).getDomFileDescription((XmlFile) file) instanceof LayoutDomFileDescription; }
@Override public void setUpArtifact( @NotNull Artifact artifact, @NotNull NewArtifactConfiguration configuration) { final AndroidFacet facet = AndroidArtifactUtil.getPackagedFacet(myProject, artifact); if (facet != null) { final ArtifactProperties<?> properties = artifact.getProperties(AndroidArtifactPropertiesProvider.getInstance()); if (properties instanceof AndroidApplicationArtifactProperties) { final AndroidApplicationArtifactProperties p = (AndroidApplicationArtifactProperties) properties; p.setProGuardCfgFiles(facet.getProperties().myProGuardCfgFiles); } } }
public Pair<RenderResources, RenderResources> createResourceResolver( final AndroidFacet facet, FolderConfiguration config, ProjectResources projectResources, String themeName, boolean isProjectTheme) { final Map<ResourceType, Map<String, ResourceValue>> configedProjectRes = projectResources.getConfiguredResources(config); DumbService.getInstance(facet.getModule().getProject()).waitForSmartMode(); final Collection<String> ids = ApplicationManager.getApplication() .runReadAction( new Computable<Collection<String>>() { @Override public Collection<String> compute() { return facet.getLocalResourceManager().getIds(); } }); final Map<String, ResourceValue> map = configedProjectRes.get(ResourceType.ID); for (String id : ids) { if (!map.containsKey(id)) { map.put(id, new ResourceValue(ResourceType.ID, id, false)); } } final Map<ResourceType, Map<String, ResourceValue>> configedFrameworkRes = myResources.getConfiguredResources(config); final ResourceResolver resolver = ResourceResolver.create( configedProjectRes, configedFrameworkRes, themeName, isProjectTheme); return new Pair<RenderResources, RenderResources>( new ResourceResolverDecorator(resolver), resolver); }
public static void createSourceRootIfNotExist( @NotNull final String path, @NotNull final Module module) { ApplicationManager.getApplication().assertIsDispatchThread(); final File rootFile = new File(path); final boolean created; if (!rootFile.exists()) { if (!rootFile.mkdirs()) return; created = true; } else { created = false; } final Project project = module.getProject(); Module genModule = module; final AndroidFacet facet = AndroidFacet.getInstance(genModule); if (facet != null && facet.getConfiguration().LIBRARY_PROJECT) { removeGenModule(module); } if (project.isDisposed() || genModule.isDisposed()) { return; } final VirtualFile root; if (created) { root = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(rootFile); } else { root = LocalFileSystem.getInstance().findFileByIoFile(rootFile); } if (root != null) { final ModuleRootManager manager = ModuleRootManager.getInstance(genModule); unexcludeRootIfNeccessary(root, manager); for (VirtualFile existingRoot : manager.getSourceRoots()) { if (existingRoot == root) return; } ApplicationManager.getApplication() .runWriteAction( new Runnable() { public void run() { addSourceRoot(manager, root); } }); } }
public static void createGenModulesAndSourceRoots(@NotNull final AndroidFacet facet) { final Module module = facet.getModule(); String sourceRootPath = AndroidRootUtil.getRenderscriptGenSourceRootPath(module); if (sourceRootPath != null) { createSourceRootIfNotExist(sourceRootPath, module); } sourceRootPath = facet.getAptGenSourceRootPath(); if (sourceRootPath != null) { createSourceRootIfNotExist(sourceRootPath, module); } sourceRootPath = facet.getAidlGenSourceRootPath(); if (sourceRootPath != null) { createSourceRootIfNotExist(sourceRootPath, module); } }
@Override protected boolean isEnabledOnElements(PsiElement[] elements) { if (elements.length != 1) { return false; } final PsiElement element = elements[0]; return element instanceof XmlTag && AndroidFacet.getInstance(element) != null && isEnabled((XmlTag) element); }
@NotNull @Override public List<? extends ArtifactTemplate> getNewArtifactTemplates( @NotNull PackagingElementResolvingContext context) { final List<AndroidFacet> facets = new ArrayList<AndroidFacet>(); for (Module module : context.getModulesProvider().getModules()) { final FacetModel facetModel = context.getModulesProvider().getFacetModel(module); final AndroidFacet facet = facetModel.getFacetByType(AndroidFacet.ID); if (facet != null && !facet.isLibraryProject()) { facets.add(facet); } } if (facets.size() == 0) { return Collections.emptyList(); } return Collections.singletonList(new MyTemplate(context.getProject(), facets)); }
@Override protected boolean isAvailableOnElementInEditorAndFile( PsiElement element, Editor editor, PsiFile file, DataContext context) { if (element == null || AndroidFacet.getInstance(element) == null || PsiTreeUtil.getParentOfType(element, XmlText.class) != null) { return false; } final XmlTag tag = PsiTreeUtil.getParentOfType(element, XmlTag.class); return tag != null && isEnabled(tag); }
@Nullable public static ValidationInfo checkIfResourceAlreadyExists( @NotNull Module selectedModule, @NotNull String resourceName, @NotNull ResourceType resourceType, @NotNull List<String> dirNames, @NotNull String fileName) { if (resourceName.length() == 0 || dirNames.size() == 0 || fileName.length() == 0) { return null; } final AndroidFacet facet = AndroidFacet.getInstance(selectedModule); final VirtualFile resourceDir = facet != null ? AndroidRootUtil.getResourceDir(facet) : null; if (resourceDir == null) { return null; } for (String directoryName : dirNames) { final VirtualFile resourceSubdir = resourceDir.findChild(directoryName); if (resourceSubdir == null) { continue; } final VirtualFile resFile = resourceSubdir.findChild(fileName); if (resFile == null) { continue; } if (resFile.getFileType() != StdFileTypes.XML) { return new ValidationInfo( "File " + FileUtil.toSystemDependentName(resFile.getPath()) + " is not XML file"); } final Resources resources = AndroidUtils.loadDomElement(selectedModule, resFile, Resources.class); if (resources == null) { return new ValidationInfo( AndroidBundle.message( "not.resource.file.error", FileUtil.toSystemDependentName(resFile.getPath()))); } for (ResourceElement element : AndroidResourceUtil.getValueResourcesFromElement(resourceType.getName(), resources)) { if (resourceName.equals(element.getName().getValue())) { return new ValidationInfo( "resource '" + resourceName + "' already exists in " + FileUtil.toSystemDependentName(resFile.getPath())); } } } return null; }
public boolean render() { ApplicationManager.getApplication().assertIsDispatchThread(); if (myToolWindow == null || !myToolWindow.isVisible()) { return false; } final PsiFile psiFile = myToolWindowForm.getFile(); if (psiFile == null) { return false; } final AndroidFacet facet = AndroidFacet.getInstance(psiFile); if (facet == null) { return false; } getRenderingQueue() .queue( new Update("render") { @Override public void run() { ProgressManager.getInstance() .runProcess( new Runnable() { @Override public void run() { DumbService.getInstance(myProject).waitForSmartMode(); try { doRender(facet, psiFile); } catch (Throwable e) { LOG.error(e); } synchronized (PROGRESS_LOCK) { if (myCurrentIndicator != null) { myCurrentIndicator.stop(); myCurrentIndicator = null; } } } }, new AndroidPreviewProgressIndicator(myToolWindowForm, 100)); } @Override public boolean canEat(Update update) { return true; } }); return true; }
@NotNull public static String[] collectResourceDirs( AndroidFacet facet, boolean collectResCacheDirs, @Nullable CompileContext context) { final Project project = facet.getModule().getProject(); final IntermediateOutputCompiler pngFilesCachingCompiler = collectResCacheDirs ? Extensions.findExtension( Compiler.EP_NAME, project, AndroidPngFilesCachingCompiler.class) : null; if (collectResCacheDirs) { assert pngFilesCachingCompiler != null; } final List<String> result = new ArrayList<String>(); doCollectResourceDirs(facet, collectResCacheDirs, result, context); for (AndroidFacet depFacet : AndroidUtils.getAllAndroidDependencies(facet.getModule(), true)) { doCollectResourceDirs(depFacet, collectResCacheDirs, result, context); } return ArrayUtil.toStringArray(result); }
@Override public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { if (file instanceof XmlFile && file.isValid() && AndroidFacet.getInstance(file) != null) { ResourceFolderType folderType = ResourceHelper.getFolderType(file); if (folderType == null) { return false; } else if (folderType != ResourceFolderType.VALUES) { return true; } else { return isAvailable(getValueTag(editor, file), file); } } return false; }
private static void addItem( @NotNull final Collection<VirtualFile> sourceFiles, @NotNull final AndroidFacet facet, @NotNull final String resourceDirPath, @NotNull String sdkLocation, @NotNull final IAndroidTarget target, @NotNull final List<GenerationItem> items) { final String sourceRootPath = AndroidRootUtil.getRenderscriptGenSourceRootPath(facet); if (sourceRootPath == null) { return; } final String rawDirPath = resourceDirPath + '/' + AndroidConstants.FD_RES_RAW; items.add( new MyGenerationItem(facet.getModule(), sourceFiles, rawDirPath, sdkLocation, target)); }
@Override public void invoke(@NotNull final Project project, Editor editor, PsiFile file) throws IncorrectOperationException { AndroidFacet facet = AndroidFacet.getInstance(file); ResourceFolderType folderType = ResourceHelper.getFolderType(file); if (facet == null || folderType == null) { // shouldn't happen; we checked in isAvailable return; } if (folderType != ResourceFolderType.VALUES) { forkResourceFile((XmlFile) file, null, true); } else if (editor != null) { forkResourceValue(project, editor, file, facet, null); } }
private void createNewResourceFile(ResourceType resourceType) { AndroidFacet facet = AndroidFacet.getInstance(myModule); XmlFile newFile = CreateResourceFileAction.createFileResource( facet, resourceType, null, null, null, true, null); if (newFile != null) { String name = newFile.getName(); int index = name.lastIndexOf('.'); if (index != -1) { name = name.substring(0, index); } myResultResourceName = "@" + resourceType.getName() + "/" + name; close(OK_EXIT_CODE); } }
public boolean isAvailable(@Nullable XmlTag tag, PsiFile file) { if (file instanceof XmlFile && file.isValid() && AndroidFacet.getInstance(file) != null) { ResourceFolderType folderType = ResourceHelper.getFolderType(file); if (folderType == null) { return false; } else if (folderType != ResourceFolderType.VALUES) { return true; } else { // In value files, you can invoke this action if the caret is on or inside an element (other // than the // root <resources> tag). Only accept the element if it has a known type with a known name. if (tag != null && tag.getAttributeValue(ATTR_NAME) != null) { return AndroidResourceUtil.getResourceForResourceTag(tag) != null; } } } return false; }
@NotNull private static Set<PsiClass> findRelatedActivitiesForMenu( @NotNull XmlFile file, @NotNull AndroidFacet facet) { final String resType = ResourceType.MENU.getName(); final String resourceName = AndroidCommonUtils.getResourceName(resType, file.getName()); final PsiField[] fields = AndroidResourceUtil.findResourceFields(facet, resType, resourceName, true); if (fields.length == 0) { return Collections.emptySet(); } final Module module = facet.getModule(); final GlobalSearchScope scope = module.getModuleScope(false); final PsiClass activityClass = findActivityClass(module); if (activityClass == null) { return Collections.emptySet(); } final Set<PsiClass> result = new HashSet<PsiClass>(); ReferencesSearch.search(fields[0], scope) .forEach( new Processor<PsiReference>() { @Override public boolean process(PsiReference reference) { final PsiElement element = reference.getElement(); if (element == null) { return true; } final PsiClass aClass = PsiTreeUtil.getParentOfType(element, PsiClass.class); if (aClass != null && !result.contains(aClass) && aClass.isInheritor(activityClass, true)) { result.add(aClass); } return true; } }); return result; }
public void setFacet(@NotNull AndroidFacet facet) { if (!CloudConfigurationProvider.isEnabled()) { return; // Running tests in cloud is not enabled! } myCurrentFacet = facet; myCurrentModule = myCurrentFacet.getModule(); myTestingConfigurations = myConfigurationProvider.getCloudConfigurations(myCurrentFacet, myConfigurationKind); // Since setFacet can be called multiple times, make sure to remove any previously registered // listeners. removeActionListener(myActionListener); myActionListener = new ActionListener() { @Override public void actionPerformed(ActionEvent e) { CloudConfiguration selectedConfig = myConfigurationProvider.openMatrixConfigurationDialog( myCurrentFacet, (CloudConfiguration) getComboBox().getSelectedItem(), myConfigurationKind); // Update the comboboxes' contents even if selectedConfig is null since it might mean // that a user deleted // all configurations in the Matrix Configuration dialog. List<? extends CloudConfiguration> cloudConfigurations = myConfigurationProvider.getCloudConfigurations(myCurrentFacet, myConfigurationKind); CloudConfigurationCoordinator.getInstance(myConfigurationKind) .updateComboBoxesWithNewCloudConfigurations(cloudConfigurations, myCurrentModule); if (cloudConfigurations.isEmpty() || selectedConfig != null) { getComboBox().setSelectedItem(selectedConfig); } getComboBox().updateUI(); } }; addActionListener(myActionListener); updateContent(); }
@NotNull private static Collection<PsiClass> findRelatedActivities( @NotNull XmlFile file, @NotNull AndroidFacet facet, @NotNull DomFileDescription<?> description) { if (description instanceof LayoutDomFileDescription) { final Computable<List<GotoRelatedItem>> computable = AndroidGotoRelatedProvider.getLazyItemsForXmlFile(file, facet); if (computable == null) { return Collections.emptyList(); } final List<GotoRelatedItem> items = computable.compute(); if (items.isEmpty()) { return Collections.emptyList(); } final PsiClass activityClass = findActivityClass(facet.getModule()); if (activityClass == null) { return Collections.emptyList(); } final List<PsiClass> result = new ArrayList<PsiClass>(); for (GotoRelatedItem item : items) { final PsiElement element = item.getElement(); if (element instanceof PsiClass) { final PsiClass aClass = (PsiClass) element; if (aClass.isInheritor(activityClass, true)) { result.add(aClass); } } } return result; } else { return findRelatedActivitiesForMenu(file, facet); } }
@NotNull public IDevice[] getSelectedDevices() { int[] rows = mySelectedRows != null ? mySelectedRows : myDeviceTable.getSelectedRows(); List<IDevice> result = new ArrayList<IDevice>(); for (int row : rows) { if (row >= 0) { Object serial = myDeviceTable.getValueAt(row, SERIAL_COLUMN_INDEX); final AndroidDebugBridge bridge = AndroidSdkUtils.getDebugBridge(myFacet.getModule().getProject()); if (bridge == null) { return EMPTY_DEVICE_ARRAY; } IDevice[] devices = getFilteredDevices(bridge); for (IDevice device : devices) { if (device.getSerialNumber().equals(serial.toString())) { result.add(device); break; } } } } return result.toArray(new IDevice[result.size()]); }
@Override public ProblemDescriptor[] checkFile( @NotNull PsiFile file, @NotNull InspectionManager manager, boolean isOnTheFly) { if (!(file instanceof XmlFile)) { return ProblemDescriptor.EMPTY_ARRAY; } final AndroidFacet facet = AndroidFacet.getInstance(file); if (facet == null) { return ProblemDescriptor.EMPTY_ARRAY; } final DomFileDescription<?> description = DomManager.getDomManager(file.getProject()).getDomFileDescription((XmlFile) file); if (!(description instanceof LayoutDomFileDescription) && !(description instanceof MenuDomFileDescription)) { return ProblemDescriptor.EMPTY_ARRAY; } final Collection<PsiClass> activities = findRelatedActivities((XmlFile) file, facet, description); final MyVisitor visitor = new MyVisitor(manager, isOnTheFly, activities); file.accept(visitor); return visitor.myResult.toArray(new ProblemDescriptor[visitor.myResult.size()]); }