mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
augment of R and Manifest classes, do not generate the constants anymore
This commit is contained in:
@@ -220,6 +220,7 @@
|
||||
<renameHandler implementation="org.jetbrains.android.AndroidRenameHandler" order="first"/>
|
||||
|
||||
<codeInsight.unresolvedReferenceQuickFixProvider implementation="org.jetbrains.android.inspections.AndroidQuickFixProvider"/>
|
||||
<lang.psiAugmentProvider implementation="org.jetbrains.android.augment.AndroidPsiAugmentProvider"/>
|
||||
|
||||
<packaging.elementType implementation="org.jetbrains.android.compiler.artifact.AndroidFinalPackageElementType"/>
|
||||
<packaging.sourceItemProvider implementation="org.jetbrains.android.compiler.artifact.AndroidSourceItemsProvider"/>
|
||||
|
||||
@@ -0,0 +1,338 @@
|
||||
package org.jetbrains.android.augment;
|
||||
|
||||
import com.intellij.lang.java.JavaLanguage;
|
||||
import com.intellij.navigation.ItemPresentation;
|
||||
import com.intellij.navigation.ItemPresentationProviders;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.PsiClassImplUtil;
|
||||
import com.intellij.psi.impl.PsiImplUtil;
|
||||
import com.intellij.psi.impl.light.LightElement;
|
||||
import com.intellij.psi.impl.light.LightEmptyImplementsList;
|
||||
import com.intellij.psi.impl.light.LightModifierList;
|
||||
import com.intellij.psi.impl.light.LightTypeParameterListBuilder;
|
||||
import com.intellij.psi.javadoc.PsiDocComment;
|
||||
import com.intellij.psi.scope.PsiScopeProcessor;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Eugene.Kudelevsky
|
||||
*/
|
||||
public abstract class AndroidLightClass extends LightElement implements PsiClass, SyntheticElement {
|
||||
private final PsiClass myContainingClass;
|
||||
protected final String myName;
|
||||
|
||||
protected AndroidLightClass(@NotNull PsiClass context, @NotNull String name) {
|
||||
super(context.getManager(), JavaLanguage.INSTANCE);
|
||||
myContainingClass = context;
|
||||
myName = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AndroidRClass";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getQualifiedName() {
|
||||
return myContainingClass.getQualifiedName() + '.' + myName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInterface() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAnnotationType() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnum() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiReferenceList getExtendsList() {
|
||||
return new LightEmptyImplementsList(myManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiReferenceList getImplementsList() {
|
||||
return new LightEmptyImplementsList(myManager);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiClassType[] getExtendsListTypes() {
|
||||
return PsiClassType.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiClassType[] getImplementsListTypes() {
|
||||
return PsiClassType.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiClass getSuperClass() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiClass[] getInterfaces() {
|
||||
return PsiClass.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiClass[] getSupers() {
|
||||
return PsiClass.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiClassType[] getSuperTypes() {
|
||||
return PsiClassType.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public abstract PsiField[] getFields();
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiMethod[] getMethods() {
|
||||
return PsiMethod.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiMethod[] getConstructors() {
|
||||
return PsiMethod.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiClass[] getInnerClasses() {
|
||||
return PsiClass.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiClassInitializer[] getInitializers() {
|
||||
return PsiClassInitializer.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiField[] getAllFields() {
|
||||
return getFields();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiMethod[] getAllMethods() {
|
||||
return PsiMethod.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiClass[] getAllInnerClasses() {
|
||||
return PsiClass.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiField findFieldByName(@NonNls String name, boolean checkBases) {
|
||||
final PsiField[] fields = getFields();
|
||||
for (final PsiField field : fields) {
|
||||
if (name.equals(field.getName())) return field;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiMethod findMethodBySignature(PsiMethod patternMethod, boolean checkBases) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiMethod[] findMethodsBySignature(PsiMethod patternMethod, boolean checkBases) {
|
||||
return PsiMethod.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiMethod[] findMethodsByName(@NonNls String name, boolean checkBases) {
|
||||
return PsiMethod.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<Pair<PsiMethod, PsiSubstitutor>> findMethodsAndTheirSubstitutorsByName(@NonNls String name, boolean checkBases) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<Pair<PsiMethod, PsiSubstitutor>> getAllMethodsAndTheirSubstitutors() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiClass findInnerClassByName(@NonNls String name, boolean checkBases) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiElement getLBrace() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiElement getRBrace() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiIdentifier getNameIdentifier() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElement getNavigationElement() {
|
||||
return myContainingClass;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiElement getScope() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInheritor(@NotNull PsiClass baseClass, boolean checkDeep) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInheritorDeep(PsiClass baseClass, @Nullable PsiClass classToByPass) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiClass getContainingClass() {
|
||||
return myContainingClass;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<HierarchicalMethodSignature> getVisibleSignatures() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiElement setName(@NonNls @NotNull String name) throws IncorrectOperationException {
|
||||
throw new IncorrectOperationException("Cannot change the name of " + getQualifiedName() + " class");
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiDocComment getDocComment() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDeprecated() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasTypeParameters() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiTypeParameterList getTypeParameterList() {
|
||||
return new LightTypeParameterListBuilder(myManager, getLanguage());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiTypeParameter[] getTypeParameters() {
|
||||
return PsiTypeParameter.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiModifierList getModifierList() {
|
||||
return new LightModifierList(myManager, getLanguage(), PsiModifier.PUBLIC, PsiModifier.STATIC, PsiModifier.FINAL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasModifierProperty(@PsiModifier.ModifierConstant @NonNls @NotNull String name) {
|
||||
final PsiModifierList list = getModifierList();
|
||||
return list != null && list.hasModifierProperty(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return myName;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isVisibilitySupported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Icon getElementIcon(@IconFlags int flags) {
|
||||
return PsiClassImplUtil.getClassIcon(flags, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEquivalentTo(PsiElement another) {
|
||||
return PsiClassImplUtil.isClassEquivalentTo(this, another);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public SearchScope getUseScope() {
|
||||
return PsiImplUtil.getMemberUseScope(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemPresentation getPresentation() {
|
||||
return ItemPresentationProviders.getItemPresentation(this);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiFile getContainingFile() {
|
||||
final PsiClass containingClass = getContainingClass();
|
||||
return containingClass == null ? null : containingClass.getContainingFile();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiElement getParent() {
|
||||
return myContainingClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean processDeclarations(@NotNull final PsiScopeProcessor processor,
|
||||
@NotNull final ResolveState state,
|
||||
final PsiElement lastParent,
|
||||
@NotNull final PsiElement place) {
|
||||
return PsiClassImplUtil.processDeclarationsInClass(this, processor, state, null, lastParent, place, false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package org.jetbrains.android.augment;
|
||||
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiType;
|
||||
import com.intellij.psi.impl.light.LightFieldBuilder;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author Eugene.Kudelevsky
|
||||
*/
|
||||
class AndroidLightField extends LightFieldBuilder {
|
||||
private final AndroidLightClass myContext;
|
||||
|
||||
public AndroidLightField(@NotNull String name,
|
||||
@NotNull AndroidLightClass context,
|
||||
@NotNull PsiType type) {
|
||||
super(name, type, context);
|
||||
myContext = context;
|
||||
setContainingClass(context);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiFile getContainingFile() {
|
||||
return myContext.getContainingFile();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package org.jetbrains.android.augment;
|
||||
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.augment.PsiAugmentProvider;
|
||||
import org.jetbrains.android.dom.converters.ResourceReferenceConverter;
|
||||
import org.jetbrains.android.facet.AndroidFacet;
|
||||
import org.jetbrains.android.util.AndroidResourceUtil;
|
||||
import org.jetbrains.android.util.AndroidUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Eugene.Kudelevsky
|
||||
*/
|
||||
public class AndroidPsiAugmentProvider extends PsiAugmentProvider {
|
||||
@SuppressWarnings("unchecked")
|
||||
@NotNull
|
||||
@Override
|
||||
public <Psi extends PsiElement> List<Psi> getAugments(@NotNull PsiElement element, @NotNull Class<Psi> type) {
|
||||
if (type != PsiClass.class ||
|
||||
!(element instanceof PsiClass)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
final PsiClass aClass = (PsiClass)element;
|
||||
final String className = aClass.getName();
|
||||
|
||||
if (!AndroidUtils.R_CLASS_NAME.equals(className) &&
|
||||
!AndroidUtils.MANIFEST_CLASS_NAME.equals(className)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
final AndroidFacet facet = AndroidFacet.getInstance(element);
|
||||
if (facet == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
final PsiFile containingFile = element.getContainingFile();
|
||||
if (containingFile == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
if (AndroidResourceUtil.isRJavaFile(facet, containingFile)) {
|
||||
final Set<String> types = ResourceReferenceConverter.getResourceTypesInCurrentModule(facet);
|
||||
final List<Psi> result = new ArrayList<Psi>(types.size());
|
||||
|
||||
for (String resType : types) {
|
||||
final AndroidLightClass resClass = new ResourceTypeClass(facet, resType, aClass);
|
||||
result.add((Psi)resClass);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
else if (AndroidResourceUtil.isManifestJavaFile(facet, containingFile)) {
|
||||
return Arrays.asList((Psi)new PermissionClass(facet, aClass),
|
||||
(Psi)new PermissionGroupClass(facet, aClass));
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package org.jetbrains.android.augment;
|
||||
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.util.CachedValue;
|
||||
import com.intellij.psi.util.CachedValueProvider;
|
||||
import com.intellij.psi.util.CachedValuesManager;
|
||||
import com.intellij.psi.util.PsiModificationTracker;
|
||||
import com.intellij.psi.xml.XmlElement;
|
||||
import org.jetbrains.android.dom.manifest.Manifest;
|
||||
import org.jetbrains.android.facet.AndroidFacet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Eugene.Kudelevsky
|
||||
*/
|
||||
abstract class ManifestInnerClass extends AndroidLightClass {
|
||||
private CachedValue<PsiField[]> myFieldsCache;
|
||||
private final AndroidFacet myFacet;
|
||||
|
||||
ManifestInnerClass(@NotNull AndroidFacet facet, @NotNull String name, @NotNull PsiClass context) {
|
||||
super(context, name);
|
||||
myFacet = facet;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiField[] getFields() {
|
||||
if (myFieldsCache == null) {
|
||||
myFieldsCache = CachedValuesManager.getManager(getProject()).createCachedValue(new CachedValueProvider<PsiField[]>() {
|
||||
@Override
|
||||
public Result<PsiField[]> compute() {
|
||||
final Manifest manifest = myFacet.getManifest();
|
||||
if (manifest == null) {
|
||||
return Result.create(PsiField.EMPTY_ARRAY, PsiModificationTracker.MODIFICATION_COUNT);
|
||||
}
|
||||
final List<Pair<String, String>> pairs = doGetFields(manifest);
|
||||
|
||||
final PsiField[] result = new PsiField[pairs.size()];
|
||||
final PsiClassType stringType = PsiType.getJavaLangString(myManager, GlobalSearchScope.allScope(getProject()));
|
||||
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(getProject());
|
||||
int i = 0;
|
||||
for (Pair<String, String> pair : pairs) {
|
||||
final AndroidLightField field = new AndroidLightField(pair.getFirst(), ManifestInnerClass.this, stringType);
|
||||
field.setModifiers(PsiModifier.PUBLIC, PsiModifier.STATIC);
|
||||
field.setInitializer(factory.createExpressionFromText("\"" + pair.getSecond() + "\"", field));
|
||||
result[i++] = field;
|
||||
}
|
||||
|
||||
final XmlElement xmlElement = manifest.getXmlElement();
|
||||
final PsiFile psiManifestFile = xmlElement != null ? xmlElement.getContainingFile() : null;
|
||||
return Result.create(result, psiManifestFile != null ? psiManifestFile : PsiModificationTracker.MODIFICATION_COUNT);
|
||||
}
|
||||
});
|
||||
}
|
||||
return myFieldsCache.getValue();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected abstract List<Pair<String, String>> doGetFields(@NotNull Manifest manifest);
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package org.jetbrains.android.augment;
|
||||
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import org.jetbrains.android.dom.manifest.Manifest;
|
||||
import org.jetbrains.android.dom.manifest.Permission;
|
||||
import org.jetbrains.android.facet.AndroidFacet;
|
||||
import org.jetbrains.android.util.AndroidResourceUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Eugene.Kudelevsky
|
||||
*/
|
||||
class PermissionClass extends ManifestInnerClass {
|
||||
PermissionClass(@NotNull AndroidFacet facet, @NotNull PsiClass context) {
|
||||
super(facet, "permission", context);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected List<Pair<String, String>> doGetFields(@NotNull Manifest manifest) {
|
||||
final List<Pair<String, String>> result = new ArrayList<Pair<String, String>>();
|
||||
|
||||
for (Permission permission : manifest.getPermissions()) {
|
||||
final String name = permission.getName().getValue();
|
||||
|
||||
if (name != null && name.length() > 0) {
|
||||
final int lastDotIndex = name.lastIndexOf('.');
|
||||
final String lastId = name.substring(lastDotIndex + 1);
|
||||
|
||||
if (lastId.length() > 0) {
|
||||
result.add(Pair.create(AndroidResourceUtil.getFieldNameByResourceName(lastId), name));
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package org.jetbrains.android.augment;
|
||||
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import org.jetbrains.android.dom.manifest.Manifest;
|
||||
import org.jetbrains.android.dom.manifest.PermissionGroup;
|
||||
import org.jetbrains.android.facet.AndroidFacet;
|
||||
import org.jetbrains.android.util.AndroidResourceUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Eugene.Kudelevsky
|
||||
*/
|
||||
public class PermissionGroupClass extends ManifestInnerClass {
|
||||
PermissionGroupClass(@NotNull AndroidFacet facet, @NotNull PsiClass context) {
|
||||
super(facet, "permission_group", context);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected List<Pair<String, String>> doGetFields(@NotNull Manifest manifest) {
|
||||
final List<Pair<String, String>> result = new ArrayList<Pair<String, String>>();
|
||||
|
||||
for (PermissionGroup permissionGroup : manifest.getPermissionGroups()) {
|
||||
final String name = permissionGroup.getName().getValue();
|
||||
|
||||
if (name != null && name.length() > 0) {
|
||||
final int lastDotIndex = name.lastIndexOf('.');
|
||||
final String lastId = name.substring(lastDotIndex + 1);
|
||||
|
||||
if (lastId.length() > 0) {
|
||||
result.add(Pair.create(AndroidResourceUtil.getFieldNameByResourceName(lastId), name));
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package org.jetbrains.android.augment;
|
||||
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.CachedValue;
|
||||
import com.intellij.psi.util.CachedValueProvider;
|
||||
import com.intellij.psi.util.CachedValuesManager;
|
||||
import com.intellij.psi.util.PsiModificationTracker;
|
||||
import org.jetbrains.android.facet.AndroidFacet;
|
||||
import org.jetbrains.android.util.AndroidResourceUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* @author Eugene.Kudelevsky
|
||||
*/
|
||||
class ResourceTypeClass extends AndroidLightClass {
|
||||
private CachedValue<PsiField[]> myFieldsCache;
|
||||
private final AndroidFacet myFacet;
|
||||
|
||||
public ResourceTypeClass(@NotNull AndroidFacet facet, @NotNull String name, @NotNull PsiClass context) {
|
||||
super(context, name);
|
||||
myFacet = facet;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiField[] getFields() {
|
||||
if (myFieldsCache == null) {
|
||||
myFieldsCache = CachedValuesManager.getManager(getProject()).createCachedValue(new CachedValueProvider<PsiField[]>() {
|
||||
@Override
|
||||
public Result<PsiField[]> compute() {
|
||||
final PsiField[] fields = buildResourceFields(myFacet, myName, ResourceTypeClass.this);
|
||||
return Result.create(fields, PsiModificationTracker.MODIFICATION_COUNT);
|
||||
}
|
||||
});
|
||||
}
|
||||
return myFieldsCache.getValue();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static PsiField[] buildResourceFields(@NotNull AndroidFacet facet,
|
||||
@NotNull String resType,
|
||||
@NotNull final AndroidLightClass context) {
|
||||
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(facet.getModule().getProject());
|
||||
final Collection<String> resNames = facet.getLocalResourceManager().getResourceNames(resType);
|
||||
final PsiField[] result = new PsiField[resNames.size()];
|
||||
int i = 0;
|
||||
for (String resName : resNames) {
|
||||
final AndroidLightField field = new AndroidLightField(AndroidResourceUtil.getFieldNameByResourceName(resName), context, PsiType.INT);
|
||||
field.setModifiers(PsiModifier.PUBLIC, PsiModifier.STATIC);
|
||||
field.setInitializer(factory.createExpressionFromText("0", field));
|
||||
result[i++] = field;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -19,10 +19,8 @@ import com.intellij.openapi.vfs.ReadonlyStatusHandler;
|
||||
import com.intellij.openapi.vfs.VfsUtilCore;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.search.FilenameIndex;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import com.intellij.util.containers.HashSet;
|
||||
import org.jetbrains.android.compiler.tools.AndroidApt;
|
||||
import org.jetbrains.android.compiler.tools.AndroidIdl;
|
||||
import org.jetbrains.android.compiler.tools.AndroidRenderscript;
|
||||
import org.jetbrains.android.dom.manifest.Manifest;
|
||||
@@ -33,12 +31,13 @@ import org.jetbrains.android.fileTypes.AndroidRenderscriptFileType;
|
||||
import org.jetbrains.android.sdk.AndroidPlatform;
|
||||
import org.jetbrains.android.util.AndroidBundle;
|
||||
import org.jetbrains.android.util.AndroidCommonUtils;
|
||||
import org.jetbrains.android.util.AndroidCompilerMessageKind;
|
||||
import org.jetbrains.android.util.AndroidUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
@@ -283,36 +282,33 @@ public class AndroidAutogenerator {
|
||||
// Aapt generation can be very long, so we generate it in temp directory first
|
||||
tempOutDir = FileUtil.createTempDirectory("android_apt_autogeneration", "tmp");
|
||||
|
||||
final Map<AndroidCompilerMessageKind, List<String>> messages =
|
||||
AndroidApt.compile(item.myTarget, item.myPlatformToolsRevision, item.myManifestFileOsPath, item.myPackage,
|
||||
tempOutDir.getPath(), item.myResDirOsPaths, ArrayUtil.EMPTY_STRING_ARRAY, item.myNonConstantFields);
|
||||
generateStubClasses(item.myPackage, tempOutDir,
|
||||
AndroidUtils.R_CLASS_NAME,
|
||||
AndroidUtils.MANIFEST_CLASS_NAME);
|
||||
|
||||
if (messages.get(AndroidCompilerMessageKind.ERROR).size() == 0) {
|
||||
for (String genFileRelPath : item.myGenFileRelPath2package.keySet()) {
|
||||
final File srcFile = new File(tempOutDir.getPath() + '/' + genFileRelPath);
|
||||
for (String genFileRelPath : item.myGenFileRelPath2package.keySet()) {
|
||||
final File srcFile = new File(tempOutDir.getPath() + '/' + genFileRelPath);
|
||||
|
||||
if (srcFile.isFile()) {
|
||||
final File dstFile = new File(item.myOutputDirOsPath + '/' + genFileRelPath);
|
||||
if (srcFile.isFile()) {
|
||||
final File dstFile = new File(item.myOutputDirOsPath + '/' + genFileRelPath);
|
||||
|
||||
if (dstFile.exists()) {
|
||||
if (!FileUtil.delete(dstFile)) {
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (module.isDisposed() || module.getProject().isDisposed()) {
|
||||
return;
|
||||
}
|
||||
context.addMessage(CompilerMessageCategory.ERROR,
|
||||
"Cannot delete " + FileUtil.toSystemDependentName(dstFile.getPath()), null, -1, -1);
|
||||
if (dstFile.exists()) {
|
||||
if (!FileUtil.delete(dstFile)) {
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (module.isDisposed() || module.getProject().isDisposed()) {
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
context.addMessage(CompilerMessageCategory.ERROR,
|
||||
"Cannot delete " + FileUtil.toSystemDependentName(dstFile.getPath()), null, -1, -1);
|
||||
}
|
||||
});
|
||||
}
|
||||
FileUtil.rename(srcFile, dstFile);
|
||||
}
|
||||
FileUtil.rename(srcFile, dstFile);
|
||||
}
|
||||
}
|
||||
AndroidCompileUtil.addMessages(context, AndroidCompileUtil.toCompilerMessageCategoryKeys(messages), module);
|
||||
|
||||
for (Map.Entry<String, String> entry : item.myGenFileRelPath2package.entrySet()) {
|
||||
final String path = item.myOutputDirOsPath + '/' + entry.getKey();
|
||||
@@ -328,16 +324,13 @@ public class AndroidAutogenerator {
|
||||
if (genSourceRoot != null) {
|
||||
genSourceRoot.refresh(false, true);
|
||||
}
|
||||
facet.clearAutogeneratedFiles(AndroidAutogeneratorMode.AAPT);
|
||||
|
||||
if (messages.get(AndroidCompilerMessageKind.ERROR).size() == 0) {
|
||||
facet.clearAutogeneratedFiles(AndroidAutogeneratorMode.AAPT);
|
||||
for (String relPath : item.myGenFileRelPath2package.keySet()) {
|
||||
final VirtualFile genFile = LocalFileSystem.getInstance().findFileByPath(item.myOutputDirOsPath + '/' + relPath);
|
||||
|
||||
for (String relPath : item.myGenFileRelPath2package.keySet()) {
|
||||
final VirtualFile genFile = LocalFileSystem.getInstance().findFileByPath(item.myOutputDirOsPath + '/' + relPath);
|
||||
|
||||
if (genFile != null && genFile.exists()) {
|
||||
facet.markFileAutogenerated(AndroidAutogeneratorMode.AAPT, genFile);
|
||||
}
|
||||
if (genFile != null && genFile.exists()) {
|
||||
facet.markFileAutogenerated(AndroidAutogeneratorMode.AAPT, genFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -357,6 +350,30 @@ public class AndroidAutogenerator {
|
||||
}
|
||||
}
|
||||
|
||||
private static void generateStubClasses(@NotNull String aPackage, @NotNull File outputDir, @NotNull String... classNames)
|
||||
throws IOException {
|
||||
assert aPackage.length() > 0;
|
||||
|
||||
for (String className : classNames) {
|
||||
final File packageDir = new File(outputDir.getPath() + '/' + aPackage.replace('.', '/'));
|
||||
if (!packageDir.exists() && !packageDir.mkdirs()) {
|
||||
throw new IOException("Cannot create directory " + FileUtil.toSystemDependentName(packageDir.getPath()));
|
||||
}
|
||||
final BufferedWriter writer = new BufferedWriter(new FileWriter(new File(packageDir, className + ".java")));
|
||||
try {
|
||||
writer.write(
|
||||
"package " + aPackage + ";\n\n" +
|
||||
"/* This stub is for using by IDE only. It is NOT the " + className + " class actually packed into APK */\n" +
|
||||
"public final class " + className + " {\n" +
|
||||
"}"
|
||||
);
|
||||
}
|
||||
finally {
|
||||
writer.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void removeAllFilesWithSameName(@NotNull final Module module, @NotNull File file, @NotNull String directoryPath) {
|
||||
final VirtualFile vFile = LocalFileSystem.getInstance().findFileByIoFile(file);
|
||||
final VirtualFile genDir = LocalFileSystem.getInstance().findFileByPath(directoryPath);
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package org.jetbrains.android.compiler;
|
||||
|
||||
import com.android.resources.ResourceType;
|
||||
import com.intellij.CommonBundle;
|
||||
import com.intellij.compiler.CompilerConfiguration;
|
||||
import com.intellij.compiler.CompilerConfigurationImpl;
|
||||
@@ -35,7 +34,6 @@ import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleManager;
|
||||
import com.intellij.openapi.module.ModuleUtil;
|
||||
import com.intellij.openapi.project.DumbService;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.*;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
@@ -57,18 +55,16 @@ import com.intellij.util.containers.HashMap;
|
||||
import com.intellij.util.containers.HashSet;
|
||||
import org.jetbrains.android.compiler.artifact.*;
|
||||
import org.jetbrains.android.dom.manifest.Manifest;
|
||||
import org.jetbrains.android.dom.resources.Attr;
|
||||
import org.jetbrains.android.dom.resources.DeclareStyleable;
|
||||
import org.jetbrains.android.dom.resources.ResourceElement;
|
||||
import org.jetbrains.android.dom.resources.Resources;
|
||||
import org.jetbrains.android.facet.AndroidFacet;
|
||||
import org.jetbrains.android.facet.AndroidFacetConfiguration;
|
||||
import org.jetbrains.android.facet.AndroidRootUtil;
|
||||
import org.jetbrains.android.fileTypes.AndroidIdlFileType;
|
||||
import org.jetbrains.android.fileTypes.AndroidRenderscriptFileType;
|
||||
import org.jetbrains.android.resourceManagers.LocalResourceManager;
|
||||
import org.jetbrains.android.sdk.AndroidPlatform;
|
||||
import org.jetbrains.android.util.*;
|
||||
import org.jetbrains.android.util.AndroidCommonUtils;
|
||||
import org.jetbrains.android.util.AndroidCompilerMessageKind;
|
||||
import org.jetbrains.android.util.AndroidExecutionUtil;
|
||||
import org.jetbrains.android.util.AndroidUtils;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -140,18 +136,6 @@ public class AndroidCompileUtil {
|
||||
addMessages(context, messages, null, module);
|
||||
}
|
||||
|
||||
public static void addMessages(@NotNull Map<CompilerMessageCategory, List<String>> messages,
|
||||
@NotNull Map<CompilerMessageCategory, List<String>> toAdd) {
|
||||
for (Map.Entry<CompilerMessageCategory, List<String>> entry : toAdd.entrySet()) {
|
||||
List<String> list = messages.get(entry.getKey());
|
||||
if (list == null) {
|
||||
list = new ArrayList<String>();
|
||||
messages.put(entry.getKey(), list);
|
||||
}
|
||||
list.addAll(entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
static void addMessages(final CompileContext context,
|
||||
final Map<CompilerMessageCategory, List<String>> messages,
|
||||
@Nullable final Map<VirtualFile, VirtualFile> presentableFilesMap,
|
||||
@@ -711,95 +695,6 @@ public class AndroidCompileUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public static void collectAllResources(@NotNull final AndroidFacet facet, final Set<ResourceEntry> resourceSet) {
|
||||
final LocalResourceManager manager = facet.getLocalResourceManager();
|
||||
final Project project = facet.getModule().getProject();
|
||||
|
||||
for (final ResourceType resType : AndroidResourceUtil.VALUE_RESOURCE_TYPES) {
|
||||
for (final ResourceElement element : manager.getValueResources(resType.getName())) {
|
||||
waitForSmartMode(project);
|
||||
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!element.isValid() || facet.getModule().isDisposed() || project.isDisposed()) {
|
||||
return;
|
||||
}
|
||||
final String name = element.getName().getValue();
|
||||
|
||||
if (name != null) {
|
||||
resourceSet.add(new ResourceEntry(resType.getName(), name));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
for (final Pair<Resources, VirtualFile> pair : manager.getResourceElements()) {
|
||||
final Resources resources = pair.getFirst();
|
||||
waitForSmartMode(project);
|
||||
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!resources.isValid() || facet.getModule().isDisposed() || project.isDisposed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (final Attr attr : resources.getAttrs()) {
|
||||
final String name = attr.getName().getValue();
|
||||
|
||||
if (name != null) {
|
||||
resourceSet.add(new ResourceEntry(ResourceType.ATTR.getName(), name));
|
||||
}
|
||||
}
|
||||
|
||||
for (final DeclareStyleable styleable : resources.getDeclareStyleables()) {
|
||||
final String name = styleable.getName().getValue();
|
||||
|
||||
if (name != null) {
|
||||
resourceSet.add(new ResourceEntry(ResourceType.DECLARE_STYLEABLE.getName(), name));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
waitForSmartMode(project);
|
||||
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (facet.getModule().isDisposed() || project.isDisposed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (String id : manager.getIds()) {
|
||||
resourceSet.add(new ResourceEntry(ResourceType.ID.getName(), id));
|
||||
}
|
||||
}
|
||||
});
|
||||
final HashSet<VirtualFile> visited = new HashSet<VirtualFile>();
|
||||
|
||||
for (VirtualFile subdir : manager.getResourceSubdirs(null)) {
|
||||
final HashSet<VirtualFile> resourceFiles = new HashSet<VirtualFile>();
|
||||
AndroidUtils.collectFiles(subdir, visited, resourceFiles);
|
||||
|
||||
for (VirtualFile file : resourceFiles) {
|
||||
final String subdirName = subdir.getName();
|
||||
final int index = subdirName.indexOf('-');
|
||||
final String type = index >= 0 ? subdirName.substring(0, index) : subdirName;
|
||||
resourceSet.add(new ResourceEntry(type, FileUtil.getNameWithoutExtension(file.getName())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void waitForSmartMode(Project project) {
|
||||
if (!ApplicationManager.getApplication().isReadAccessAllowed()) {
|
||||
DumbService.getInstance(project).waitForSmartMode();
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String[] toOsPaths(@NotNull VirtualFile[] classFilesDirs) {
|
||||
final String[] classFilesDirOsPaths = new String[classFilesDirs.length];
|
||||
|
||||
+8
-12
@@ -160,7 +160,7 @@ public class ResourceReferenceConverter extends ResolvingConverter<ResourceValue
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Set<String> getResourceTypesInCurrentModule(@NotNull AndroidFacet facet) {
|
||||
public static Set<String> getResourceTypesInCurrentModule(@NotNull AndroidFacet facet) {
|
||||
final Set<String> result = new HashSet<String>();
|
||||
final LocalResourceManager manager = facet.getLocalResourceManager();
|
||||
|
||||
@@ -173,6 +173,9 @@ public class ResourceReferenceConverter extends ResolvingConverter<ResourceValue
|
||||
}
|
||||
|
||||
result.addAll(manager.getValueResourceTypes());
|
||||
if (manager.getIds().size() > 0) {
|
||||
result.add(ResourceType.ID.getName());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -205,17 +208,10 @@ public class ResourceReferenceConverter extends ResolvingConverter<ResourceValue
|
||||
String resPackage,
|
||||
Collection<ResourceValue> result,
|
||||
boolean explicitResourceType) {
|
||||
ResourceManager manager = facet.getResourceManager(resPackage);
|
||||
if (manager == null) return;
|
||||
for (String name : manager.getValueResourceNames(type)) {
|
||||
result.add(referenceTo(type, resPackage, name, explicitResourceType));
|
||||
}
|
||||
for (String file : manager.getFileResourcesNames(type)) {
|
||||
result.add(referenceTo(type, resPackage, file, explicitResourceType));
|
||||
}
|
||||
if (type.equals("id")) {
|
||||
for (String id : manager.getIds()) {
|
||||
result.add(referenceTo(type, resPackage, id, explicitResourceType));
|
||||
final ResourceManager manager = facet.getResourceManager(resPackage);
|
||||
if (manager != null) {
|
||||
for (String name : manager.getResourceNames(type)) {
|
||||
result.add(referenceTo(type, resPackage, name, explicitResourceType));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,6 @@ import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleUtil;
|
||||
import com.intellij.openapi.project.DumbService;
|
||||
import com.intellij.openapi.project.IndexNotReadyException;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
@@ -87,7 +86,6 @@ import org.jetbrains.android.sdk.*;
|
||||
import org.jetbrains.android.util.AndroidBundle;
|
||||
import org.jetbrains.android.util.AndroidCommonUtils;
|
||||
import org.jetbrains.android.util.AndroidUtils;
|
||||
import org.jetbrains.android.util.ResourceEntry;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -446,12 +444,6 @@ public class AndroidFacet extends Facet<AndroidFacetConfiguration> {
|
||||
return;
|
||||
}
|
||||
|
||||
DumbService.getInstance(project).waitForSmartMode();
|
||||
|
||||
final HashSet<ResourceEntry> resourceSet = new HashSet<ResourceEntry>();
|
||||
AndroidCompileUtil.collectAllResources(AndroidFacet.this, resourceSet);
|
||||
myListener.setResourceSet(resourceSet);
|
||||
|
||||
if (AndroidAptCompiler.isToCompileModule(module, getConfiguration())) {
|
||||
AndroidCompileUtil.generate(module, AndroidAutogeneratorMode.AAPT);
|
||||
}
|
||||
|
||||
@@ -422,10 +422,6 @@ public class AndroidFacetEditorTab extends FacetEditorTab {
|
||||
String absLibsPath = myNativeLibsFolder.getText().trim();
|
||||
myConfiguration.LIBS_FOLDER_RELATIVE_PATH = absLibsPath.length() > 0 ? '/' + getAndCheckRelativePath(absLibsPath, false) : "";
|
||||
|
||||
if (myConfiguration.LIBRARY_PROJECT != myIsLibraryProjectCheckbox.isSelected()) {
|
||||
runApt = true;
|
||||
}
|
||||
|
||||
myConfiguration.CUSTOM_DEBUG_KEYSTORE_PATH = getSelectedCustomKeystorePath();
|
||||
|
||||
myConfiguration.LIBRARY_PROJECT = myIsLibraryProjectCheckbox.isSelected();
|
||||
@@ -454,9 +450,6 @@ public class AndroidFacetEditorTab extends FacetEditorTab {
|
||||
|
||||
boolean useCustomAptSrc = myUseCustomSourceDirectoryRadio.isSelected();
|
||||
|
||||
if (myConfiguration.USE_CUSTOM_APK_RESOURCE_FOLDER != useCustomAptSrc) {
|
||||
runApt = true;
|
||||
}
|
||||
myConfiguration.USE_CUSTOM_APK_RESOURCE_FOLDER = useCustomAptSrc;
|
||||
|
||||
String absAptSourcePath = myCustomAptSourceDirField.getText().trim();
|
||||
@@ -464,11 +457,7 @@ public class AndroidFacetEditorTab extends FacetEditorTab {
|
||||
if (absAptSourcePath.length() == 0) {
|
||||
throw new ConfigurationException("Resources folder not specified");
|
||||
}
|
||||
String newCustomAptSourceFolder = '/' + getAndCheckRelativePath(absAptSourcePath, false);
|
||||
if (!newCustomAptSourceFolder.equals(myConfiguration.CUSTOM_APK_RESOURCE_FOLDER)) {
|
||||
runApt = true;
|
||||
}
|
||||
myConfiguration.CUSTOM_APK_RESOURCE_FOLDER = newCustomAptSourceFolder;
|
||||
myConfiguration.CUSTOM_APK_RESOURCE_FOLDER = '/' + getAndCheckRelativePath(absAptSourcePath, false);
|
||||
}
|
||||
else {
|
||||
String relPath = toRelativePath(absAptSourcePath);
|
||||
|
||||
@@ -20,11 +20,9 @@ import com.android.resources.ResourceFolderType;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleUtil;
|
||||
import com.intellij.openapi.project.DumbService;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.vfs.*;
|
||||
import com.intellij.util.containers.HashSet;
|
||||
import com.intellij.util.ui.update.MergingUpdateQueue;
|
||||
import com.intellij.util.ui.update.Update;
|
||||
import org.jetbrains.android.compiler.AndroidAptCompiler;
|
||||
@@ -35,14 +33,12 @@ import org.jetbrains.android.fileTypes.AndroidIdlFileType;
|
||||
import org.jetbrains.android.fileTypes.AndroidRenderscriptFileType;
|
||||
import org.jetbrains.android.util.AndroidCommonUtils;
|
||||
import org.jetbrains.android.util.AndroidUtils;
|
||||
import org.jetbrains.android.util.ResourceEntry;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.jetbrains.android.util.AndroidUtils.findSourceRoot;
|
||||
|
||||
@@ -59,9 +55,6 @@ class AndroidResourceFilesListener extends VirtualFileAdapter {
|
||||
private final AndroidFacet myFacet;
|
||||
private String myCachedPackage = null;
|
||||
|
||||
private volatile Set<ResourceEntry> myResourceSet = new HashSet<ResourceEntry>();
|
||||
private static final Object RESOURCES_SET_LOCK = new Object();
|
||||
|
||||
public AndroidResourceFilesListener(final AndroidFacet facet) {
|
||||
myFacet = facet;
|
||||
myQueue = new MergingUpdateQueue("AndroidResourcesCompilationQueue", 300, true, null, myFacet, null, false);
|
||||
@@ -128,12 +121,6 @@ class AndroidResourceFilesListener extends VirtualFileAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
public void setResourceSet(@NotNull Set<ResourceEntry> resourceSet) {
|
||||
synchronized (RESOURCES_SET_LOCK) {
|
||||
myResourceSet = resourceSet;
|
||||
}
|
||||
}
|
||||
|
||||
private class MyUpdate extends Update {
|
||||
private final VirtualFileEvent myEvent;
|
||||
|
||||
@@ -160,23 +147,6 @@ class AndroidResourceFilesListener extends VirtualFileAdapter {
|
||||
}
|
||||
|
||||
for (AndroidAutogeneratorMode autogenerationMode : autogenerationModes) {
|
||||
if (autogenerationMode == AndroidAutogeneratorMode.AAPT &&
|
||||
AndroidRootUtil.getManifestFile(myFacet) != myEvent.getFile()) {
|
||||
|
||||
final HashSet<ResourceEntry> resourceSet = new HashSet<ResourceEntry>();
|
||||
|
||||
DumbService.getInstance(myFacet.getModule().getProject()).waitForSmartMode();
|
||||
|
||||
AndroidCompileUtil.collectAllResources(myFacet, resourceSet);
|
||||
|
||||
synchronized (RESOURCES_SET_LOCK) {
|
||||
if (resourceSet.equals(myResourceSet) &&
|
||||
!myFacet.areSourcesGeneratedWithErrors(AndroidAutogeneratorMode.AAPT)) {
|
||||
return;
|
||||
}
|
||||
myResourceSet = resourceSet;
|
||||
}
|
||||
}
|
||||
AndroidCompileUtil.generate(myFacet.getModule(), autogenerationMode, true);
|
||||
}
|
||||
}
|
||||
@@ -216,7 +186,7 @@ class AndroidResourceFilesListener extends VirtualFileAdapter {
|
||||
|
||||
final List<AndroidAutogeneratorMode> modes = new ArrayList<AndroidAutogeneratorMode>();
|
||||
|
||||
if (AndroidAptCompiler.isToCompileModule(module, myFacet.getConfiguration()) && (gp == resourceDir || manifestFile == file)) {
|
||||
if (AndroidAptCompiler.isToCompileModule(module, myFacet.getConfiguration()) && manifestFile == file) {
|
||||
final Manifest manifest = myFacet.getManifest();
|
||||
final String aPackage = manifest != null ? manifest.getPackage().getValue() : null;
|
||||
|
||||
|
||||
@@ -262,6 +262,17 @@ public abstract class ResourceManager {
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Collection<String> getResourceNames(@NotNull String type) {
|
||||
final Set<String> result = new HashSet<String>();
|
||||
result.addAll(getValueResourceNames(type));
|
||||
result.addAll(getFileResourcesNames(type));
|
||||
if (type.equals("id")) {
|
||||
result.addAll(getIds());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public abstract AttributeDefinitions getAttributeDefinitions();
|
||||
|
||||
|
||||
@@ -572,6 +572,15 @@ public class AndroidResourceUtil {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isManifestJavaFile(@NotNull AndroidFacet facet, @NotNull PsiFile file) {
|
||||
if (file.getName().equals(AndroidCommonUtils.MANIFEST_JAVA_FILE_NAME) && file instanceof PsiJavaFile) {
|
||||
final Manifest manifest = facet.getManifest();
|
||||
final PsiJavaFile javaFile = (PsiJavaFile)file;
|
||||
return manifest != null && javaFile.getPackageName().equals(manifest.getPackage().getValue());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static List<String> getNames(@NotNull Collection<ResourceType> resourceTypes) {
|
||||
if (resourceTypes.size() == 0) {
|
||||
return Collections.emptyList();
|
||||
@@ -803,4 +812,9 @@ public class AndroidResourceUtil {
|
||||
}
|
||||
return AndroidFileTemplateProvider.RESOURCE_FILE_TEMPLATE;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String getFieldNameByResourceName(@NotNull String fieldName) {
|
||||
return fieldName.replace('.', '_').replace('-', '_');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,6 +109,7 @@ public class AndroidUtils {
|
||||
@NonNls public static final String APPLICATION_CLASS_NAME = "android.app.Application";
|
||||
@NonNls public static final String ACTIVITY_BASE_CLASS_NAME = "android.app.Activity";
|
||||
@NonNls public static final String R_CLASS_NAME = "R";
|
||||
@NonNls public static final String MANIFEST_CLASS_NAME = "Manifest";
|
||||
@NonNls public static final String LAUNCH_ACTION_NAME = "android.intent.action.MAIN";
|
||||
@NonNls public static final String LAUNCH_CATEGORY_NAME = "android.intent.category.LAUNCHER";
|
||||
@NonNls public static final String INSTRUMENTATION_RUNNER_BASE_CLASS = "android.app.Instrumentation";
|
||||
|
||||
@@ -1,12 +1,4 @@
|
||||
package p1.p2;
|
||||
|
||||
public final class R {
|
||||
public static final class string {
|
||||
public static final int welcome=0x7f040001;
|
||||
public static final int hello=0x7f040000;
|
||||
}
|
||||
|
||||
public static final class drawable {
|
||||
public static final int picture3=0x7f040002;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
package p1.p2;
|
||||
|
||||
public class JavaCompletion {
|
||||
public void f() {
|
||||
R.layo<caret>
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package p1.p2;
|
||||
|
||||
public class JavaCompletion {
|
||||
public void f() {
|
||||
R.layout
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package p1.p2;
|
||||
|
||||
public class JavaCompletion {
|
||||
public void f() {
|
||||
R.layout.mai<caret>
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package p1.p2;
|
||||
|
||||
public class JavaCompletion {
|
||||
public void f() {
|
||||
R.layout.main
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package p1.p2;
|
||||
|
||||
public class JavaCompletion {
|
||||
public void f() {
|
||||
R.xm<caret>
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package p1.p2;
|
||||
|
||||
public class JavaCompletion {
|
||||
public void f() {
|
||||
R.xm
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package p1.p2;
|
||||
|
||||
public class JavaHighlighting1 {
|
||||
public void f() {
|
||||
int n = R.<error>xml</error>.main;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package p1;
|
||||
|
||||
public class JavaHighlighting6 {
|
||||
public void f() {
|
||||
int n = p1.p2.R.layout.main;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package p1.p2;
|
||||
|
||||
public class JavaHighlighting3 {
|
||||
public void f() {
|
||||
int n = R.layout.<error>unknown</error>;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package p1.p2;
|
||||
|
||||
public class JavaHighlighting4 {
|
||||
public void f() {
|
||||
int n = R.layout.main;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package p1;
|
||||
|
||||
public class JavaHighlighting5 {
|
||||
public void f() {
|
||||
int n = <error>R</error>.layout.main;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package p1.p2;
|
||||
|
||||
public class JavaIdCompletion {
|
||||
public void f() {
|
||||
int n = R.id.myComp<caret>;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package p1.p2;
|
||||
|
||||
public class JavaIdCompletion {
|
||||
public void f() {
|
||||
int n = R.id.myComponent;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<TextView android:id="@+id/myComponent"/>
|
||||
</LinearLayout>
|
||||
@@ -0,0 +1,17 @@
|
||||
package p1.p2;
|
||||
|
||||
import java.lang.String;
|
||||
|
||||
public class JavaCompletion {
|
||||
public void f() {
|
||||
String s = Manifest.permission.perm1;
|
||||
s = Manifest.permission.perm2;
|
||||
s = Manifest.permission.<error>unknown</error>;
|
||||
s = Manifest.<error>permissio</error>.perm1;
|
||||
s = Manifest.permission.aba_perm;
|
||||
|
||||
s = Manifest.permission_group.group1;
|
||||
s = Manifest.permission_group.<error>unknown</error>;
|
||||
s = Manifest.permission_group.aba_group;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package p1.p2;
|
||||
|
||||
public class Manifest {
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="p1.p2">
|
||||
<permission android:name="android.permission.perm1"/>
|
||||
<permission android:name="aba.perm2"/>
|
||||
<permission android:name="android.aba-perm"/>
|
||||
<permission-group android:name="android.permission-group.group1"/>
|
||||
<permission-group android:name="group2"/>
|
||||
<permission-group android:name="android.permission-group.aba_group"/>
|
||||
</manifest>
|
||||
@@ -0,0 +1,7 @@
|
||||
package p1.p2;
|
||||
|
||||
public class JavaCompletion1 {
|
||||
public void f() {
|
||||
int n = R.string.my_str<caret>;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package p1.p2;
|
||||
|
||||
public class JavaCompletion1 {
|
||||
public void f() {
|
||||
int n = R.string.my_string;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package p1.p2;
|
||||
|
||||
public class JavaCompletion1 {
|
||||
public void f() {
|
||||
int n = R.stri<caret>;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package p1.p2;
|
||||
|
||||
public class JavaCompletion1 {
|
||||
public void f() {
|
||||
int n = R.string;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package p1.p2;
|
||||
|
||||
public class JavaCompletion1 {
|
||||
public void f() {
|
||||
int n = R.string.unknow<caret>;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package p1.p2;
|
||||
|
||||
public class JavaCompletion1 {
|
||||
public void f() {
|
||||
int n = R.string.unknow;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package p1.p2;
|
||||
|
||||
public class JavaCompletion1 {
|
||||
public void f() {
|
||||
int n = R.style.Theme_My<caret>;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package p1.p2;
|
||||
|
||||
public class JavaCompletion1 {
|
||||
public void f() {
|
||||
int n = R.style.Theme_MyCustomStyle
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package p1.p2;
|
||||
|
||||
public class JavaCompletion1 {
|
||||
public void f() {
|
||||
int n = R.string.my_string;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package p1.p2;
|
||||
|
||||
public class JavaCompletion1 {
|
||||
public void f() {
|
||||
int n = R.string.<error>unknown</error>;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
<resources>
|
||||
<string name="my_string">abacaba</string>
|
||||
<style name="Theme.MyCustomStyle" parent="android:style/Theme.Dialog"></style>
|
||||
</resources>
|
||||
@@ -39,6 +39,14 @@ abstract class AndroidDomTest extends AndroidTestCase {
|
||||
return "dom/res";
|
||||
}
|
||||
|
||||
protected void doTestJavaCompletion(String aPackage) throws Throwable {
|
||||
final String fileName = getTestName(false) + ".java";
|
||||
final VirtualFile file = copyFileToProject(fileName, "src/" + aPackage.replace('/', '.') + '/' + fileName);
|
||||
myFixture.configureFromExistingVirtualFile(file);
|
||||
myFixture.complete(CompletionType.BASIC);
|
||||
myFixture.checkResultByFile(testFolder + '/' + getTestName(false) + "_after.java");
|
||||
}
|
||||
|
||||
protected static String[] withNamespace(String... arr) {
|
||||
List<String> list = new ArrayList<String>();
|
||||
for (String s : arr) {
|
||||
@@ -66,6 +74,13 @@ abstract class AndroidDomTest extends AndroidTestCase {
|
||||
myFixture.checkHighlighting(true, false, false);
|
||||
}
|
||||
|
||||
protected void doTestJavaHighlighting(String aPackage) throws Throwable {
|
||||
final String fileName = getTestName(false) + ".java";
|
||||
final VirtualFile virtualFile = copyFileToProject(fileName, "src/" + aPackage.replace('.', '/') + '/' + fileName);
|
||||
myFixture.configureFromExistingVirtualFile(virtualFile);
|
||||
myFixture.checkHighlighting(true, false, false);
|
||||
}
|
||||
|
||||
protected void doTestCompletion() throws Throwable {
|
||||
doTestCompletion(true);
|
||||
}
|
||||
|
||||
@@ -385,5 +385,50 @@ public class AndroidLayoutDomTest extends AndroidDomTest {
|
||||
copyFileToProject("OnClick_Class3.java", "src/p1/p2/OnClick_Class3.java");
|
||||
copyFileToProject("OnClick_Class4.java", "src/p1/p2/OnClick_Class4.java");
|
||||
}
|
||||
|
||||
public void testJavaCompletion1() throws Throwable {
|
||||
copyFileToProject("main.xml", "res/layout/main.xml");
|
||||
doTestJavaCompletion("p1.p2");
|
||||
}
|
||||
|
||||
public void testJavaCompletion2() throws Throwable {
|
||||
copyFileToProject("main.xml", "res/layout/main.xml");
|
||||
doTestJavaCompletion("p1.p2");
|
||||
}
|
||||
|
||||
public void testJavaCompletion3() throws Throwable {
|
||||
copyFileToProject("main.xml", "res/layout/main.xml");
|
||||
doTestJavaCompletion("p1.p2");
|
||||
}
|
||||
|
||||
public void testJavaIdCompletion() throws Throwable {
|
||||
copyFileToProject("main.xml", "res/layout/main.xml");
|
||||
doTestJavaCompletion("p1.p2");
|
||||
}
|
||||
|
||||
public void testJavaHighlighting1() throws Throwable {
|
||||
copyFileToProject("main.xml", "res/layout/main.xml");
|
||||
doTestJavaHighlighting("p1.p2");
|
||||
}
|
||||
|
||||
public void testJavaHighlighting2() throws Throwable {
|
||||
copyFileToProject("main.xml", "res/layout/main.xml");
|
||||
doTestJavaHighlighting("p1");
|
||||
}
|
||||
|
||||
public void testJavaHighlighting3() throws Throwable {
|
||||
copyFileToProject("main.xml", "res/layout/main.xml");
|
||||
doTestJavaHighlighting("p1.p2");
|
||||
}
|
||||
|
||||
public void testJavaHighlighting4() throws Throwable {
|
||||
copyFileToProject("main.xml", "res/layout/main.xml");
|
||||
doTestJavaHighlighting("p1.p2");
|
||||
}
|
||||
|
||||
public void testJavaHighlighting5() throws Throwable {
|
||||
copyFileToProject("main.xml", "res/layout/main.xml");
|
||||
doTestJavaHighlighting("p1");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -192,4 +192,11 @@ public class AndroidManifestDomTest extends AndroidDomTest {
|
||||
copyFileToProject("myIntResource.xml", "res/values/myIntResource.xml");
|
||||
doTestCompletion();
|
||||
}
|
||||
|
||||
public void testJavaHighlighting() throws Throwable {
|
||||
copyFileToProject("PermissionsManifest.xml", "AndroidManifest.xml");
|
||||
copyFileToProject("Manifest.java", "src/p1/p2/Manifest.java");
|
||||
doTestJavaHighlighting("p1.p2");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -215,4 +215,34 @@ public class AndroidValueResourcesTest extends AndroidDomTest {
|
||||
}.execute();
|
||||
myFixture.checkResultByFile(testFolder + '/' + getTestName(true) + "_after.xml", true);
|
||||
}
|
||||
|
||||
public void testJavaCompletion1() throws Throwable {
|
||||
copyFileToProject("value_resources.xml", "res/values/value_resources.xml");
|
||||
doTestJavaCompletion("p1.p2");
|
||||
}
|
||||
|
||||
public void testJavaCompletion2() throws Throwable {
|
||||
copyFileToProject("value_resources.xml", "res/values/value_resources.xml");
|
||||
doTestJavaCompletion("p1.p2");
|
||||
}
|
||||
|
||||
public void testJavaCompletion3() throws Throwable {
|
||||
copyFileToProject("value_resources.xml", "res/values/value_resources.xml");
|
||||
doTestJavaCompletion("p1.p2");
|
||||
}
|
||||
|
||||
public void testJavaCompletion4() throws Throwable {
|
||||
copyFileToProject("value_resources.xml", "res/values/value_resources.xml");
|
||||
doTestJavaCompletion("p1.p2");
|
||||
}
|
||||
|
||||
public void testJavaHighlighting1() throws Throwable {
|
||||
copyFileToProject("value_resources.xml", "res/values/value_resources.xml");
|
||||
doTestJavaHighlighting("p1.p2");
|
||||
}
|
||||
|
||||
public void testJavaHighlighting2() throws Throwable {
|
||||
copyFileToProject("value_resources.xml", "res/values/value_resources.xml");
|
||||
doTestJavaHighlighting("p1.p2");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user