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