Search in sources :

Example 1 with ResourceItem

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;
}
Also used : StyleResourceValue(com.android.ide.common.rendering.api.StyleResourceValue) AbstractResourceRepository(com.android.ide.common.res2.AbstractResourceRepository) ItemResourceValue(com.android.ide.common.rendering.api.ItemResourceValue) StyleResourceValue(com.android.ide.common.rendering.api.StyleResourceValue) ItemResourceValue(com.android.ide.common.rendering.api.ItemResourceValue) ResourceValue(com.android.ide.common.rendering.api.ResourceValue) ResourceItem(com.android.ide.common.res2.ResourceItem) ResourceUrl(com.android.ide.common.resources.ResourceUrl) Nullable(com.android.annotations.Nullable)

Example 2 with ResourceItem

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();
}
Also used : VirtualFile(com.intellij.openapi.vfs.VirtualFile) PsiFile(com.intellij.psi.PsiFile) Document(com.intellij.openapi.editor.Document) ResourceItem(com.android.ide.common.res2.ResourceItem) PsiDocumentManager(com.intellij.psi.PsiDocumentManager)

Example 3 with ResourceItem

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();
}
Also used : VirtualFile(com.intellij.openapi.vfs.VirtualFile) Document(com.intellij.openapi.editor.Document) PsiFile(com.intellij.psi.PsiFile) ResourceItem(com.android.ide.common.res2.ResourceItem) PsiDocumentManager(com.intellij.psi.PsiDocumentManager)

Example 4 with ResourceItem

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();
}
Also used : VirtualFile(com.intellij.openapi.vfs.VirtualFile) PsiFile(com.intellij.psi.PsiFile) ResourceItem(com.android.ide.common.res2.ResourceItem) Document(com.intellij.openapi.editor.Document) PsiDocumentManager(com.intellij.psi.PsiDocumentManager)

Example 5 with ResourceItem

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();
}
Also used : VirtualFile(com.intellij.openapi.vfs.VirtualFile) PsiFile(com.intellij.psi.PsiFile) Document(com.intellij.openapi.editor.Document) ResourceItem(com.android.ide.common.res2.ResourceItem) PsiDocumentManager(com.intellij.psi.PsiDocumentManager)

Aggregations

ResourceItem (com.android.ide.common.res2.ResourceItem)83 VirtualFile (com.intellij.openapi.vfs.VirtualFile)44 PsiFile (com.intellij.psi.PsiFile)35 Document (com.intellij.openapi.editor.Document)26 PsiDocumentManager (com.intellij.psi.PsiDocumentManager)26 ResourceValue (com.android.ide.common.rendering.api.ResourceValue)11 FolderConfiguration (com.android.ide.common.resources.configuration.FolderConfiguration)11 XmlTag (com.intellij.psi.xml.XmlTag)11 NotNull (org.jetbrains.annotations.NotNull)11 IOException (java.io.IOException)10 AbstractResourceRepository (com.android.ide.common.res2.AbstractResourceRepository)8 AndroidFacet (org.jetbrains.android.facet.AndroidFacet)8 StyleResourceValue (com.android.ide.common.rendering.api.StyleResourceValue)7 ResourceFile (com.android.ide.common.res2.ResourceFile)7 ResourceType (com.android.resources.ResourceType)7 WriteCommandAction (com.intellij.openapi.command.WriteCommandAction)7 Nullable (org.jetbrains.annotations.Nullable)7 LocalResourceRepository (com.android.tools.idea.res.LocalResourceRepository)6 Project (com.intellij.openapi.project.Project)6 File (java.io.File)6