From b5b78c0ae5fb49867e9e4458bd95d7a60baf0eca Mon Sep 17 00:00:00 2001 From: Tor Norbye Date: Thu, 6 Dec 2012 10:30:51 -0800 Subject: Support layout aliases properly Change-Id: I3c1dac7809a225118b69f1557a42051e96011198 --- .../eclipse/adt/internal/build/AaptQuickFix.java | 3 +- .../eclipse/adt/internal/editors/Hyperlinks.java | 38 +--- .../layout/configuration/ConfigurationChooser.java | 3 +- .../layout/configuration/ConfigurationMatcher.java | 6 +- .../editors/layout/gle2/RenderPreview.java | 3 +- .../core/RenameResourceXmlTextAction.java | 4 +- .../adt/internal/resources/ResourceHelper.java | 36 +--- .../core/RenameResourceParticipantTest.java | 4 +- .../adt/internal/resources/ResourceHelperTest.java | 16 -- sdk_common/.settings/org.moreunit.prefs | 4 + .../ide/common/resources/ResourceRepository.java | 194 ++++++++++++++++++--- sdk_common/tests/.settings/org.moreunit.prefs | 4 + .../common/resources/ResourceRepositoryTest.java | 45 +++++ 13 files changed, 240 insertions(+), 120 deletions(-) create mode 100644 sdk_common/.settings/org.moreunit.prefs create mode 100644 sdk_common/tests/.settings/org.moreunit.prefs create mode 100644 sdk_common/tests/src/com/android/ide/common/resources/ResourceRepositoryTest.java diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/AaptQuickFix.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/AaptQuickFix.java index defaca6..98a1fab 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/AaptQuickFix.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/build/AaptQuickFix.java @@ -20,6 +20,7 @@ import static com.android.SdkConstants.ANDROID_URI; import static com.android.SdkConstants.XMLNS_ANDROID; import static com.android.SdkConstants.XMLNS_URI; +import com.android.ide.common.resources.ResourceRepository; import com.android.ide.eclipse.adt.AdtConstants; import com.android.ide.eclipse.adt.AdtPlugin; import com.android.ide.eclipse.adt.AdtUtils; @@ -343,7 +344,7 @@ public class AaptQuickFix implements IMarkerResolutionGenerator2, IQuickAssistPr } private void perform() { - Pair resource = ResourceHelper.parseResource(mResource); + Pair resource = ResourceRepository.parseResource(mResource); ResourceType type = resource.getFirst(); String name = resource.getSecond(); String value = ""; //$NON-NLS-1$ diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/Hyperlinks.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/Hyperlinks.java index 23846a3..0e46255 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/Hyperlinks.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/Hyperlinks.java @@ -26,7 +26,6 @@ import static com.android.SdkConstants.ATTR_CONTEXT; import static com.android.SdkConstants.ATTR_ID; import static com.android.SdkConstants.ATTR_NAME; import static com.android.SdkConstants.ATTR_ON_CLICK; -import static com.android.SdkConstants.ATTR_REF_PREFIX; import static com.android.SdkConstants.CLASS_ACTIVITY; import static com.android.SdkConstants.EXT_XML; import static com.android.SdkConstants.FD_DOCS; @@ -36,13 +35,13 @@ import static com.android.SdkConstants.FN_RESOURCE_CLASS; import static com.android.SdkConstants.NEW_ID_PREFIX; import static com.android.SdkConstants.PREFIX_RESOURCE_REF; import static com.android.SdkConstants.PREFIX_THEME_REF; -import static com.android.SdkConstants.RESOURCE_CLZ_ATTR; import static com.android.SdkConstants.STYLE_RESOURCE_PREFIX; import static com.android.SdkConstants.TAG_RESOURCES; import static com.android.SdkConstants.TAG_STYLE; import static com.android.SdkConstants.TOOLS_URI; import static com.android.SdkConstants.VIEW; import static com.android.SdkConstants.VIEW_FRAGMENT; +import static com.android.ide.common.resources.ResourceRepository.parseResource; import static com.android.xml.AndroidManifest.ATTRIBUTE_NAME; import static com.android.xml.AndroidManifest.ATTRIBUTE_PACKAGE; import static com.android.xml.AndroidManifest.NODE_ACTIVITY; @@ -1154,41 +1153,6 @@ public class Hyperlinks { } /** - * Parse a resource reference or a theme reference and return the individual - * parts - * - * @param url the url to parse - * @return a pair which represents the resource type and name - */ - public static Pair parseResource(String url) { - if (url.startsWith(PREFIX_THEME_REF)) { - String remainder = url.substring(PREFIX_THEME_REF.length()); - if (url.startsWith(ATTR_REF_PREFIX)) { - url = PREFIX_RESOURCE_REF + url.substring(1); - return ResourceHelper.parseResource(url); - } - int colon = url.indexOf(':'); - if (colon != -1) { - // Convert from ?android:progressBarStyleBig to ?android:attr/progressBarStyleBig - if (remainder.indexOf('/', colon) == -1) { - remainder = remainder.substring(0, colon) + RESOURCE_CLZ_ATTR + '/' - + remainder.substring(colon); - } - url = PREFIX_RESOURCE_REF + remainder; - return ResourceHelper.parseResource(url); - } else { - int slash = url.indexOf('/'); - if (slash == -1) { - url = PREFIX_RESOURCE_REF + RESOURCE_CLZ_ATTR + '/' + remainder; - return ResourceHelper.parseResource(url); - } - } - } - - return ResourceHelper.parseResource(url); - } - - /** * Computes hyperlinks to resource definitions for resource urls (e.g. * {@code @android:string/ok} or {@code @layout/foo}. May create multiple links. * @param range TBD diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationChooser.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationChooser.java index a81ddc8..c11268c 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationChooser.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationChooser.java @@ -62,7 +62,6 @@ import com.android.ide.eclipse.adt.internal.resources.manager.ProjectResources; import com.android.ide.eclipse.adt.internal.resources.manager.ResourceManager; import com.android.ide.eclipse.adt.internal.sdk.AndroidTargetData; import com.android.ide.eclipse.adt.internal.sdk.Sdk; -import com.android.resources.ResourceFolderType; import com.android.resources.ResourceType; import com.android.resources.ScreenOrientation; import com.android.sdklib.AndroidVersion; @@ -2072,7 +2071,7 @@ public class ConfigurationChooser extends Composite */ public boolean isBestMatchFor(IFile file, FolderConfiguration config) { ResourceFile match = mResources.getMatchingFile(mEditedFile.getName(), - ResourceFolderType.LAYOUT, config); + ResourceType.LAYOUT, config); if (match != null) { return match.getFile().equals(mEditedFile); } diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationMatcher.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationMatcher.java index 096fa6f..5dfcdb8 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationMatcher.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/configuration/ConfigurationMatcher.java @@ -38,7 +38,7 @@ import com.android.ide.eclipse.adt.internal.sdk.Sdk; import com.android.ide.eclipse.adt.io.IFileWrapper; import com.android.resources.Density; import com.android.resources.NightMode; -import com.android.resources.ResourceFolderType; +import com.android.resources.ResourceType; import com.android.resources.ScreenOrientation; import com.android.resources.ScreenSize; import com.android.resources.UiMode; @@ -145,7 +145,7 @@ public class ConfigurationMatcher { */ public boolean isCurrentFileBestMatchFor(FolderConfiguration config) { ResourceFile match = mResources.getMatchingFile(mEditedFile.getName(), - ResourceFolderType.LAYOUT, config); + ResourceType.LAYOUT, config); if (match != null) { return match.getFile().equals(mEditedFile); @@ -687,7 +687,7 @@ public class ConfigurationMatcher { } String name = editedFile.getName(); FolderConfiguration config = chooser.getConfiguration().getFullConfig(); - ResourceFile match = resources.getMatchingFile(name, ResourceFolderType.LAYOUT, config); + ResourceFile match = resources.getMatchingFile(name, ResourceType.LAYOUT, config); if (match != null) { // In Eclipse, the match's file is always an instance of IFileWrapper diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/RenderPreview.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/RenderPreview.java index 496173a..07baaeb 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/RenderPreview.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/RenderPreview.java @@ -56,7 +56,6 @@ import com.android.ide.eclipse.adt.internal.sdk.Sdk; import com.android.ide.eclipse.adt.io.IFileWrapper; import com.android.io.IAbstractFile; import com.android.resources.Density; -import com.android.resources.ResourceFolderType; import com.android.resources.ResourceType; import com.android.resources.ScreenOrientation; import com.android.sdklib.IAndroidTarget; @@ -384,7 +383,7 @@ public class RenderPreview implements IJobChangeListener { ProjectResources resources = chooser.getResources(); if (resources != null) { ResourceFile best = resources.getMatchingFile(editedFile.getName(), - ResourceFolderType.LAYOUT, config); + ResourceType.LAYOUT, config); if (best != null) { IAbstractFile file = best.getFile(); if (file instanceof IFileWrapper) { diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/RenameResourceXmlTextAction.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/RenameResourceXmlTextAction.java index 8d52114..4ca7837 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/RenameResourceXmlTextAction.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/refactorings/core/RenameResourceXmlTextAction.java @@ -24,8 +24,8 @@ import static com.android.SdkConstants.TAG_ITEM; import com.android.annotations.NonNull; import com.android.annotations.Nullable; +import com.android.ide.common.resources.ResourceRepository; import com.android.ide.eclipse.adt.AdtPlugin; -import com.android.ide.eclipse.adt.internal.editors.Hyperlinks; import com.android.ide.eclipse.adt.internal.editors.layout.gle2.DomUtilities; import com.android.resources.ResourceType; import com.android.utils.Pair; @@ -173,7 +173,7 @@ public final class RenameResourceXmlTextAction extends Action { return null; } - return Hyperlinks.parseResource(url); + return ResourceRepository.parseResource(url); } } } catch (BadLocationException e) { diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/ResourceHelper.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/ResourceHelper.java index 9695318..978980b 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/ResourceHelper.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/resources/ResourceHelper.java @@ -34,6 +34,7 @@ import static com.android.ide.eclipse.adt.AdtConstants.WS_SEP; import com.android.ide.common.rendering.api.ResourceValue; import com.android.ide.common.resources.ResourceDeltaKind; +import com.android.ide.common.resources.ResourceRepository; import com.android.ide.common.resources.ResourceResolver; import com.android.ide.common.resources.configuration.CountryCodeQualifier; import com.android.ide.common.resources.configuration.DensityQualifier; @@ -180,39 +181,6 @@ public class ResourceHelper { } /** - * Return the resource type of the given url, and the resource name - * - * @param url the resource url to be parsed - * @return a pair of the resource type and the resource name - */ - public static Pair parseResource(String url) { - if (!url.startsWith(PREFIX_RESOURCE_REF)) { - return null; - } - int typeEnd = url.indexOf('/', 1); - if (typeEnd == -1) { - return null; - } - int nameBegin = typeEnd + 1; - - // Skip @ and @+ - int typeBegin = url.startsWith("@+") ? 2 : 1; //$NON-NLS-1$ - - int colon = url.lastIndexOf(':', typeEnd); - if (colon != -1) { - typeBegin = colon + 1; - } - String typeName = url.substring(typeBegin, typeEnd); - ResourceType type = ResourceType.getEnum(typeName); - if (type == null) { - return null; - } - String name = url.substring(nameBegin); - - return Pair.of(type, name); - } - - /** * Is this a resource that can be defined in any file within the "values" folder? *

* Some resource types can be defined both as a separate XML file as well @@ -281,7 +249,7 @@ public class ResourceHelper { return false; } - Pair parsed = parseResource(resource); + Pair parsed = ResourceRepository.parseResource(resource); if (parsed != null) { ResourceType type = parsed.getFirst(); String name = parsed.getSecond(); diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/refactorings/core/RenameResourceParticipantTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/refactorings/core/RenameResourceParticipantTest.java index d3459b8..b7793bb 100644 --- a/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/refactorings/core/RenameResourceParticipantTest.java +++ b/eclipse/plugins/com.android.ide.eclipse.tests/src/com/android/ide/eclipse/adt/internal/refactorings/core/RenameResourceParticipantTest.java @@ -16,7 +16,7 @@ package com.android.ide.eclipse.adt.internal.refactorings.core; import com.android.annotations.NonNull; -import com.android.ide.eclipse.adt.internal.editors.Hyperlinks; +import com.android.ide.common.resources.ResourceRepository; import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper; import com.android.resources.ResourceType; import com.android.utils.Pair; @@ -366,7 +366,7 @@ public class RenameResourceParticipantTest extends RefactoringTestBase { if (resource instanceof String) { String url = (String) resource; assert url.startsWith("@") : resource; - Pair pair = Hyperlinks.parseResource(url); + Pair pair = ResourceRepository.parseResource(url); assertNotNull(url, pair); ResourceType type = pair.getFirst(); String currentName = pair.getSecond(); diff --git a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/resources/ResourceHelperTest.java b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/resources/ResourceHelperTest.java index f90f437..de4e591 100644 --- a/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/resources/ResourceHelperTest.java +++ b/eclipse/plugins/com.android.ide.eclipse.tests/unittests/com/android/ide/eclipse/adt/internal/resources/ResourceHelperTest.java @@ -16,9 +16,6 @@ package com.android.ide.eclipse.adt.internal.resources; -import static com.android.resources.ResourceType.DIMEN; -import static com.android.resources.ResourceType.LAYOUT; - import com.android.ide.common.resources.ResourceDeltaKind; import com.android.ide.common.resources.configuration.FolderConfiguration; import com.android.ide.common.resources.configuration.ResourceQualifier; @@ -123,19 +120,6 @@ public class ResourceHelperTest extends TestCase { assertNull(ResourceHelper.getResourceDeltaKind(IResourceDelta.ADDED_PHANTOM)); } - public void testParseResource() { - assertNull(ResourceHelper.parseResource("")); - assertNull(ResourceHelper.parseResource("not_a_resource")); - - assertEquals(LAYOUT, ResourceHelper.parseResource("@layout/foo").getFirst()); - assertEquals(DIMEN, ResourceHelper.parseResource("@dimen/foo").getFirst()); - assertEquals(DIMEN, ResourceHelper.parseResource("@android:dimen/foo").getFirst()); - assertEquals("foo", ResourceHelper.parseResource("@layout/foo").getSecond()); - assertEquals("foo", ResourceHelper.parseResource("@dimen/foo").getSecond()); - assertEquals("foo", ResourceHelper.parseResource("@android:dimen/foo").getSecond()); - } - - public void testIsFileBasedResourceType() throws Exception { assertTrue(ResourceHelper.isFileBasedResourceType(ResourceType.ANIMATOR)); assertTrue(ResourceHelper.isFileBasedResourceType(ResourceType.LAYOUT)); diff --git a/sdk_common/.settings/org.moreunit.prefs b/sdk_common/.settings/org.moreunit.prefs new file mode 100644 index 0000000..b1e7a57 --- /dev/null +++ b/sdk_common/.settings/org.moreunit.prefs @@ -0,0 +1,4 @@ +eclipse.preferences.version=1 +org.moreunit.prefixes= +org.moreunit.unitsourcefolder=sdk_common\:src\:sdk_common-tests\:src +org.moreunit.useprojectsettings=true diff --git a/sdk_common/src/com/android/ide/common/resources/ResourceRepository.java b/sdk_common/src/com/android/ide/common/resources/ResourceRepository.java index 02c61d1..542409d 100755 --- a/sdk_common/src/com/android/ide/common/resources/ResourceRepository.java +++ b/sdk_common/src/com/android/ide/common/resources/ResourceRepository.java @@ -16,6 +16,11 @@ package com.android.ide.common.resources; +import static com.android.SdkConstants.ATTR_REF_PREFIX; +import static com.android.SdkConstants.PREFIX_RESOURCE_REF; +import static com.android.SdkConstants.PREFIX_THEME_REF; +import static com.android.SdkConstants.RESOURCE_CLZ_ATTR; + import com.android.SdkConstants; import com.android.annotations.NonNull; import com.android.annotations.Nullable; @@ -30,7 +35,9 @@ import com.android.io.IAbstractResource; import com.android.resources.FolderTypeRelationship; import com.android.resources.ResourceFolderType; import com.android.resources.ResourceType; +import com.android.utils.Pair; +import java.io.File; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -510,39 +517,126 @@ public abstract class ResourceRepository { } /** - * Returns the {@link ResourceFile} matching the given name, {@link ResourceFolderType} and - * configuration. - *

This only works with files generating one resource named after the file (for instance, - * layouts, bitmap based drawable, xml, anims). + * Returns the {@link ResourceFile} matching the given name, + * {@link ResourceFolderType} and configuration. + *

+ * This only works with files generating one resource named after the file + * (for instance, layouts, bitmap based drawable, xml, anims). + * + * @param name the resource name or file name + * @param type the folder type search for + * @param config the folder configuration to match for * @return the matching file or null if no match was found. */ @Nullable - public ResourceFile getMatchingFile(@NonNull String name, @NonNull ResourceFolderType type, + public ResourceFile getMatchingFile( + @NonNull String name, + @NonNull ResourceFolderType type, @NonNull FolderConfiguration config) { - ensureInitialized(); + List types = FolderTypeRelationship.getRelatedResourceTypes(type); + for (ResourceType t : types) { + if (t == ResourceType.ID) { + continue; + } + ResourceFile match = getMatchingFile(name, type, config); + if (match != null) { + return match; + } + } - // get the folders for the given type - List folders = mFolderMap.get(type); + return null; + } - // look for folders containing a file with the given name. - ArrayList matchingFolders = new ArrayList(folders.size()); + /** + * Returns the {@link ResourceFile} matching the given name, + * {@link ResourceType} and configuration. + *

+ * This only works with files generating one resource named after the file + * (for instance, layouts, bitmap based drawable, xml, anims). + * + * @param name the resource name or file name + * @param type the folder type search for + * @param config the folder configuration to match for + * @return the matching file or null if no match was found. + */ + @Nullable + public ResourceFile getMatchingFile( + @NonNull String name, + @NonNull ResourceType type, + @NonNull FolderConfiguration config) { + ensureInitialized(); - // remove the folders that do not have a file with the given name. - for (int i = 0 ; i < folders.size(); i++) { - ResourceFolder folder = folders.get(i); + String resourceName = name; + int dot = resourceName.indexOf('.'); + if (dot != -1) { + resourceName = resourceName.substring(0, dot); + } - if (folder.hasFile(name) == true) { - matchingFolders.add(folder); + Map items = mResourceMap.get(type); + if (items != null) { + ResourceItem item = items.get(resourceName); + if (item != null) { + List files = item.getSourceFileList(); + if (files != null) { + if (files.size() > 1) { + ResourceValue value = item.getResourceValue(type, config, + isFrameworkRepository()); + if (value != null) { + String v = value.getValue(); + if (v != null) { + Pair pair = parseResource(v); + if (pair != null) { + return getMatchingFile(pair.getSecond(), pair.getFirst(), + config); + } else { + // Looks like the resource value is pointing to a file + // It's most likely one of the source files for this + // resource item, so check those first + for (ResourceFile f : files) { + if (v.equals(f.getFile().getOsLocation())) { + // Found the file + return f; + } + } + + // No; look up the resource file from the full path + File file = new File(v); + if (file.exists()) { + ResourceFile f = findResourceFile(file); + if (f != null) { + return f; + } + } + } + } + } + } else if (files.size() == 1) { + // Single file: see if it matches + ResourceFile matchingFile = files.get(0); + if (matchingFile.getFolder().getConfiguration().isMatchFor(config)) { + return matchingFile; + } + } + } } } - // from those, get the folder with a config matching the given reference configuration. - Configurable match = config.findMatchingConfigurable(matchingFolders); + return null; + } - // do we have a matching folder? - if (match instanceof ResourceFolder) { - // get the ResourceFile from the filename - return ((ResourceFolder)match).getFile(name); + @Nullable + private ResourceFile findResourceFile(@NonNull File file) { + // Look up the right resource file for this path + String parentName = file.getParentFile().getName(); + IAbstractFolder folder = getResFolder().getFolder(parentName); + if (folder != null) { + ResourceFolder resourceFolder = getResourceFolder(folder); + if (resourceFolder != null) { + ResourceFile resourceFile = resourceFolder.getFile(file.getName()); + if (resourceFile != null) { + return resourceFile; + } + } } return null; @@ -775,5 +869,63 @@ public abstract class ResourceRepository { return null; } + + /** + * Return the resource type of the given url, and the resource name + * + * @param url the resource url to be parsed + * @return a pair of the resource type and the resource name + */ + public static Pair parseResource(String url) { + // Handle theme references + if (url.startsWith(PREFIX_THEME_REF)) { + String remainder = url.substring(PREFIX_THEME_REF.length()); + if (url.startsWith(ATTR_REF_PREFIX)) { + url = PREFIX_RESOURCE_REF + url.substring(1); + return parseResource(url); + } + int colon = url.indexOf(':'); + if (colon != -1) { + // Convert from ?android:progressBarStyleBig to ?android:attr/progressBarStyleBig + if (remainder.indexOf('/', colon) == -1) { + remainder = remainder.substring(0, colon) + RESOURCE_CLZ_ATTR + '/' + + remainder.substring(colon); + } + url = PREFIX_RESOURCE_REF + remainder; + return parseResource(url); + } else { + int slash = url.indexOf('/'); + if (slash == -1) { + url = PREFIX_RESOURCE_REF + RESOURCE_CLZ_ATTR + '/' + remainder; + return parseResource(url); + } + } + } + + if (!url.startsWith(PREFIX_RESOURCE_REF)) { + return null; + } + int typeEnd = url.indexOf('/', 1); + if (typeEnd == -1) { + return null; + } + int nameBegin = typeEnd + 1; + + // Skip @ and @+ + int typeBegin = url.startsWith("@+") ? 2 : 1; //$NON-NLS-1$ + + int colon = url.lastIndexOf(':', typeEnd); + if (colon != -1) { + typeBegin = colon + 1; + } + String typeName = url.substring(typeBegin, typeEnd); + ResourceType type = ResourceType.getEnum(typeName); + if (type == null) { + return null; + } + String name = url.substring(nameBegin); + + return Pair.of(type, name); + } } diff --git a/sdk_common/tests/.settings/org.moreunit.prefs b/sdk_common/tests/.settings/org.moreunit.prefs new file mode 100644 index 0000000..902b677 --- /dev/null +++ b/sdk_common/tests/.settings/org.moreunit.prefs @@ -0,0 +1,4 @@ +eclipse.preferences.version=1 +org.moreunit.prefixes= +org.moreunit.unitsourcefolder=sdk_common-tests\:src\:sdk_common\:src +org.moreunit.useprojectsettings=true diff --git a/sdk_common/tests/src/com/android/ide/common/resources/ResourceRepositoryTest.java b/sdk_common/tests/src/com/android/ide/common/resources/ResourceRepositoryTest.java new file mode 100644 index 0000000..a8b8b1e --- /dev/null +++ b/sdk_common/tests/src/com/android/ide/common/resources/ResourceRepositoryTest.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.ide.common.resources; + +import static com.android.resources.ResourceType.ATTR; +import static com.android.resources.ResourceType.DIMEN; +import static com.android.resources.ResourceType.LAYOUT; +import junit.framework.TestCase; + +@SuppressWarnings("javadoc") +public class ResourceRepositoryTest extends TestCase { + public void testParseResource() { + assertNull(ResourceRepository.parseResource("")); + assertNull(ResourceRepository.parseResource("not_a_resource")); + + assertEquals(LAYOUT, ResourceRepository.parseResource("@layout/foo").getFirst()); + assertEquals(DIMEN, ResourceRepository.parseResource("@dimen/foo").getFirst()); + assertEquals(DIMEN, ResourceRepository.parseResource("@android:dimen/foo").getFirst()); + assertEquals("foo", ResourceRepository.parseResource("@layout/foo").getSecond()); + assertEquals("foo", ResourceRepository.parseResource("@dimen/foo").getSecond()); + assertEquals("foo", ResourceRepository.parseResource("@android:dimen/foo").getSecond()); + + assertEquals(ATTR, ResourceRepository.parseResource("?attr/foo").getFirst()); + assertEquals("foo", ResourceRepository.parseResource("?attr/foo").getSecond()); + + assertEquals(ATTR, ResourceRepository.parseResource("?foo").getFirst()); + assertEquals("foo", ResourceRepository.parseResource("?foo").getSecond()); + + assertEquals(ATTR, ResourceRepository.parseResource("?android:foo").getFirst()); + assertEquals("foo", ResourceRepository.parseResource("?android:foo").getSecond()); + } +} -- cgit v1.1