use of com.android.ide.common.res2.ResourceItem in project kotlin by JetBrains.
the class LintUtils method getStyleAttributes.
/**
* Looks up the resource values for the given attribute given a style. Note that
* this only looks project-level style values, it does not resume into the framework
* styles.
*/
@Nullable
public static List<ResourceValue> getStyleAttributes(@NonNull Project project, @NonNull LintClient client, @NonNull String styleUrl, @NonNull String namespace, @NonNull String attribute) {
if (!client.supportsProjectResources()) {
return null;
}
AbstractResourceRepository resources = client.getProjectResources(project, true);
if (resources == null) {
return null;
}
ResourceUrl style = ResourceUrl.parse(styleUrl);
if (style == null || style.framework) {
return null;
}
List<ResourceValue> result = null;
Queue<ResourceValue> queue = new ArrayDeque<ResourceValue>();
queue.add(new ResourceValue(style.type, style.name, false));
Set<String> seen = Sets.newHashSet();
int count = 0;
boolean isFrameworkAttribute = ANDROID_URI.equals(namespace);
while (count < 30 && !queue.isEmpty()) {
ResourceValue front = queue.remove();
String name = front.getName();
seen.add(name);
List<ResourceItem> items = resources.getResourceItem(front.getResourceType(), name);
if (items != null) {
for (ResourceItem item : items) {
ResourceValue rv = item.getResourceValue(false);
if (rv instanceof StyleResourceValue) {
StyleResourceValue srv = (StyleResourceValue) rv;
ItemResourceValue value = srv.getItem(attribute, isFrameworkAttribute);
if (value != null) {
if (result == null) {
result = Lists.newArrayList();
}
if (!result.contains(value)) {
result.add(value);
}
}
String parent = srv.getParentStyle();
if (parent != null && !parent.startsWith(ANDROID_PREFIX)) {
ResourceUrl p = ResourceUrl.parse(parent);
if (p != null && !p.framework && !seen.contains(p.name)) {
seen.add(p.name);
queue.add(new ResourceValue(ResourceType.STYLE, p.name, false));
}
}
int index = name.lastIndexOf('.');
if (index > 0) {
String parentName = name.substring(0, index);
if (!seen.contains(parentName)) {
seen.add(parentName);
queue.add(new ResourceValue(ResourceType.STYLE, parentName, false));
}
}
}
}
}
count++;
}
return result;
}
use of com.android.ide.common.res2.ResourceItem in project android by JetBrains.
the class ResourceFolderRepositoryTest method testEditIdAttributeValue2.
public void testEditIdAttributeValue2() throws Exception {
// Edit the id attribute value: rather than by making a full value replacement,
// perform a tiny edit on the character content; this takes a different code
// path in the incremental updater
resetScanCounter();
// Edit the id attribute value of a layout item to change the set of available ids
VirtualFile file1 = myFixture.copyFileToProject(LAYOUT1, "res/layout/layout1.xml");
PsiFile psiFile1 = PsiManager.getInstance(getProject()).findFile(file1);
assertNotNull(psiFile1);
ResourceFolderRepository resources = createRepository();
assertNotNull(resources);
Collection<String> layouts = resources.getItemsOfType(ResourceType.LAYOUT);
assertEquals(1, layouts.size());
assertNotNull(resources.getResourceItem(ResourceType.LAYOUT, "layout1"));
assertTrue(resources.hasResourceItem(ResourceType.ID, "noteArea"));
assertFalse(resources.hasResourceItem(ResourceType.ID, "note2Area"));
final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(getProject());
final Document document = documentManager.getDocument(psiFile1);
assertNotNull(document);
// Edit value should cause update
long generation = resources.getModificationCount();
WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
final int offset = document.getText().indexOf("noteArea");
document.insertString(offset + 4, "2");
documentManager.commitDocument(document);
}
});
// First edit won't be incremental (file -> Psi).
assertTrue(resources.isScanPending(psiFile1));
UIUtil.dispatchAllInvocationEvents();
assertTrue(generation < resources.getModificationCount());
assertTrue(resources.hasResourceItem(ResourceType.ID, "note2Area"));
assertFalse(resources.hasResourceItem(ResourceType.ID, "noteArea"));
resetScanCounter();
// A second update should be incremental.
long generation2 = resources.getModificationCount();
WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
final int offset = document.getText().indexOf("note2Area");
document.insertString(offset + 5, "3");
documentManager.commitDocument(document);
}
});
assertTrue(resources.hasResourceItem(ResourceType.ID, "note23Area"));
assertFalse(resources.hasResourceItem(ResourceType.ID, "note2Area"));
assertTrue(resources.getModificationCount() > generation2);
// Also check that for IDs the ResourceValue is nothing of consequence.
ResourceItem idItem = getOnlyItem(resources, ResourceType.ID, "note23Area");
ResourceValue idValue = idItem.getResourceValue(false);
assertNotNull(idValue);
assertEquals("", idValue.getValue());
// Shouldn't have done any full file rescans during the above edits
ensureIncremental();
}
use of com.android.ide.common.res2.ResourceItem in project android by JetBrains.
the class ResourceFolderRepositoryTest method testEditValueText.
public void testEditValueText() throws Exception {
resetScanCounter();
VirtualFile file1 = myFixture.copyFileToProject(VALUES1, "res/values/myvalues.xml");
PsiFile psiFile1 = PsiManager.getInstance(getProject()).findFile(file1);
assertNotNull(psiFile1);
ResourceFolderRepository resources = createRepository();
assertNotNull(resources);
Collection<String> strings = resources.getItemsOfType(ResourceType.STRING);
assertEquals(8, strings.size());
assertTrue(resources.hasResourceItem(ResourceType.STRING, "app_name"));
assertTrue(resources.hasResourceItem(ResourceType.INTEGER, "card_flip_time_full"));
long generation = resources.getModificationCount();
final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(getProject());
final Document document = documentManager.getDocument(psiFile1);
assertNotNull(document);
// Edit value should cause update
final int screenSlideOffset = document.getText().indexOf("Screen Slide");
WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
document.replaceString(screenSlideOffset + 3, screenSlideOffset + 3, "e");
documentManager.commitDocument(document);
}
});
// First edit won't be incremental (file -> Psi).
assertTrue(resources.isScanPending(psiFile1));
UIUtil.dispatchAllInvocationEvents();
assertTrue(generation < resources.getModificationCount());
resetScanCounter();
// Now try another edit, where things should be incremental now.
final int screeenSlideOffset = document.getText().indexOf("Screeen Slide");
WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
document.replaceString(screeenSlideOffset + 3, screeenSlideOffset + 3, "e");
documentManager.commitDocument(document);
}
});
long generation2 = resources.getModificationCount();
// NO revision bump yet, because the resource value hasn't been observed!
assertEquals(generation2, resources.getModificationCount());
// Now observe it, do another edit, and see what happens
List<ResourceItem> labelList = resources.getResourceItem(ResourceType.STRING, "title_screen_slide");
assertNotNull(labelList);
assertEquals(1, labelList.size());
ResourceItem slideLabel = labelList.get(0);
ResourceValue resourceValue = slideLabel.getResourceValue(false);
assertNotNull(resourceValue);
assertEquals("Screeeen Slide", resourceValue.getValue());
WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
document.deleteString(screenSlideOffset + 3, screenSlideOffset + 7);
documentManager.commitDocument(document);
}
});
assertTrue(generation2 < resources.getModificationCount());
resourceValue = slideLabel.getResourceValue(false);
assertNotNull(resourceValue);
assertEquals("Scrn Slide", resourceValue.getValue());
// Shouldn't have done any full file rescans during the above edits
ensureIncremental();
}
use of com.android.ide.common.res2.ResourceItem in project android by JetBrains.
the class ResourceFolderRepositoryTest method testRemovePluralItems.
public void testRemovePluralItems() throws Exception {
resetScanCounter();
VirtualFile file1 = myFixture.copyFileToProject(VALUES1, "res/values/myvalues.xml");
PsiFile psiFile1 = PsiManager.getInstance(getProject()).findFile(file1);
assertNotNull(psiFile1);
ResourceFolderRepository resources = createRepository();
assertNotNull(resources);
assertTrue(resources.hasResourceItem(ResourceType.PLURALS, "my_plural"));
ResourceItem plural = getOnlyItem(resources, ResourceType.PLURALS, "my_plural");
ResourceValue resourceValue = plural.getResourceValue(false);
assertNotNull(resourceValue);
assertInstanceOf(resourceValue, PluralsResourceValue.class);
PluralsResourceValue prv = (PluralsResourceValue) resourceValue;
assertEquals(3, prv.getPluralsCount());
assertEquals("@string/hello_two", resourceValue.getValue());
assertEquals("one", prv.getQuantity(0));
long generation = resources.getModificationCount();
final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(getProject());
final Document document = documentManager.getDocument(psiFile1);
assertNotNull(document);
WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
String item = "<item quantity=\"one\">@string/hello</item>";
int offset = document.getText().indexOf(item);
document.deleteString(offset, offset + item.length());
documentManager.commitDocument(document);
}
});
// First edit won't be incremental (file -> Psi).
assertTrue(resources.isScanPending(psiFile1));
UIUtil.dispatchAllInvocationEvents();
plural = getOnlyItem(resources, ResourceType.PLURALS, "my_plural");
resourceValue = plural.getResourceValue(false);
assertNotNull(resourceValue);
assertInstanceOf(resourceValue, PluralsResourceValue.class);
prv = (PluralsResourceValue) resourceValue;
assertEquals(2, prv.getPluralsCount());
assertEquals("@string/hello_two", resourceValue.getValue());
assertEquals("two", prv.getQuantity(0));
assertTrue(generation < resources.getModificationCount());
resetScanCounter();
// Try a second edit.
long generation2 = resources.getModificationCount();
WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
String item = "<item quantity=\"other\">@string/hello_many</item>";
int offset = document.getText().indexOf(item);
document.deleteString(offset, offset + item.length());
documentManager.commitDocument(document);
}
});
plural = getOnlyItem(resources, ResourceType.PLURALS, "my_plural");
resourceValue = plural.getResourceValue(false);
assertNotNull(resourceValue);
assertInstanceOf(resourceValue, PluralsResourceValue.class);
prv = (PluralsResourceValue) resourceValue;
assertEquals(1, prv.getPluralsCount());
assertEquals("@string/hello_two", resourceValue.getValue());
assertEquals("two", prv.getQuantity(0));
assertTrue(generation2 < resources.getModificationCount());
// Shouldn't have done any full file rescans during the above edits
ensureIncremental();
}
use of com.android.ide.common.res2.ResourceItem in project android by JetBrains.
the class ResourceFolderRepositoryTest method testEmptyEdits.
/**
* Check that whitespace edits do not trigger a rescan
*/
public void testEmptyEdits() throws Exception {
resetScanCounter();
VirtualFile file1 = myFixture.copyFileToProject(VALUES1, "res/values/myvalues.xml");
PsiFile psiFile1 = PsiManager.getInstance(getProject()).findFile(file1);
assertNotNull(psiFile1);
final ResourceFolderRepository resources = createRepository();
assertNotNull(resources);
long generation = resources.getModificationCount();
final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(getProject());
final Document document = documentManager.getDocument(psiFile1);
assertNotNull(document);
// Add a space to an attribute name.
WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
final int offset = document.getText().indexOf("app_name");
document.insertString(offset, " ");
documentManager.commitDocument(document);
}
});
// First edit won't be incremental (file -> Psi).
assertTrue(resources.isScanPending(psiFile1));
UIUtil.dispatchAllInvocationEvents();
assertTrue(generation < resources.getModificationCount());
assertFalse(resources.hasResourceItem(ResourceType.STRING, "app_name"));
assertTrue(resources.hasResourceItem(ResourceType.STRING, " app_name"));
resetScanCounter();
// Try a second edit, adding another space.
long generation2 = resources.getModificationCount();
WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
final int offset = document.getText().indexOf(" app_name");
document.insertString(offset, " ");
documentManager.commitDocument(document);
}
});
assertFalse(resources.isScanPending(psiFile1));
assertTrue(generation2 < resources.getModificationCount());
assertTrue(resources.hasResourceItem(ResourceType.STRING, " app_name"));
generation2 = resources.getModificationCount();
ResourceItem item = getOnlyItem(resources, ResourceType.STRING, "title_zoom");
//noinspection ConstantConditions
assertEquals("Zoom", item.getResourceValue(false).getValue());
WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
final int offset = document.getText().indexOf("Zoom");
document.deleteString(offset, offset + "Zoom".length());
documentManager.commitDocument(document);
}
});
assertFalse(resources.isScanPending(psiFile1));
assertTrue(generation2 < resources.getModificationCount());
// Inserting spaces in the middle of a tag shouldn't trigger a rescan or even change the modification count
generation2 = resources.getModificationCount();
WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
final int offset = document.getText().indexOf("Card Flip");
document.insertString(offset, " ");
documentManager.commitDocument(document);
}
});
assertFalse(resources.isScanPending(psiFile1));
assertEquals(generation2, resources.getModificationCount());
ensureIncremental();
}
Aggregations