Merge remote-tracking branch 'origin/master'

This commit is contained in:
Maxim.Medvedev
2012-01-31 17:26:52 +04:00
19 changed files with 514 additions and 435 deletions
+1
View File
@@ -173,6 +173,7 @@
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"/>
@@ -21,19 +21,16 @@ 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.psi.PsiFile;
import com.intellij.psi.XmlRecursiveElementVisitor;
import com.intellij.psi.xml.XmlAttributeValue;
import com.intellij.psi.xml.XmlFile;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.HashMap;
import com.intellij.util.indexing.*;
import com.intellij.util.io.EnumeratorStringDescriptor;
import com.intellij.util.io.KeyDescriptor;
import org.jetbrains.android.resourceManagers.ResourceManager;
import com.intellij.util.text.CharArrayUtil;
import com.intellij.util.xml.NanoXmlUtil;
import org.jetbrains.android.util.AndroidResourceUtil;
import org.jetbrains.annotations.NotNull;
import java.io.ByteArrayInputStream;
import java.util.Collections;
import java.util.Map;
@@ -47,53 +44,41 @@ public class AndroidIdIndex extends ScalarIndexExtension<String> {
private static final FileBasedIndex.InputFilter INPUT_FILTER = new FileBasedIndex.InputFilter() {
public boolean acceptInput(final VirtualFile file) {
if ((file.getFileSystem() == LocalFileSystem.getInstance() || file.getFileSystem() instanceof TempFileSystem) &&
file.getFileType() == StdFileTypes.XML) {
VirtualFile parent = file.getParent();
if (parent == null || !parent.isDirectory()) {
return false;
}
final String resourceType = ResourceManager.getResourceTypeByDirName(parent.getName());
if (resourceType == null || !canContainIdDeclaration(resourceType)) {
return false;
}
parent = parent.getParent();
return parent != null && SdkConstants.FD_RES.equals(parent.getName());
}
return false;
return (file.getFileSystem() == LocalFileSystem.getInstance() || file.getFileSystem() instanceof TempFileSystem) &&
file.getFileType() == StdFileTypes.XML;
}
};
private static final DataIndexer<String, Void, FileContent> INDEXER = new DataIndexer<String, Void, FileContent>() {
@NotNull
public Map<String, Void> map(FileContent inputData) {
PsiFile file = inputData.getPsiFile();
if (file instanceof XmlFile) {
final HashMap<String, Void> ids = new HashMap<String, Void>();
file.accept(new XmlRecursiveElementVisitor() {
@Override
public void visitXmlAttributeValue(XmlAttributeValue attributeValue) {
if (AndroidResourceUtil.isIdDeclaration(attributeValue)) {
String id = AndroidResourceUtil.getResourceNameByReferenceText(attributeValue.getValue());
if (id != null) {
if (ids.isEmpty()) {
ids.put(MARKER, null);
}
ids.put(id, null);
final CharSequence content = inputData.getContentAsText();
if (content == null || CharArrayUtil.indexOf(content, SdkConstants.NS_RESOURCES, 0) == -1) {
return Collections.emptyMap();
}
final HashMap<String, Void> ids = new HashMap<String, Void>();
NanoXmlUtil.parse(new ByteArrayInputStream(inputData.getContent()), new NanoXmlUtil.IXMLBuilderAdapter() {
@Override
public void addAttribute(String key, String nsPrefix, String nsURI, String value, String type) throws Exception {
super.addAttribute(key, nsPrefix, nsURI, value, type);
if (AndroidResourceUtil.isIdDeclaration(value)) {
String id = AndroidResourceUtil.getResourceNameByReferenceText(value);
if (id != null) {
if (ids.isEmpty()) {
ids.put(MARKER, null);
}
ids.put(id, null);
}
}
});
return ids;
}
return Collections.emptyMap();
}
});
return ids;
}
};
private static boolean canContainIdDeclaration(@NotNull String resType) {
return ArrayUtil.find(RES_TYPES_CONTAINING_ID_DECLARATIONS, resType) >= 0;
}
@Override
public ID<String, Void> getName() {
return INDEX_ID;
@@ -121,6 +106,6 @@ public class AndroidIdIndex extends ScalarIndexExtension<String> {
@Override
public int getVersion() {
return 1;
return 2;
}
}
@@ -171,7 +171,7 @@ public class AndroidResourcesLineMarkerProvider implements LineMarkerProvider {
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);
}
}
@@ -197,7 +197,7 @@ public class AndroidResourcesLineMarkerProvider implements LineMarkerProvider {
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()) {
@@ -264,7 +264,7 @@ public class AndroidResourcesLineMarkerProvider implements LineMarkerProvider {
if (resourceMap != null) {
targets = new ArrayList<PsiElement>();
if (resType.equals("id")) {
AndroidResourceUtil.collectIdDeclarations(fieldName, manager.getModule(), targets);
manager.collectIdDeclarations(fieldName, targets);
}
List<PsiElement> resources = resourceMap.get(new MyResourceEntry(fieldName, resType));
if (resources != null) {
@@ -0,0 +1,203 @@
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.text.CharArrayUtil;
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) {
if (CharArrayUtil.indexOf(inputData.getContentAsText(), "<resources", 0) < 0) {
return Collections.emptyMap();
}
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;
}
}
@@ -36,6 +36,7 @@ import gnu.trove.THashMap;
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;
@@ -107,7 +108,7 @@ public class AndroidXmlSchemaProvider extends XmlSchemaProvider {
return false;
}
final String resType = ResourceManager.getResourceTypeByDirName(parent.getName());
final String resType = AndroidResourceUtil.getResourceTypeByDirName(parent.getName());
if (resType == null) {
return false;
}
@@ -141,7 +141,7 @@ public class CreateXmlResourceDialog extends DialogWrapper {
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");
}
@@ -196,7 +196,7 @@ public class CreateXmlResourceDialog extends DialogWrapper {
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()));
@@ -58,6 +58,7 @@ import org.jetbrains.android.fileTypes.AndroidRenderscriptFileType;
import org.jetbrains.android.resourceManagers.LocalResourceManager;
import org.jetbrains.android.sdk.AndroidPlatform;
import org.jetbrains.android.util.AndroidUtils;
import org.jetbrains.android.util.ResourceEntry;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -8,6 +8,7 @@ import com.intellij.util.containers.HashSet;
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;
@@ -80,6 +80,7 @@ import org.jetbrains.android.resourceManagers.SystemResourceManager;
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;
@@ -32,6 +32,7 @@ import org.jetbrains.android.dom.manifest.Manifest;
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;
@@ -20,7 +20,6 @@ import com.android.AndroidConstants;
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;
@@ -28,14 +27,10 @@ import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.xml.XmlFile;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.HashSet;
import com.intellij.util.indexing.FileBasedIndex;
import com.intellij.util.xml.GenericAttributeValue;
import org.jetbrains.android.AndroidFileTemplateProvider;
import org.jetbrains.android.AndroidIdIndex;
import org.jetbrains.android.actions.CreateResourceFileAction;
import org.jetbrains.android.dom.attrs.AttributeDefinitions;
import org.jetbrains.android.dom.resources.Attr;
@@ -52,7 +47,6 @@ import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
@@ -101,21 +95,7 @@ public class LocalResourceManager extends ResourceManager {
}
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
@@ -124,24 +104,9 @@ public class LocalResourceManager extends ResourceManager {
return AndroidRootUtil.getResourceOverlayDirs(getModule());
}
@NotNull
@Override
public Collection<String> getValueResourceNames(@NotNull String resourceType) {
final List<String> result = new ArrayList<String>();
for (ResourceElement element : getValueResources(resourceType)) {
final String name = element.getName().getValue();
if (name != null) {
result.add(name);
}
}
return result;
}
@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) {
@@ -193,43 +158,6 @@ public class LocalResourceManager extends ResourceManager {
myAttrDefs = null;
}
@Nullable
public List<PsiElement> findIdDeclarations(@NotNull String id) {
List<PsiElement> declarations = new ArrayList<PsiElement>();
AndroidResourceUtil.collectIdDeclarations(id, myModule, declarations);
return declarations;
}
@NotNull
public Collection<String> getIds() {
List<String> result = new ArrayList<String>();
Project project = myModule.getProject();
GlobalSearchScope scope = GlobalSearchScope.projectScope(myModule.getProject());
for (String key : FileBasedIndex.getInstance().getAllKeys(AndroidIdIndex.INDEX_ID, project)) {
if (!AndroidIdIndex.MARKER.equals(key)) {
if (FileBasedIndex.getInstance().getValues(AndroidIdIndex.INDEX_ID, key, scope).size() > 0) {
result.add(key);
}
}
}
return result;
}
@NotNull
@Override
public List<ResourceElement> findValueResources(@NotNull String resourceType,
@NotNull String resourceName,
boolean distinguishDelimetersInName) {
List<ResourceElement> elements = new ArrayList<ResourceElement>();
for (ResourceElement element : getValueResources(resourceType)) {
GenericAttributeValue<String> name = element.getName();
if (name != null && equal(resourceName, name.getValue(), distinguishDelimetersInName)) {
elements.add(element);
}
}
return elements;
}
@NotNull
public List<Attr> findAttrs(@NotNull String name) {
List<Attr> list = new ArrayList<Attr>();
@@ -15,28 +15,37 @@
*/
package org.jetbrains.android.resourceManagers;
import com.android.resources.ResourceType;
import com.android.sdklib.SdkConstants;
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.module.ModuleUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
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.containers.ContainerUtil;
import com.intellij.util.containers.HashMap;
import com.intellij.util.containers.HashSet;
import com.intellij.util.indexing.FileBasedIndex;
import com.intellij.util.xml.DomElement;
import org.jetbrains.android.AndroidIdIndex;
import org.jetbrains.android.AndroidValueResourcesIndex;
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.android.util.ResourceEntry;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -48,6 +57,8 @@ import static java.util.Collections.addAll;
* @author coyote
*/
public abstract class ResourceManager {
private static final Logger LOG = Logger.getInstance("#org.jetbrains.android.resourceManagers.LocalResourceManager");
public static final Set<String> REFERABLE_RESOURCE_TYPES = new HashSet<String>();
public static final String[] FILE_RESOURCE_TYPES = new String[]{"drawable", "anim", "layout", "values", "menu", "xml", "raw", "color"};
public static final String[] VALUE_RESOURCE_TYPES =
@@ -93,33 +104,9 @@ public abstract class ResourceManager {
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
@@ -193,21 +180,37 @@ public abstract class ResourceManager {
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 : getAllValueResourceFiles()) {
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
protected Set<VirtualFile> getAllValueResourceFiles() {
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) {
@@ -217,7 +220,7 @@ public abstract class ResourceManager {
if (!resources.isValid() || myModule.isDisposed() || myModule.getProject().isDisposed()) {
return;
}
result.addAll(getValueResources(resourceType, resources));
result.addAll(getValueResourcesFromElement(resourceType, resources));
}
});
}
@@ -245,7 +248,7 @@ public abstract class ResourceManager {
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;
}
@@ -267,10 +270,51 @@ public abstract class ResourceManager {
}
@NotNull
public abstract Collection<String> getValueResourceNames(@NotNull final String resourceType);
public Collection<String> getValueResourceNames(@NotNull final String resourceType) {
final ResourceType type = ResourceType.getEnum(resourceType);
if (type == null) {
LOG.error("Unknown resource type " + resourceType);
return Collections.emptyList();
}
final FileBasedIndex index = FileBasedIndex.getInstance();
final ResourceEntry typeMarkerEntry = AndroidValueResourcesIndex.createTypeMarkerEntry(resourceType);
final GlobalSearchScope scope = GlobalSearchScope.allScope(myModule.getProject());
final Map<VirtualFile, Set<ResourceEntry>> file2resourceSet = new HashMap<VirtualFile, Set<ResourceEntry>>();
for (Set<ResourceEntry> entrySet : index.getValues(AndroidValueResourcesIndex.INDEX_ID, typeMarkerEntry, scope)) {
for (ResourceEntry entry : entrySet) {
final Collection<VirtualFile> files = index.getContainingFiles(AndroidValueResourcesIndex.INDEX_ID, entry, scope);
for (VirtualFile file : files) {
Set<ResourceEntry> resourcesInFile = file2resourceSet.get(file);
if (resourcesInFile == null) {
resourcesInFile = new HashSet<ResourceEntry>();
file2resourceSet.put(file, resourcesInFile);
}
resourcesInFile.add(entry);
}
}
}
final Set<String> result = new HashSet<String>();
for (VirtualFile file : getAllValueResourceFiles()) {
final Set<ResourceEntry> entries = file2resourceSet.get(file);
if (entries != null) {
for (ResourceEntry entry : entries) {
result.add(entry.getName());
}
}
}
return result;
}
@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());
@@ -312,19 +356,91 @@ public abstract class ResourceManager {
// searches only declarations such as "@+id/..."
@Nullable
public abstract List<PsiElement> findIdDeclarations(@NotNull String id);
public List<PsiElement> findIdDeclarations(@NotNull String id) {
List<PsiElement> declarations = new ArrayList<PsiElement>();
collectIdDeclarations(id, declarations);
return declarations;
}
@NotNull
public abstract Collection<String> getIds();
public Collection<String> getIds() {
final Project project = myModule.getProject();
final GlobalSearchScope scope = GlobalSearchScope.allScope(myModule.getProject());
final FileBasedIndex index = FileBasedIndex.getInstance();
final Map<VirtualFile, Set<String>> file2ids = new HashMap<VirtualFile, Set<String>>();
for (String key : index.getAllKeys(AndroidIdIndex.INDEX_ID, project)) {
if (!AndroidIdIndex.MARKER.equals(key)) {
if (index.getValues(AndroidIdIndex.INDEX_ID, key, scope).size() > 0) {
for (VirtualFile file : index.getContainingFiles(AndroidIdIndex.INDEX_ID, key, scope)) {
Set<String> ids = file2ids.get(file);
if (ids == null) {
ids = new HashSet<String>();
file2ids.put(file, ids);
}
ids.add(key);
}
}
}
}
final Set<String> result = new HashSet<String>();
for (VirtualFile resSubdir : getResourceSubdirsToSearchIds()) {
for (VirtualFile resFile : resSubdir.getChildren()) {
final Set<String> ids = file2ids.get(resFile);
if (ids != null) {
result.addAll(ids);
}
}
}
return result;
}
@NotNull
protected List<VirtualFile> getResourceSubdirsToSearchIds() {
final List<VirtualFile> resSubdirs = new ArrayList<VirtualFile>();
resSubdirs.addAll(getResourceSubdirs(ResourceType.LAYOUT.getName()));
resSubdirs.addAll(getResourceSubdirs(ResourceType.MENU.getName()));
return resSubdirs;
}
public List<ResourceElement> findValueResources(@NotNull String resType, @NotNull String resName) {
return findValueResources(resType, resName, true);
}
@NotNull
public abstract List<ResourceElement> findValueResources(@NotNull String resourceType,
@NotNull String resourceName,
boolean distinguishDelimetersInName);
public List<ResourceElement> findValueResources(@NotNull String resourceType,
@NotNull String resourceName,
boolean distinguishDelimetersInName) {
final ResourceType type = ResourceType.getEnum(resourceType);
if (type == null) {
LOG.error("Unknown resource type " + resourceType);
return Collections.emptyList();
}
final Collection<VirtualFile> files = FileBasedIndex.getInstance()
.getContainingFiles(AndroidValueResourcesIndex.INDEX_ID, new ResourceEntry(resourceType, resourceName),
GlobalSearchScope.allScope(myModule.getProject()));
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)) {
final String name = element.getName().getValue();
if (equal(resourceName, name, distinguishDelimetersInName)) {
result.add(element);
}
}
return result;
}
public static boolean isInResourceSubdirectory(@NotNull PsiFile file, @Nullable String resourceType) {
file = file.getOriginalFile();
@@ -382,4 +498,34 @@ public abstract class ResourceManager {
private static boolean containsAndroidJar(@NotNull PsiDirectory psiDirectory) {
return psiDirectory.findFile(SdkConstants.FN_FRAMEWORK_LIBRARY) != null;
}
public void collectIdDeclarations(@NotNull final String id, final List<PsiElement> targets) {
final Collection<VirtualFile> files =
FileBasedIndex.getInstance().getContainingFiles(AndroidIdIndex.INDEX_ID, id, GlobalSearchScope.allScope(myModule.getProject()));
final Set<VirtualFile> fileSet = new HashSet<VirtualFile>(files);
final PsiManager psiManager = PsiManager.getInstance(myModule.getProject());
for (VirtualFile subdir : getResourceSubdirsToSearchIds()) {
for (VirtualFile file : subdir.getChildren()) {
if (fileSet.contains(file)) {
final PsiFile psiFile = psiManager.findFile(file);
if (psiFile instanceof XmlFile) {
psiFile.accept(new XmlRecursiveElementVisitor() {
@Override
public void visitXmlAttributeValue(XmlAttributeValue attributeValue) {
if (AndroidResourceUtil.isIdDeclaration(attributeValue)) {
final String idInAttr = AndroidResourceUtil.getResourceNameByReferenceText(attributeValue.getValue());
if (id.equals(idInAttr)) {
targets.add(attributeValue);
}
}
}
});
}
}
}
}
}
}
@@ -15,46 +15,22 @@
*/
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.xml.*;
import com.intellij.util.containers.HashMap;
import com.intellij.util.containers.HashSet;
import com.intellij.util.xml.ConvertContext;
import org.jetbrains.android.AndroidIdIndex;
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.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
/**
* @author coyote
*/
public class SystemResourceManager extends ResourceManager {
private static final Logger LOG = Logger.getInstance("#org.jetbrains.android.resourceManagers.SystemResourceManager");
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) {
@@ -74,19 +50,6 @@ public class SystemResourceManager extends ResourceManager {
return LocalFileSystem.getInstance().findFileByPath(resPath);
}
@NotNull
@Override
public Collection<String> getValueResourceNames(@NotNull String resourceType) {
final ResourceType type = ResourceType.getEnum(resourceType);
if (type == null) {
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();
}
@Nullable
public static SystemResourceManager getInstance(@NotNull ConvertContext context) {
AndroidFacet facet = AndroidFacet.getInstance(context);
@@ -96,193 +59,6 @@ public class SystemResourceManager extends ResourceManager {
@Nullable
public synchronized AttributeDefinitions getAttributeDefinitions() {
final AndroidTargetData targetData = myPlatform.getSdk().getTargetData(myPlatform.getTarget());
return targetData.getAttrDefs(myModule.getProject());
}
@Nullable
public List<PsiElement> findIdDeclarations(@NotNull String id) {
if (myIdMap == null) {
myIdMap = createIdMap();
return doFindIdDeclarations(id, false);
}
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);
if (pointers == null || pointers.size() == 0) {
return Collections.emptyList();
}
final List<PsiElement> result = new ArrayList<PsiElement>();
for (SmartPsiElementPointer<? extends PsiElement> pointer : pointers) {
final PsiElement element = pointer.getElement();
if (element != null) {
result.add(element);
}
else if (recreateMapIfCannotResolve) {
myIdMap = createIdMap();
return doFindIdDeclarations(id, false);
}
}
return result;
}
@NotNull
public Collection<String> getIds() {
if (myIdMap == null) {
myIdMap = createIdMap();
}
return myIdMap.keySet();
}
@NotNull
@Override
public List<ResourceElement> findValueResources(@NotNull String resourceType,
@NotNull String resourceName,
boolean distinguishDelimetersInName) {
final ResourceType type = ResourceType.getEnum(resourceType);
if (type == null) {
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) {
return Collections.emptyList();
}
final List<ResourceElement> result = new ArrayList<ResourceElement>();
for (ResourceElement element : getValueResources(resourceType, fileSet)) {
final String name = element.getName().getValue();
if (equal(resourceName, name, distinguishDelimetersInName)) {
result.add(element);
}
}
return result;
}
@NotNull
public Map<String, List<SmartPsiElementPointer<? extends PsiElement>>> createIdMap() {
Map<String, List<SmartPsiElementPointer<? extends PsiElement>>> result = new HashMap<String, List<SmartPsiElementPointer<? extends PsiElement>>>();
fillIdMap(result);
return result;
}
protected void fillIdMap(@NotNull Map<String, List<SmartPsiElementPointer<? extends PsiElement>>> result) {
for (String resType : AndroidIdIndex.RES_TYPES_CONTAINING_ID_DECLARATIONS) {
List<PsiFile> resFiles = findResourceFiles(resType);
for (PsiFile resFile : resFiles) {
collectIdDeclarations(resFile, result);
}
}
}
protected static void collectIdDeclarations(PsiFile psiFile, Map<String, List<SmartPsiElementPointer<? extends PsiElement>>> result) {
if (psiFile instanceof XmlFile) {
XmlDocument document = ((XmlFile)psiFile).getDocument();
if (document != null) {
XmlTag rootTag = document.getRootTag();
if (rootTag != null) {
fillMapRecursively(rootTag, result);
}
}
}
}
private static void fillMapRecursively(@NotNull XmlTag tag, @NotNull Map<String, List<SmartPsiElementPointer<? extends PsiElement>>> result) {
XmlAttribute idAttr = tag.getAttribute("id", SdkConstants.NS_RESOURCES);
if (idAttr != null) {
XmlAttributeValue idAttrValue = idAttr.getValueElement();
if (idAttrValue != null) {
if (AndroidResourceUtil.isIdDeclaration(idAttrValue)) {
String id = AndroidResourceUtil.getResourceNameByReferenceText(idAttrValue.getValue());
if (id != null) {
List<SmartPsiElementPointer<? extends PsiElement>> list = result.get(id);
if (list == null) {
list = new ArrayList<SmartPsiElementPointer<? extends PsiElement>>();
result.put(id, list);
}
final SmartPointerManager manager = SmartPointerManager.getInstance(tag.getProject());
list.add(manager.createSmartPsiElementPointer(idAttr));
}
}
}
}
for (XmlTag subtag : tag.getSubTags()) {
fillMapRecursively(subtag, result);
}
return targetData != null ? targetData.getAttrDefs(myModule.getProject()) : null;
}
}
@@ -98,6 +98,16 @@ public class AndroidSdkUtils {
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;
}
@@ -24,16 +24,14 @@ import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiUtilBase;
import com.intellij.psi.xml.XmlAttribute;
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;
import org.jetbrains.android.dom.manifest.Manifest;
import org.jetbrains.android.dom.resources.*;
import org.jetbrains.android.facet.AndroidFacet;
@@ -217,24 +215,34 @@ public class AndroidResourceUtil {
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();
@@ -268,7 +276,7 @@ public class AndroidResourceUtil {
if (type != null) {
String name = field.getName();
if (type.equals("id")) {
collectIdDeclarations(name, manager.getModule(), targets);
manager.collectIdDeclarations(name, targets);
}
for (PsiFile file : manager.findResourceFiles(type, name, false)) {
targets.add(file);
@@ -356,28 +364,6 @@ public class AndroidResourceUtil {
return null;
}
public static void collectIdDeclarations(@NotNull final String id, Module module, final List<PsiElement> targets) {
Collection<VirtualFile> files =
FileBasedIndex.getInstance().getContainingFiles(AndroidIdIndex.INDEX_ID, id, GlobalSearchScope.projectScope(module.getProject()));
PsiManager psiManager = PsiManager.getInstance(module.getProject());
for (VirtualFile file : files) {
PsiFile psiFile = psiManager.findFile(file);
if (psiFile instanceof XmlFile) {
psiFile.accept(new XmlRecursiveElementVisitor() {
@Override
public void visitXmlAttributeValue(XmlAttributeValue attributeValue) {
if (isIdDeclaration(attributeValue)) {
String idInAttr = getResourceNameByReferenceText(attributeValue.getValue());
if (id.equals(idInAttr)) {
targets.add(attributeValue);
}
}
}
});
}
}
}
public static boolean isRJavaField(@NotNull PsiFile file, @NotNull PsiField field) {
PsiClass aClass = field.getContainingClass();
if (aClass != null) {
@@ -435,4 +421,32 @@ public class AndroidResourceUtil {
}
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;
}
}
@@ -1,4 +1,4 @@
package org.jetbrains.android.compiler;
package org.jetbrains.android.util;
import org.jetbrains.annotations.NotNull;
@@ -9,7 +9,7 @@ public class ResourceEntry {
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;
}
@@ -0,0 +1,3 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="<error>@android:style/unknownStyle</error>">
</LinearLayout>
@@ -29,6 +29,7 @@ import com.intellij.openapi.roots.ModifiableRootModel;
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;
@@ -151,6 +152,9 @@ public abstract class AndroidTestCase extends 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"));
@@ -83,6 +83,10 @@ public class AndroidLayoutDomTest extends AndroidDomTest {
doTestHighlighting("layoutAttrs2.xml");
}
public void testCheckLayoutAttrs3() throws Throwable {
doTestHighlighting("layoutAttrs3.xml");
}
public void testUnknownAttribute() throws Throwable {
doTestHighlighting("hl1.xml");
}