Search in sources :

Example 6 with AppResourceRepository

use of com.android.tools.idea.res.AppResourceRepository in project android by JetBrains.

the class ResolutionUtils method getFolderConfiguration.

/**
   * Gets the {@link FolderConfiguration} of a ResourceValue
   * e.g. if we resolve a drawable using a mdpi configuration, yet that drawable only exists inside xhdpi, this method will return xhdpi
   * @param configuration the FolderConfiguration that was used for resolving the ResourceValue
   * @return the FolderConfiguration of the ResourceValue
   */
@NotNull
public static FolderConfiguration getFolderConfiguration(@NotNull AndroidFacet facet, @NotNull ResourceValue resolvedValue, @NotNull FolderConfiguration configuration) {
    List<? extends Configurable> configurables;
    if (resolvedValue.isFramework()) {
        ConfigurationManager configurationManager = facet.getConfigurationManager();
        // same as getHighestApiTarget();
        IAndroidTarget target = configurationManager.getDefaultTarget();
        assert target != null;
        ResourceRepository resourceRepository = configurationManager.getResolverCache().getFrameworkResources(configuration, target);
        assert resourceRepository != null;
        ResourceItem resourceItem = resourceRepository.getResourceItem(resolvedValue.getResourceType(), resolvedValue.getName());
        configurables = resourceItem.getSourceFileList();
    } else {
        AppResourceRepository appResourceRepository = facet.getAppResources(true);
        configurables = appResourceRepository.getResourceItem(resolvedValue.getResourceType(), resolvedValue.getName());
    }
    Configurable configurable = configuration.findMatchingConfigurable(configurables);
    assert configurable != null;
    return configurable.getConfiguration();
}
Also used : AppResourceRepository(com.android.tools.idea.res.AppResourceRepository) IAndroidTarget(com.android.sdklib.IAndroidTarget) Configurable(com.android.ide.common.resources.configuration.Configurable) AppResourceRepository(com.android.tools.idea.res.AppResourceRepository) ResourceRepository(com.android.ide.common.resources.ResourceRepository) ResourceItem(com.android.ide.common.resources.ResourceItem) ConfigurationManager(com.android.tools.idea.configurations.ConfigurationManager) NotNull(org.jetbrains.annotations.NotNull)

Example 7 with AppResourceRepository

use of com.android.tools.idea.res.AppResourceRepository in project android by JetBrains.

the class AndroidResourceRenameResourceProcessor method prepareCustomViewRenaming.

private static void prepareCustomViewRenaming(PsiClass cls, String newName, Map<PsiElement, String> allRenames, AndroidFacet facet) {
    AppResourceRepository appResources = AppResourceRepository.getAppResources(facet, true);
    String oldName = cls.getName();
    if (appResources.hasResourceItem(DECLARE_STYLEABLE, oldName)) {
        LocalResourceManager manager = facet.getLocalResourceManager();
        for (PsiElement element : manager.findResourcesByFieldName(STYLEABLE.getName(), oldName)) {
            if (element instanceof XmlAttributeValue) {
                if (element.getParent() instanceof XmlAttribute) {
                    XmlTag tag = ((XmlAttribute) element.getParent()).getParent();
                    String tagName = tag.getName();
                    if (tagName.equals(TAG_DECLARE_STYLEABLE)) {
                        // Rename main styleable field
                        for (PsiField field : AndroidResourceUtil.findResourceFields(facet, STYLEABLE.getName(), oldName, false)) {
                            String escaped = AndroidResourceUtil.getFieldNameByResourceName(newName);
                            allRenames.put(field, escaped);
                        }
                        // Rename dependent attribute fields
                        PsiField[] styleableFields = AndroidResourceUtil.findStyleableAttributeFields(tag, false);
                        if (styleableFields.length > 0) {
                            for (PsiField resField : styleableFields) {
                                String fieldName = resField.getName();
                                String newAttributeName;
                                if (fieldName.startsWith(oldName)) {
                                    newAttributeName = newName + fieldName.substring(oldName.length());
                                } else {
                                    newAttributeName = oldName;
                                }
                                String escaped = AndroidResourceUtil.getFieldNameByResourceName(newAttributeName);
                                allRenames.put(resField, escaped);
                            }
                        }
                    }
                }
            }
        }
    }
}
Also used : XmlAttribute(com.intellij.psi.xml.XmlAttribute) LocalResourceManager(org.jetbrains.android.resourceManagers.LocalResourceManager) AppResourceRepository(com.android.tools.idea.res.AppResourceRepository) XmlAttributeValue(com.intellij.psi.xml.XmlAttributeValue) XmlTag(com.intellij.psi.xml.XmlTag)

Example 8 with AppResourceRepository

use of com.android.tools.idea.res.AppResourceRepository in project android by JetBrains.

the class AndroidResourceRenameResourceProcessor method findExistingNameConflicts.

