public void apply()

in android-lint/src/com/android/tools/idea/lint/quickFixes/MigrateDrawableToMipmapFix.java [73:202]


  public void apply(@NotNull PsiElement startElement, @NotNull PsiElement endElement, @NotNull AndroidQuickfixContexts.Context context) {
    Project project = startElement.getProject();
    AndroidFacet facet = AndroidFacet.getInstance(startElement);
    if (facet == null) {
      return;
    }

    final List<PsiFile> bitmaps = new ArrayList<>();
    final Set<PsiElement> references = Sets.newHashSet();

    GlobalSearchScope useScope = GlobalSearchScope.projectScope(project);
    ResourceRepository projectResources = StudioResourceRepositoryManager.getProjectResources(facet);
    List<ResourceItem> resourceItems = projectResources.getResources(ResourceNamespace.TODO(), myUrl.type, myUrl.name);
    for (ResourceItem item : resourceItems) {
      PsiFile file = IdeResourcesUtil.getItemPsiFile(project, item);
      if (file == null) {
        continue;
      }
      bitmaps.add(file);

      Iterable<PsiReference> allReferences = SearchUtils.findAllReferences(file, useScope);
      for (PsiReference next : allReferences) {
        PsiElement element = next.getElement();
        if (element != null) {
          references.add(element);
        }
      }
    }

    PsiField[] resourceFields = IdeResourcesUtil.findResourceFields(facet, ResourceType.DRAWABLE.getName(), myUrl.name);
    if (resourceFields.length == 1) {
      Iterable<PsiReference> allReferences = SearchUtils.findAllReferences(resourceFields[0], useScope);
      for (PsiReference next : allReferences) {
        PsiElement element = next.getElement();
        if (element != null) {
          references.add(element);
        }
      }
    }

    Set<PsiFile> applicableFiles = Sets.newHashSet();
    applicableFiles.addAll(bitmaps);
    for (PsiElement element : references) {
      PsiFile containingFile = element.getContainingFile();
      if (containingFile != null) {
        applicableFiles.add(containingFile);
      }
    }

    WriteCommandAction.writeCommandAction(project, applicableFiles.toArray(PsiFile.EMPTY_ARRAY)).withName("Migrate Drawable to Bitmap").run(() -> {
      try {
        // Move each drawable bitmap from drawable-my-qualifiers to bitmap-my-qualifiers
        for (PsiFile bitmap : bitmaps) {
          VirtualFile file = bitmap.getVirtualFile();
          if (file == null) {
            continue;
          }
          VirtualFile parent = file.getParent();
          if (parent == null) { // shouldn't happen for bitmaps found in the resource repository
            continue;
          }

          if (file.getFileType() == XmlFileType.INSTANCE && parent.getName().startsWith(FD_RES_VALUES)) {
            // Resource alias rather than an actual drawable XML file: update the type reference instead
            XmlFile xmlFile = (XmlFile)bitmap;
            XmlTag root = xmlFile.getRootTag();
            if (root != null) {
              for (XmlTag item : root.getSubTags()) {
                String name = item.getAttributeValue(ATTR_NAME);
                if (myUrl.name.equals(name)) {
                  if (ResourceType.DRAWABLE.getName().equals(item.getName())) {
                    item.setName(ResourceType.MIPMAP.getName());
                  }
                  else if (ResourceType.DRAWABLE.getName().equals(item.getAttributeValue(ATTR_TYPE))) {
                    item.setAttribute(ATTR_TYPE, ResourceType.MIPMAP.getName());
                  }
                }
              }
            }
            continue; // Don't move the file
          }

          VirtualFile res = parent.getParent();
          if (res == null) { // shouldn't happen for bitmaps found in the resource repository
            continue;
          }

          FolderConfiguration configuration = FolderConfiguration.getConfigForFolder(parent.getName());
          if (configuration == null) {
            continue;
          }
          String targetFolderName = configuration.getFolderName(ResourceFolderType.MIPMAP);
          VirtualFile targetFolder = res.findChild(targetFolderName);
          if (targetFolder == null) {
            targetFolder = res.createChildDirectory(this, targetFolderName);
          }
          file.move(this, targetFolder);
        }

        // Update references
        for (PsiElement reference : references) {
          if (reference instanceof XmlAttributeValue) {
            // Convert @drawable/foo references to @mipmap/foo
            XmlAttributeValue value = (XmlAttributeValue)reference;
            XmlAttribute attribute = (XmlAttribute)value.getParent();
            attribute.setValue(ResourceUrl.create(ResourceType.MIPMAP, myUrl.name, false).toString());
          }
          else if (reference instanceof PsiReferenceExpression) {
            // Convert R.drawable.foo references to R.mipmap.foo
            PsiReferenceExpression inner = (PsiReferenceExpression)reference;
            PsiExpression qualifier = inner.getQualifierExpression();
            if (qualifier instanceof PsiReferenceExpression) {
              PsiReferenceExpression outer = (PsiReferenceExpression)qualifier;
              if (outer.getReferenceNameElement() instanceof PsiIdentifier) {
                PsiIdentifier identifier = (PsiIdentifier)outer.getReferenceNameElement();
                if (ResourceType.DRAWABLE.getName().equals(identifier.getText())) {
                  final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(reference.getProject());
                  PsiIdentifier newIdentifier = elementFactory.createIdentifier(ResourceType.MIPMAP.getName());
                  identifier.replace(newIdentifier);
                }
              }
            }
          }
        }
      }
      catch (Exception e) {
        throw new RuntimeException(e);
      }
    });
  }