in android/src/com/android/tools/idea/res/ResourceFolderRepository.java [1299:1428]
public void childRemoved(@NotNull PsiTreeChangeEvent event) {
ResourceUpdateTracer.log(() -> getSimpleId(this) + ".childRemoved " + pathForLogging(event.getFile()));
try {
PsiFile psiFile = event.getFile();
if (psiFile != null && isRelevantFile(psiFile)) {
VirtualFile virtualFile = psiFile.getVirtualFile();
// If the file is currently being scanned, schedule a new scan to avoid a race condition
// between the incremental update and the running scan.
if (rescheduleScanIfRunning(virtualFile)) {
return;
}
// Some child was removed within a file.
ResourceFolderType folderType = ResourceFilesUtil.getFolderType(virtualFile);
if (folderType != null && isResourceFile(virtualFile)) {
PsiElement child = event.getChild();
PsiElement parent = event.getParent();
if (folderType == VALUES) {
if (child instanceof XmlTag) {
XmlTag tag = (XmlTag)child;
// See if you just removed an item inside a <style> or <array> or <declare-styleable> etc.
if (parent instanceof XmlTag) {
XmlTag parentTag = (XmlTag)parent;
if (getResourceTypeForResourceTag(parentTag) != null) {
if (convertToPsiIfNeeded(psiFile, folderType)) {
return;
}
// Yes just invalidate the corresponding cached value.
ResourceItem resourceItem = findValueResourceItem(parentTag, psiFile);
if (resourceItem instanceof PsiResourceItem) {
if (((PsiResourceItem)resourceItem).recomputeValue()) {
setModificationCount(ourModificationCounter.incrementAndGet());
}
ResourceUpdateTracer.log(() -> getSimpleId(this) + ".childRemoved " + pathForLogging(event.getFile()) +
" recomputed: " + resourceItem);
if (resourceItem.getType() == ResourceType.ATTR) {
parentTag = parentTag.getParentTag();
if (parentTag != null && getResourceTypeForResourceTag(parentTag) == ResourceType.STYLEABLE) {
ResourceItem declareStyleable = findValueResourceItem(parentTag, psiFile);
if (declareStyleable instanceof PsiResourceItem) {
if (((PsiResourceItem)declareStyleable).recomputeValue()) {
setModificationCount(ourModificationCounter.incrementAndGet());
}
}
}
}
return;
}
}
}
if (isItemElement(tag)) {
if (convertToPsiIfNeeded(psiFile, folderType)) {
return;
}
scheduleUpdate(() -> {
ResourceItemSource<?> source = mySources.get(virtualFile);
if (source == null) {
scan(psiFile, folderType);
return;
}
PsiResourceFile resourceFile = (PsiResourceFile)source;
String name;
if (tag.isValid()) {
name = tag.getAttributeValue(ATTR_NAME);
}
else {
ResourceItem item = findValueResourceItem(tag, psiFile);
if (item == null) {
// Can't find the name of the deleted tag; just do a full rescan.
scan(psiFile, folderType);
return;
}
name = item.getName();
}
if (name != null) {
ResourceType type = getResourceTypeForResourceTag(tag);
if (type != null) {
synchronized (ITEM_MAP_LOCK) {
boolean removed = removeItemsForTag(resourceFile, tag, type);
if (removed) {
setModificationCount(ourModificationCounter.incrementAndGet());
invalidateParentCaches(ResourceFolderRepository.this, type);
}
}
}
}
});
}
return;
}
else if (parent instanceof XmlText) {
// If the edit is within an item tag.
XmlText text = (XmlText)parent;
handleValueXmlTextEdit(text.getParentTag(), psiFile);
}
else if (child instanceof XmlText) {
handleValueXmlTextEdit(parent, psiFile);
}
else if (parent instanceof XmlComment || child instanceof XmlComment) {
// Can ignore comment edits or removed comments.
return;
}
else {
// Some other change: do full file rescan.
scheduleScan(virtualFile, folderType);
}
}
else if (FolderTypeRelationship.isIdGeneratingFolderType(folderType) && psiFile.getFileType() == XmlFileType.INSTANCE) {
// TODO: Handle removals of id's (values an attributes) incrementally.
scheduleScan(virtualFile, folderType);
}
else if (folderType == FONT) {
clearFontCache(virtualFile);
}
}
}
myIgnoreChildrenChanged = true;
}
finally {
ResourceUpdateTracer.log(() -> getSimpleId(this) + ".childRemoved " + pathForLogging(event.getFile()) + " end");
}
}