@Override
public void findExistingNameConflicts(final PsiElement originalElement, String newName, final MultiMap<PsiElement, String> conflicts) {
    ResourceType type = getResourceType(originalElement);
    if (type == null) {
        return;
    }
    PsiElement element = LazyValueResourceElementWrapper.computeLazyElement(originalElement);
    if (element == null) {
        return;
    }
    AndroidFacet facet = AndroidFacet.getInstance(element);
    if (facet == null) {
        return;
    }
    // First check to see if the new name is conflicting with an existing resource
    if (element instanceof PsiFile) {
        // The name of a file resource is the name of the file without the extension.
        // So when dealing with a file, we must first remove the extension in the name
        // before checking if it is already used.
        newName = AndroidCommonUtils.getResourceName(type.getName(), newName);
    }
    AppResourceRepository appResources = AppResourceRepository.getAppResources(facet, true);
    if (appResources.hasResourceItem(type, newName)) {
        boolean foundElements = false;
        PsiField[] resourceFields = AndroidResourceUtil.findResourceFields(facet, type.getName(), newName, true);
        String message = String.format("Resource @%1$s/%2$s already exists", type, newName);
        if (resourceFields.length > 0) {
            // Use find usages to find the actual declaration location such that they can be shown in the conflicts view
            AndroidFindUsagesHandlerFactory factory = new AndroidFindUsagesHandlerFactory();
            if (factory.canFindUsages(originalElement)) {
                FindUsagesHandler handler = factory.createFindUsagesHandler(resourceFields[0], false);
                if (handler != null) {
                    PsiElement[] elements = ArrayUtil.mergeArrays(handler.getPrimaryElements(), handler.getSecondaryElements());
                    for (PsiElement e : elements) {
                        if (e instanceof LightElement) {
                            // AndroidLightField does not work in the conflicts view; UsageInfo throws NPE
                            continue;
                        }
                        conflicts.putValue(e, message);
                        foundElements = true;
                    }
                }
            }
        }
        if (!foundElements) {
            conflicts.putValue(originalElement, message);
        }
    }
    // Next see if the renamed resource is also defined externally, in which case we should ask the
    // user if they really want to continue. Despite the name of this method ("findExistingNameConflicts")
    // and the dialog used to show the message (ConflictsDialog), this isn't conflict specific; the
    // dialog title simply says "Problems Detected" and the label for the text view is "The following
    // problems were found". We need to use this because it's the only facility in the rename processor
    // which lets us ask the user whether to continue and to have the answer either bail out of the operation
    // or to resume.
    // See if this is a locally defined resource (you can't rename fields from libraries such as appcompat)
    // e.g. ?attr/listPreferredItemHeightSmall
    String name = getResourceName(originalElement);
    if (name != null) {
        Project project = facet.getModule().getProject();
        List<ResourceItem> all = appResources.getResourceItem(type, name);
        if (all == null) {
            all = Collections.emptyList();
        }
        List<ResourceItem> local = ProjectResourceRepository.getProjectResources(facet, true).getResourceItem(type, name);
        if (local == null) {
            local = Collections.emptyList();
        }
        HtmlBuilder builder = null;
        if (local.size() == 0 && all.size() > 0) {
            builder = new HtmlBuilder(new StringBuilder(300));
            builder.add("Resource is also only defined in external libraries and cannot be renamed.");
        } else if (local.size() < all.size()) {
            // This item is also defined in one of the libraries, not just locally: we can't rename it. Should we
            // display some sort of warning?
            builder = new HtmlBuilder(new StringBuilder(300));
            builder.add("The resource ").beginBold().add(PREFIX_RESOURCE_REF).add(type.getName()).add("/").add(name).endBold();
            builder.add(" is defined outside of the project (in one of the libraries) and cannot ");
            builder.add("be updated. This can change the behavior of the application.").newline().newline();
            builder.add("Are you sure you want to do this?");
        }
        if (builder != null) {
            appendUnhandledReferences(project, facet, all, local, builder);
            conflicts.putValue(originalElement, builder.getHtml());
        }
    }
}
Also used : FindUsagesHandler(com.intellij.find.findUsages.FindUsagesHandler) HtmlBuilder(com.android.utils.HtmlBuilder) ResourceType(com.android.resources.ResourceType) AppResourceRepository(com.android.tools.idea.res.AppResourceRepository) AndroidFacet(org.jetbrains.android.facet.AndroidFacet) LightElement(com.intellij.psi.impl.light.LightElement) Project(com.intellij.openapi.project.Project) ResourceItem(com.android.ide.common.res2.ResourceItem)

Example 9 with AppResourceRepository

use of com.android.tools.idea.res.AppResourceRepository in project android by JetBrains.

the class ModuleClassLoaderTest method testAARPriority.

