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);
}
});
}