serviceImplementation="org.jetbrains.android.maven.AndroidExternalApklibDependenciesManager"/>
<xml.xmlExtension implementation="org.jetbrains.android.dom.AndroidXmlExtension" order="first"/>
<fileBasedIndex implementation="org.jetbrains.android.AndroidIdIndex"/>
+ <fileBasedIndex implementation="org.jetbrains.android.AndroidValueResourcesIndex"/>
<referencesSearch implementation="org.jetbrains.android.AndroidReferenceSearchExecutor"/>
<projectService serviceInterface="org.jetbrains.android.compiler.AndroidDexCompilerConfiguration"
serviceImplementation="org.jetbrains.android.compiler.AndroidDexCompilerConfiguration"/>
import com.intellij.util.indexing.*;
import com.intellij.util.io.EnumeratorStringDescriptor;
import com.intellij.util.io.KeyDescriptor;
-import org.jetbrains.android.resourceManagers.ResourceManager;
import org.jetbrains.android.util.AndroidResourceUtil;
import org.jetbrains.annotations.NotNull;
if (parent == null || !parent.isDirectory()) {
return false;
}
- final String resourceType = ResourceManager.getResourceTypeByDirName(parent.getName());
+ final String resourceType = AndroidResourceUtil.getResourceTypeByDirName(parent.getName());
if (resourceType == null || !canContainIdDeclaration(resourceType)) {
return false;
}
Collection<Resources> resourceFiles = resManager.getResourceElements();
for (Resources res : resourceFiles) {
for (String valueResourceType : ResourceManager.VALUE_RESOURCE_TYPES) {
- for (ResourceElement valueResource : ResourceManager.getValueResources(valueResourceType, res)) {
+ for (ResourceElement valueResource : ResourceManager.getValueResourcesFromElement(valueResourceType, res)) {
addResource(valueResourceType, valueResource, result);
}
}
public void run() {
List<VirtualFile> resourceSubdirs = resManager.getResourceSubdirs(null);
for (VirtualFile dir : resourceSubdirs) {
- String resType = ResourceManager.getResourceTypeByDirName(dir.getName());
+ String resType = AndroidResourceUtil.getResourceTypeByDirName(dir.getName());
if (resType != null) {
for (VirtualFile resourceFile : dir.getChildren()) {
if (!resourceFile.isDirectory()) {
--- /dev/null
+package org.jetbrains.android;
+
+import com.android.resources.ResourceType;
+import com.intellij.openapi.fileTypes.StdFileTypes;
+import com.intellij.openapi.vfs.LocalFileSystem;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.vfs.ex.temp.TempFileSystem;
+import com.intellij.util.containers.HashMap;
+import com.intellij.util.containers.HashSet;
+import com.intellij.util.indexing.*;
+import com.intellij.util.io.DataExternalizer;
+import com.intellij.util.io.KeyDescriptor;
+import com.intellij.util.xml.NanoXmlUtil;
+import org.jetbrains.android.util.AndroidResourceUtil;
+import org.jetbrains.android.util.ResourceEntry;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.ByteArrayInputStream;
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author Eugene.Kudelevsky
+ */
+public class AndroidValueResourcesIndex extends FileBasedIndexExtension<ResourceEntry, Set<ResourceEntry>> {
+ public static final ID<ResourceEntry, Set<ResourceEntry>> INDEX_ID = ID.create("android.value.resources.index");
+
+ private final FileBasedIndex.InputFilter myInputFilter = new FileBasedIndex.InputFilter() {
+ public boolean acceptInput(final VirtualFile file) {
+ return (file.getFileSystem() == LocalFileSystem.getInstance() || file.getFileSystem() instanceof TempFileSystem) &&
+ file.getFileType() == StdFileTypes.XML;
+ }
+ };
+
+ private final DataIndexer<ResourceEntry, Set<ResourceEntry>, FileContent> myIndexer =
+ new DataIndexer<ResourceEntry, Set<ResourceEntry>, FileContent>() {
+ @NotNull
+ public Map<ResourceEntry, Set<ResourceEntry>> map(FileContent inputData) {
+ final Map<ResourceEntry, Set<ResourceEntry>> result = new HashMap<ResourceEntry, Set<ResourceEntry>>();
+
+ NanoXmlUtil.parse(new ByteArrayInputStream(inputData.getContent()), new NanoXmlUtil.IXMLBuilderAdapter() {
+ private boolean mySeenResources = false;
+ private String myLastTypeAttr = null;
+ private String myLastNameAttr = null;
+
+ @Override
+ public void startElement(String name, String nsPrefix, String nsURI, String systemID, int lineNr) throws Exception {
+ super.startElement(name, nsPrefix, nsURI, systemID, lineNr);
+
+ if (!mySeenResources) {
+ if ("resources".equals(name)) {
+ mySeenResources = true;
+ }
+ else {
+ throw new NanoXmlUtil.ParserStoppedException();
+ }
+ }
+ myLastNameAttr = null;
+ myLastTypeAttr = null;
+ }
+
+ @Override
+ public void addAttribute(String key, String nsPrefix, String nsURI, String value, String type) throws Exception {
+ super.addAttribute(key, nsPrefix, nsURI, value, type);
+
+ if ("name".equals(key)) {
+ myLastNameAttr = value;
+ }
+ else if ("type".equals(key)) {
+ myLastTypeAttr = value;
+ }
+ }
+
+ @Override
+ public void elementAttributesProcessed(String name, String nsPrefix, String nsURI) throws Exception {
+ super.elementAttributesProcessed(name, nsPrefix, nsURI);
+
+ if (myLastNameAttr != null && name != null) {
+ final String resType = "item".equals(name)
+ ? myLastTypeAttr
+ : AndroidResourceUtil.getResourceTypeByTagName(name);
+ if (resType != null && ResourceType.getEnum(resType) != null) {
+ final ResourceEntry entry = new ResourceEntry(resType, myLastNameAttr);
+ result.put(entry, Collections.<ResourceEntry>emptySet());
+
+ final ResourceEntry typeMarkerEntry = createTypeMarkerEntry(resType);
+ Set<ResourceEntry> set = result.get(typeMarkerEntry);
+
+ if (set == null) {
+ set = new HashSet<ResourceEntry>();
+ result.put(typeMarkerEntry, set);
+ }
+ set.add(entry);
+ }
+ }
+ }
+ });
+
+ return result;
+ }
+ };
+
+ public static ResourceEntry createTypeMarkerEntry(String type) {
+ return new ResourceEntry(type, "TYPE_MARKER_RESOURCE");
+ }
+
+ private final KeyDescriptor<ResourceEntry> myKeyDescriptor = new KeyDescriptor<ResourceEntry>() {
+ @Override
+ public void save(DataOutput out, ResourceEntry value) throws IOException {
+ out.writeUTF(value.getType());
+ out.writeUTF(value.getName());
+ }
+
+ @Override
+ public ResourceEntry read(DataInput in) throws IOException {
+ final String resType = in.readUTF();
+ final String resName = in.readUTF();
+ return new ResourceEntry(resType, resName);
+ }
+
+ @Override
+ public int getHashCode(ResourceEntry value) {
+ return value.hashCode();
+ }
+
+ @Override
+ public boolean isEqual(ResourceEntry val1, ResourceEntry val2) {
+ return val1.equals(val2);
+ }
+ };
+
+ private final DataExternalizer<Set<ResourceEntry>> myValueExternalizer = new DataExternalizer<Set<ResourceEntry>>() {
+ @Override
+ public void save(DataOutput out, Set<ResourceEntry> value) throws IOException {
+ out.writeInt(value.size());
+
+ for (ResourceEntry entry : value) {
+ myKeyDescriptor.save(out, entry);
+ }
+ }
+
+ @Nullable
+ @Override
+ public Set<ResourceEntry> read(DataInput in) throws IOException {
+ final int size = in.readInt();
+
+ if (size == 0) {
+ return Collections.emptySet();
+ }
+ final Set<ResourceEntry> result = new HashSet<ResourceEntry>(size);
+
+ for (int i = 0; i < size; i++) {
+ result.add(myKeyDescriptor.read(in));
+ }
+ return result;
+ }
+ };
+
+ @Override
+ public ID<ResourceEntry, Set<ResourceEntry>> getName() {
+ return INDEX_ID;
+ }
+
+ @Override
+ public DataIndexer<ResourceEntry, Set<ResourceEntry>, FileContent> getIndexer() {
+ return myIndexer;
+ }
+
+ @Override
+ public KeyDescriptor<ResourceEntry> getKeyDescriptor() {
+ return myKeyDescriptor;
+ }
+
+ @Override
+ public DataExternalizer<Set<ResourceEntry>> getValueExternalizer() {
+ return myValueExternalizer;
+ }
+
+ @Override
+ public FileBasedIndex.InputFilter getInputFilter() {
+ return myInputFilter;
+ }
+
+ @Override
+ public boolean dependsOnFileContent() {
+ return true;
+ }
+
+ @Override
+ public int getVersion() {
+ return 0;
+ }
+}
import org.jetbrains.android.dom.manifest.ManifestDomFileDescription;
import org.jetbrains.android.facet.AndroidFacet;
import org.jetbrains.android.resourceManagers.ResourceManager;
+import org.jetbrains.android.util.AndroidResourceUtil;
import org.jetbrains.android.util.AndroidUtils;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
return false;
}
- final String resType = ResourceManager.getResourceTypeByDirName(parent.getName());
+ final String resType = AndroidResourceUtil.getResourceTypeByDirName(parent.getName());
if (resType == null) {
return false;
}
return new ValidationInfo("specify module", myModuleCombo);
}
else if (!ResourceFolderType.VALUES.getName().equals(
- ResourceManager.getResourceTypeByDirName(directoryName))) {
+ AndroidResourceUtil.getResourceTypeByDirName(directoryName))) {
return new ValidationInfo("directory name is not appropriate for value resources");
}
return new ValidationInfo(AndroidBundle.message("not.resource.file.error", FileUtil.toSystemDependentName(resFile.getPath())));
}
- for (ResourceElement element : ResourceManager.getValueResources(resourceType.getName(), resources)) {
+ for (ResourceElement element : ResourceManager.getValueResourcesFromElement(resourceType.getName(), resources)) {
if (resourceName.equals(element.getName().getValue())) {
return new ValidationInfo("resource '" + resourceName + "' already exists in " + FileUtil.toSystemDependentName(
resFile.getPath()));
import org.jetbrains.android.facet.AndroidFacet;
import org.jetbrains.android.facet.AndroidRootUtil;
import org.jetbrains.android.sdk.AndroidPlatform;
+import org.jetbrains.android.util.ResourceEntry;
import org.jetbrains.annotations.NotNull;
import java.io.DataInput;
import org.jetbrains.android.sdk.*;
import org.jetbrains.android.util.AndroidBundle;
import org.jetbrains.android.util.AndroidUtils;
+import org.jetbrains.android.util.ResourceEntry;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.android.fileTypes.AndroidIdlFileType;
import org.jetbrains.android.fileTypes.AndroidRenderscriptFileType;
import org.jetbrains.android.util.AndroidUtils;
+import org.jetbrains.android.util.ResourceEntry;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import com.intellij.CommonBundle;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
}
public List<Resources> getResourceElements() {
- return getResourceElements(getAllResourceFiles());
- }
-
- @NotNull
- private Set<VirtualFile> getAllResourceFiles() {
- final Set<VirtualFile> files = new HashSet<VirtualFile>();
-
- for (VirtualFile valueResourceDir : getResourceSubdirs("values")) {
- for (VirtualFile valueResourceFile : valueResourceDir.getChildren()) {
- if (!valueResourceFile.isDirectory() && valueResourceFile.getFileType().equals(StdFileTypes.XML)) {
- files.add(valueResourceFile);
- }
- }
- }
- return files;
+ return getResourceElements(null);
}
@NotNull
@NotNull
public List<ResourceElement> getValueResources(@NotNull final String resourceType) {
- return getValueResources(resourceType, getAllResourceFiles());
+ return getValueResources(resourceType, null);
}
private static void collectResourceDirs(Module module, Set<VirtualFile> result, Set<Module> visited) {
import com.android.sdklib.SdkConstants;
import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtil;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiManager;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.ArrayUtil;
-import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.containers.HashSet;
import com.intellij.util.xml.DomElement;
import org.jetbrains.android.dom.attrs.AttributeDefinitions;
import org.jetbrains.android.dom.resources.Item;
import org.jetbrains.android.dom.resources.ResourceElement;
import org.jetbrains.android.dom.resources.Resources;
import org.jetbrains.android.facet.AndroidFacet;
+import org.jetbrains.android.util.AndroidResourceUtil;
import org.jetbrains.android.util.AndroidUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
return VirtualFile.EMPTY_ARRAY;
}
- @Nullable
- public static String getResourceTypeByDirName(@NotNull String name) {
- int index = name.indexOf('-');
- String type = index >= 0 ? name.substring(0, index) : name;
- return ArrayUtil.find(FILE_RESOURCE_TYPES, type) >= 0 ? type : null;
- }
-
@NotNull
public List<VirtualFile> getResourceSubdirs(@Nullable String resourceType) {
- List<VirtualFile> dirs = new ArrayList<VirtualFile>();
- if (ArrayUtil.find(FILE_RESOURCE_TYPES, resourceType) < 0 && resourceType != null) {
- return dirs;
- }
- VirtualFile[] resourcesDirs = getAllResourceDirs();
- for (VirtualFile resourcesDir : resourcesDirs) {
- if (resourcesDir == null) return dirs;
- if (resourceType == null) {
- ContainerUtil.addAll(dirs, resourcesDir.getChildren());
- }
- else {
- for (VirtualFile child : resourcesDir.getChildren()) {
- String type = getResourceTypeByDirName(child.getName());
- if (resourceType.equals(type)) dirs.add(child);
- }
- }
- }
- return dirs;
+ return AndroidResourceUtil.getResourceSubdirs(resourceType, getAllResourceDirs());
}
@NotNull
return findResourceFiles(resType, null, true);
}
- protected List<Resources> getResourceElements(@NotNull Set<VirtualFile> files) {
+ protected List<Resources> getResourceElements(@Nullable Set<VirtualFile> files) {
return getRootDomElements(Resources.class, files);
}
private <T extends DomElement> List<T> getRootDomElements(@NotNull Class<T> elementType,
- @NotNull Collection<VirtualFile> files) {
+ @Nullable Set<VirtualFile> files) {
final List<T> result = new ArrayList<T>();
- for (VirtualFile file : files) {
- T element = AndroidUtils.loadDomElement(myModule, file, elementType);
- if (element != null) result.add(element);
+ for (VirtualFile file : getAllResourceFiles()) {
+ if ((files == null || files.contains(file)) && file.isValid()) {
+ T element = AndroidUtils.loadDomElement(myModule, file, elementType);
+ if (element != null) result.add(element);
+ }
}
return result;
}
- protected List<ResourceElement> getValueResources(final String resourceType, Set<VirtualFile> files) {
+ @NotNull
+ private Set<VirtualFile> getAllResourceFiles() {
+ final Set<VirtualFile> files = new HashSet<VirtualFile>();
+
+ for (VirtualFile valueResourceDir : getResourceSubdirs("values")) {
+ for (VirtualFile valueResourceFile : valueResourceDir.getChildren()) {
+ if (!valueResourceFile.isDirectory() && valueResourceFile.getFileType().equals(StdFileTypes.XML)) {
+ files.add(valueResourceFile);
+ }
+ }
+ }
+ return files;
+ }
+
+ protected List<ResourceElement> getValueResources(@NotNull final String resourceType, @Nullable Set<VirtualFile> files) {
final List<ResourceElement> result = new ArrayList<ResourceElement>();
Collection<Resources> resourceFiles = getResourceElements(files);
for (final Resources resources : resourceFiles) {
if (!resources.isValid() || myModule.isDisposed() || myModule.getProject().isDisposed()) {
return;
}
- result.addAll(getValueResources(resourceType, resources));
+ result.addAll(getValueResourcesFromElement(resourceType, resources));
}
});
}
if (possibleResDir == null || !isResourceDir(possibleResDir.getVirtualFile())) {
return null;
}
- String type = getResourceTypeByDirName(dir.getName());
+ String type = AndroidResourceUtil.getResourceTypeByDirName(dir.getName());
if (type == null) return null;
return isCorrectFileName(type, file.getName()) ? type : null;
}
public abstract Collection<String> getValueResourceNames(@NotNull final String resourceType);
@NotNull
- public static List<ResourceElement> getValueResources(@NotNull String resourceType, Resources resources) {
+ public static List<ResourceElement> getValueResourcesFromElement(@NotNull String resourceType, Resources resources) {
List<ResourceElement> result = new ArrayList<ResourceElement>();
if (resourceType.equals("string")) {
result.addAll(resources.getStrings());
*/
package org.jetbrains.android.resourceManagers;
-import com.android.resources.ResourceFolderType;
import com.android.resources.ResourceType;
import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.SdkConstants;
-import com.intellij.lang.injection.InjectedLanguageManager;
-import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.*;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.SmartPointerManager;
+import com.intellij.psi.SmartPsiElementPointer;
+import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.xml.*;
import com.intellij.util.containers.HashMap;
import com.intellij.util.containers.HashSet;
+import com.intellij.util.indexing.FileBasedIndex;
import com.intellij.util.xml.ConvertContext;
import org.jetbrains.android.AndroidIdIndex;
+import org.jetbrains.android.AndroidValueResourcesIndex;
import org.jetbrains.android.dom.attrs.AttributeDefinitions;
import org.jetbrains.android.dom.resources.ResourceElement;
-import org.jetbrains.android.dom.resources.Resources;
import org.jetbrains.android.facet.AndroidFacet;
import org.jetbrains.android.sdk.AndroidPlatform;
import org.jetbrains.android.sdk.AndroidTargetData;
import org.jetbrains.android.util.AndroidResourceUtil;
-import org.jetbrains.android.util.AndroidUtils;
+import org.jetbrains.android.util.ResourceEntry;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
private volatile Map<String, List<SmartPsiElementPointer<? extends PsiElement>>> myIdMap;
- private volatile Map<ResourceType, Map<String, Set<VirtualFile>>> myValueResourcesMap;
-
private final AndroidPlatform myPlatform;
public SystemResourceManager(@NotNull Module module, @NotNull AndroidPlatform androidPlatform) {
LOG.error("Unknown resource type " + resourceType);
return Collections.emptyList();
}
- final Map<String, Set<VirtualFile>> map = getValueResourcesMap().get(type);
- return map != null ? map.keySet() : Collections.<String>emptyList();
+ final Set<String> result = new HashSet<String>();
+ final ResourceEntry typeMarkerEntry = AndroidValueResourcesIndex.createTypeMarkerEntry(resourceType);
+ final List<Set<ResourceEntry>> values = FileBasedIndex.getInstance()
+ .getValues(AndroidValueResourcesIndex.INDEX_ID, typeMarkerEntry, GlobalSearchScope.moduleWithLibrariesScope(myModule));
+
+ for (Set<ResourceEntry> entrySet : values) {
+ for (ResourceEntry entry : entrySet) {
+ result.add(entry.getName());
+ }
+ }
+ return result;
}
@Nullable
@Nullable
public synchronized AttributeDefinitions getAttributeDefinitions() {
final AndroidTargetData targetData = myPlatform.getSdk().getTargetData(myPlatform.getTarget());
- return targetData.getAttrDefs(myModule.getProject());
+ return targetData != null ? targetData.getAttrDefs(myModule.getProject()) : null;
}
@Nullable
return doFindIdDeclarations(id, true);
}
- @NotNull
- private synchronized Map<ResourceType, Map<String, Set<VirtualFile>>> getValueResourcesMap() {
- if (myValueResourcesMap == null) {
- myValueResourcesMap = new HashMap<ResourceType, Map<String, Set<VirtualFile>>>();
-
- for (VirtualFile valueResourceDir : getResourceSubdirs(ResourceFolderType.VALUES.getName())) {
- for (final VirtualFile valueResourceFile : valueResourceDir.getChildren()) {
- if (!valueResourceFile.isDirectory() && valueResourceFile.getFileType().equals(StdFileTypes.XML)) {
- ApplicationManager.getApplication().runReadAction(new Runnable() {
- @Override
- public void run() {
- fillValueResourcesMap(valueResourceFile);
- }
- });
- }
- }
- }
- }
- return myValueResourcesMap;
- }
-
- private void fillValueResourcesMap(@NotNull VirtualFile valueResourceFile) {
- final Resources roots = AndroidUtils.loadDomElement(myModule, valueResourceFile, Resources.class);
- if (roots == null) {
- return;
- }
-
- for (ResourceType resType : ResourceType.values()) {
- Map<String, Set<VirtualFile>> map = myValueResourcesMap.get(resType);
-
- if (map == null) {
- map = new HashMap<String, Set<VirtualFile>>();
- myValueResourcesMap.put(resType, map);
- }
-
- for (ResourceElement element : ResourceManager.getValueResources(resType.getName(), roots)) {
- final String name = element.getName().getValue();
-
- if (name != null) {
- Set<VirtualFile> fileSet = map.get(name);
-
- if (fileSet == null) {
- fileSet = new HashSet<VirtualFile>();
- map.put(name, fileSet);
- }
- fileSet.add(valueResourceFile);
- }
- }
- }
-
- PsiManager.getInstance(myModule.getProject()).dropResolveCaches();
- final XmlElement element = roots.getXmlElement();
-
- if (element != null) {
- final PsiFile file = element.getContainingFile();
-
- if (file != null) {
- InjectedLanguageManager.getInstance(myModule.getProject()).dropFileCaches(file);
- }
- }
- }
-
private List<PsiElement> doFindIdDeclarations(@NotNull String id, boolean recreateMapIfCannotResolve) {
final List<SmartPsiElementPointer<? extends PsiElement>> pointers = myIdMap.get(id);
LOG.error("Unknown resource type " + resourceType);
return Collections.emptyList();
}
-
- final Map<String, Set<VirtualFile>> map = getValueResourcesMap().get(type);
- if (map == null) {
- return Collections.emptyList();
- }
- final Set<VirtualFile> fileSet = map.get(resourceName);
- if (fileSet == null) {
+ final Collection<VirtualFile> files = FileBasedIndex.getInstance()
+ .getContainingFiles(AndroidValueResourcesIndex.INDEX_ID, new ResourceEntry(resourceType, resourceName),
+ GlobalSearchScope.moduleWithLibrariesScope(
+ myModule));
+
+ if (files.size() == 0) {
return Collections.emptyList();
}
-
+ final Set<VirtualFile> fileSet = new HashSet<VirtualFile>(files);
final List<ResourceElement> result = new ArrayList<ResourceElement>();
for (ResourceElement element : getValueResources(resourceType, fileSet)) {
if (sdkDir != null) {
addJavaDocAndSources(result, sdkDir);
}
+
+ final String resFolderPath = target.getPath(IAndroidTarget.RESOURCES);
+
+ if (resFolderPath != null) {
+ final VirtualFile resFolder = LocalFileSystem.getInstance().findFileByPath(resFolderPath);
+
+ if (resFolder != null) {
+ result.add(new OrderRoot(resFolder, OrderRootType.CLASSES));
+ }
+ }
return result;
}
import com.intellij.psi.xml.XmlAttributeValue;
import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
+import com.intellij.util.ArrayUtil;
import com.intellij.util.Processor;
+import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashSet;
import com.intellij.util.indexing.FileBasedIndex;
import org.jetbrains.android.AndroidIdIndex;
LocalResourceManager manager = facet.getLocalResourceManager();
String fileResType = manager.getFileResourceType(tag.getContainingFile());
if ("values".equals(fileResType)) {
- String resClassName = tag.getName();
- if (resClassName.equals("item")) {
- resClassName = tag.getAttributeValue("type", null);
- }
- else if (resClassName.equals("declare-styleable")) {
- resClassName = "styleable";
- }
- else if (resClassName.endsWith("-array")) {
- resClassName = "array";
- }
- if (resClassName != null) {
- String resourceName = tag.getAttributeValue("name");
- return resourceName != null ? resClassName : null;
- }
+ return getResourceTypeByValueResourceTag(tag);
+ }
+ return null;
+ }
+
+ @Nullable
+ public static String getResourceTypeByValueResourceTag(XmlTag tag) {
+ String resClassName = tag.getName();
+ resClassName = resClassName.equals("item")
+ ? tag.getAttributeValue("type", null)
+ : getResourceTypeByTagName(resClassName);
+ if (resClassName != null) {
+ final String resourceName = tag.getAttributeValue("name");
+ return resourceName != null ? resClassName : null;
}
return null;
}
+ public static String getResourceTypeByTagName(@NotNull String tagName) {
+ if (tagName.equals("declare-styleable")) {
+ tagName = "styleable";
+ }
+ else if (tagName.endsWith("-array")) {
+ tagName = "array";
+ }
+ return tagName;
+ }
+
@Nullable
public static String getResourceClassName(@NotNull PsiField field) {
PsiClass resourceClass = field.getContainingClass();
}
throw new IllegalArgumentException("Incorrect resource type");
}
+
+ @Nullable
+ public static String getResourceTypeByDirName(@NotNull String name) {
+ int index = name.indexOf('-');
+ String type = index >= 0 ? name.substring(0, index) : name;
+ return ArrayUtil.find(ResourceManager.FILE_RESOURCE_TYPES, type) >= 0 ? type : null;
+ }
+
+ @NotNull
+ public static List<VirtualFile> getResourceSubdirs(@Nullable String resourceType, @NotNull VirtualFile[] resourceDirs) {
+ List<VirtualFile> dirs = new ArrayList<VirtualFile>();
+ if (ArrayUtil.find(ResourceManager.FILE_RESOURCE_TYPES, resourceType) < 0 && resourceType != null) {
+ return dirs;
+ }
+ for (VirtualFile resourcesDir : resourceDirs) {
+ if (resourcesDir == null) return dirs;
+ if (resourceType == null) {
+ ContainerUtil.addAll(dirs, resourcesDir.getChildren());
+ }
+ else {
+ for (VirtualFile child : resourcesDir.getChildren()) {
+ String type = getResourceTypeByDirName(child.getName());
+ if (resourceType.equals(type)) dirs.add(child);
+ }
+ }
+ }
+ return dirs;
+ }
}
-package org.jetbrains.android.compiler;
+package org.jetbrains.android.util;
import org.jetbrains.annotations.NotNull;
private final String myType;
private final String myName;
- ResourceEntry(@NotNull String type, @NotNull String name) {
+ public ResourceEntry(@NotNull String type, @NotNull String name) {
myType = type;
myName = name;
}
--- /dev/null
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ style="<error>@android:style/unknownStyle</error>">
+</LinearLayout>
\ No newline at end of file
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.roots.OrderRootType;
import com.intellij.openapi.vfs.JarFileSystem;
+import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.testFramework.builders.JavaModuleFixtureBuilder;
import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase;
VirtualFile androidJar = JarFileSystem.getInstance().findFileByPath(androidJarPath);
sdkModificator.addRoot(androidJar, OrderRootType.CLASSES);
+ VirtualFile resFolder = LocalFileSystem.getInstance().findFileByPath(sdkPath + "/platforms/android-1.5/data/res");
+ sdkModificator.addRoot(resFolder, OrderRootType.CLASSES);
+
AndroidSdkAdditionalData data = new AndroidSdkAdditionalData(sdk);
AndroidSdk sdkObject = AndroidSdk.parse(sdkPath, new EmptySdkLog());
data.setBuildTarget(sdkObject.findTargetByName("Android 1.5"));
doTestHighlighting("layoutAttrs2.xml");
}
+ public void testCheckLayoutAttrs3() throws Throwable {
+ doTestHighlighting("layoutAttrs3.xml");
+ }
+
public void testUnknownAttribute() throws Throwable {
doTestHighlighting("hl1.xml");
}