/**
   * Verifies that the AAR generated R classes are given priority vs the build generated files. This is important in cases like support
   * library upgrades/downgrades. In those cases, the build generated file, will be outdated so it shouldn't be used by the ModuleClassLoader.
   * By preferring the AAR geneated versions, we make sure we are always up-to-date.
   * See <a href="http://b.android.com/229382">229382</a>
   */
public void testAARPriority() throws ClassNotFoundException, IOException {
    LayoutLibrary layoutLibrary = mock(LayoutLibrary.class);
    Module module = myFixture.getModule();
    File tmpDir = Files.createTempDir();
    File outputDir = new File(tmpDir, CompilerModuleExtension.PRODUCTION + "/" + module.getName() + "/test");
    assertTrue(FileUtil.createDirectory(outputDir));
    CompilerProjectExtension.getInstance(getProject()).setCompilerOutputUrl(pathToIdeaUrl(tmpDir));
    generateRClass("test", new File(outputDir, "R.class"));
    AppResourceRepository appResources = AppResourceRepository.getAppResources(module, true);
    ResourceClassRegistry rClassRegistry = ResourceClassRegistry.get(module.getProject());
    rClassRegistry.addLibrary(appResources, "test");
    AtomicBoolean noSuchField = new AtomicBoolean(false);
    ApplicationManager.getApplication().runReadAction(() -> {
        ModuleClassLoader loader = ModuleClassLoader.get(layoutLibrary, module);
        try {
            Class<?> rClass = loader.loadClass("test.R");
            rClass.getDeclaredField("ID");
        } catch (NoSuchFieldException e) {
            noSuchField.set(true);
        } catch (ClassNotFoundException e) {
            fail("Unexpected exception " + e.getLocalizedMessage());
        }
    });
    assertTrue(noSuchField.get());
}
Also used : AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) LayoutLibrary(com.android.ide.common.rendering.LayoutLibrary) AppResourceRepository(com.android.tools.idea.res.AppResourceRepository) Module(com.intellij.openapi.module.Module) ResourceClassRegistry(com.android.tools.idea.res.ResourceClassRegistry) File(java.io.File)

Example 10 with AppResourceRepository

use of com.android.tools.idea.res.AppResourceRepository in project android by JetBrains.

the class ViewLoaderTest method testRClassLoad.

public void testRClassLoad() throws ClassNotFoundException {
    RenderLogger logger = RenderService.get(myFacet).createLogger();
    ViewLoader viewLoader = new ViewLoader(myLayoutLib, myFacet, logger, null);
    // No AppResourceRepository exists prior to calling loadAndParseRClass. It will get created during the call.
    assertNull(AppResourceRepository.getAppResources(myModule, false));
    viewLoader.loadAndParseRClass("org.jetbrains.android.uipreview.ViewLoaderTest$R");
    AppResourceRepository appResources = AppResourceRepository.getAppResources(myModule, false);
    assertNotNull(appResources);
    assertEquals(0x7f0a000e, appResources.getResourceId(ResourceType.STRING, "app_name").intValue());
    // This value wasn't read from the R class since it wasn't final. The value must be a dynamic ID (they start at 0x7fff0000)
    assertEquals(0x7fff0001, appResources.getResourceId(ResourceType.STRING, "not_final").intValue());
}
Also used : RenderLogger(com.android.tools.idea.rendering.RenderLogger) AppResourceRepository(com.android.tools.idea.res.AppResourceRepository)

Aggregations

AppResourceRepository (com.android.tools.idea.res.AppResourceRepository)17 NotNull (org.jetbrains.annotations.NotNull)5 AndroidFacet (org.jetbrains.android.facet.AndroidFacet)4 ResourceValue (com.android.ide.common.rendering.api.ResourceValue)3 FolderConfiguration (com.android.ide.common.resources.configuration.FolderConfiguration)3 ResourceType (com.android.resources.ResourceType)3 Module (com.intellij.openapi.module.Module)3 File (java.io.File)3 LayoutLibrary (com.android.ide.common.rendering.LayoutLibrary)2 ResourceItem (com.android.ide.common.res2.ResourceItem)2 ResourceItem (com.android.ide.common.resources.ResourceItem)2 ResourceRepository (com.android.ide.common.resources.ResourceRepository)2 IAndroidTarget (com.android.sdklib.IAndroidTarget)2 ResourceClassRegistry (com.android.tools.idea.res.ResourceClassRegistry)2 VisibleForTesting (com.google.common.annotations.VisibleForTesting)2 VirtualFile (com.intellij.openapi.vfs.VirtualFile)2 PsiFile (com.intellij.psi.PsiFile)2 XmlTag (com.intellij.psi.xml.XmlTag)2 VisibleForTesting (com.android.annotations.VisibleForTesting)1 HardwareConfigHelper (com.android.ide.common.rendering.HardwareConfigHelper)1