Search in sources :

Example 16 with ResourceUrl

use of com.android.ide.common.resources.ResourceUrl in project kotlin by JetBrains.

the class AppIndexingApiDetector method replaceUrlWithValue.

private static String replaceUrlWithValue(@NonNull XmlContext context, @NonNull String str) {
    Project project = context.getProject();
    LintClient client = context.getClient();
    if (!client.supportsProjectResources()) {
        return str;
    }
    ResourceUrl style = ResourceUrl.parse(str);
    if (style == null || style.type != ResourceType.STRING || style.framework) {
        return str;
    }
    AbstractResourceRepository resources = client.getProjectResources(project, true);
    if (resources == null) {
        return str;
    }
    List<ResourceItem> items = resources.getResourceItem(ResourceType.STRING, style.name);
    if (items == null || items.isEmpty()) {
        return str;
    }
    ResourceValue resourceValue = items.get(0).getResourceValue(false);
    if (resourceValue == null) {
        return str;
    }
    return resourceValue.getValue() == null ? str : resourceValue.getValue();
}
Also used : Project(com.android.tools.klint.detector.api.Project) AbstractResourceRepository(com.android.ide.common.res2.AbstractResourceRepository) LintClient(com.android.tools.klint.client.api.LintClient) ResourceValue(com.android.ide.common.rendering.api.ResourceValue) ResourceItem(com.android.ide.common.res2.ResourceItem) ResourceUrl(com.android.ide.common.resources.ResourceUrl)

Example 17 with ResourceUrl

use of com.android.ide.common.resources.ResourceUrl in project kotlin by JetBrains.

the class ResourceEvaluator method getResourceTypes.

/**
     * Evaluates the given node and returns the resource types applicable to the
     * node, if any.
     *
     * @param element the element to compute the types for
     * @return the corresponding resource types
     */
@Nullable
public EnumSet<ResourceType> getResourceTypes(@Nullable UElement element) {
    if (element == null) {
        return null;
    }
    if (element instanceof UIfExpression) {
        UIfExpression expression = (UIfExpression) element;
        Object known = ConstantEvaluator.evaluate(null, expression.getCondition());
        if (known == Boolean.TRUE && expression.getThenExpression() != null) {
            return getResourceTypes(expression.getThenExpression());
        } else if (known == Boolean.FALSE && expression.getElseExpression() != null) {
            return getResourceTypes(expression.getElseExpression());
        } else {
            EnumSet<ResourceType> left = getResourceTypes(expression.getThenExpression());
            EnumSet<ResourceType> right = getResourceTypes(expression.getElseExpression());
            if (left == null) {
                return right;
            } else if (right == null) {
                return left;
            } else {
                EnumSet<ResourceType> copy = EnumSet.copyOf(left);
                copy.addAll(right);
                return copy;
            }
        }
    } else if (element instanceof UParenthesizedExpression) {
        UParenthesizedExpression parenthesizedExpression = (UParenthesizedExpression) element;
        return getResourceTypes(parenthesizedExpression.getExpression());
    } else if ((element instanceof UQualifiedReferenceExpression && mAllowDereference) || element instanceof UCallExpression) {
        UElement probablyCallExpression = element;
        if (element instanceof UQualifiedReferenceExpression) {
            UQualifiedReferenceExpression qualifiedExpression = (UQualifiedReferenceExpression) element;
            probablyCallExpression = qualifiedExpression.getSelector();
        }
        if ((probablyCallExpression instanceof UCallExpression)) {
            UCallExpression call = (UCallExpression) probablyCallExpression;
            PsiMethod method = call.resolve();
            PsiClass containingClass = UastUtils.getContainingClass(method);
            if (method != null && containingClass != null) {
                EnumSet<ResourceType> types = getTypesFromAnnotations(method);
                if (types != null) {
                    return types;
                }
                String qualifiedName = containingClass.getQualifiedName();
                String name = call.getMethodName();
                if ((CLASS_RESOURCES.equals(qualifiedName) || CLASS_CONTEXT.equals(qualifiedName) || CLASS_FRAGMENT.equals(qualifiedName) || CLASS_V4_FRAGMENT.equals(qualifiedName) || CLS_TYPED_ARRAY.equals(qualifiedName)) && name != null && name.startsWith("get")) {
                    List<UExpression> args = call.getValueArguments();
                    if (!args.isEmpty()) {
                        types = getResourceTypes(args.get(0));
                        if (types != null) {
                            return types;
                        }
                    }
                }
            }
        }
    }
    if (element instanceof UReferenceExpression) {
        ResourceUrl url = getResourceConstant(element);
        if (url != null) {
            return EnumSet.of(url.type);
        }
        PsiElement resolved = ((UReferenceExpression) element).resolve();
        if (resolved instanceof PsiVariable) {
            PsiVariable variable = (PsiVariable) resolved;
            UElement lastAssignment = UastLintUtils.findLastAssignment(variable, element, mContext);
            if (lastAssignment != null) {
                return getResourceTypes(lastAssignment);
            }
            return null;
        }
    }
    return null;
}
Also used : PsiVariable(com.intellij.psi.PsiVariable) PsiMethod(com.intellij.psi.PsiMethod) UParenthesizedExpression(org.jetbrains.uast.UParenthesizedExpression) UQualifiedReferenceExpression(org.jetbrains.uast.UQualifiedReferenceExpression) EnumSet(java.util.EnumSet) PsiClass(com.intellij.psi.PsiClass) ResourceType(com.android.resources.ResourceType) UCallExpression(org.jetbrains.uast.UCallExpression) UExpression(org.jetbrains.uast.UExpression) UElement(org.jetbrains.uast.UElement) UReferenceExpression(org.jetbrains.uast.UReferenceExpression) ResourceUrl(com.android.ide.common.resources.ResourceUrl) PsiElement(com.intellij.psi.PsiElement) UIfExpression(org.jetbrains.uast.UIfExpression) Nullable(com.android.annotations.Nullable)

Example 18 with ResourceUrl

use of com.android.ide.common.resources.ResourceUrl in project kotlin by JetBrains.

the class ResourceEvaluator method getResource.

/**
     * Evaluates the given node and returns the resource reference (type and name) it
     * points to, if any
     *
     * @param element the node to compute the constant value for
     * @return the corresponding constant value - a String, an Integer, a Float, and so on
     */
@Nullable
public ResourceUrl getResource(@Nullable UElement element) {
    if (element == null) {
        return null;
    }
    if (element instanceof UIfExpression) {
        UIfExpression expression = (UIfExpression) element;
        Object known = ConstantEvaluator.evaluate(null, expression.getCondition());
        if (known == Boolean.TRUE && expression.getThenExpression() != null) {
            return getResource(expression.getThenExpression());
        } else if (known == Boolean.FALSE && expression.getElseExpression() != null) {
            return getResource(expression.getElseExpression());
        }
    } else if (element instanceof UParenthesizedExpression) {
        UParenthesizedExpression parenthesizedExpression = (UParenthesizedExpression) element;
        return getResource(parenthesizedExpression.getExpression());
    } else if (mAllowDereference && element instanceof UQualifiedReferenceExpression) {
        UQualifiedReferenceExpression qualifiedExpression = (UQualifiedReferenceExpression) element;
        UExpression selector = qualifiedExpression.getSelector();
        if ((selector instanceof UCallExpression)) {
            UCallExpression call = (UCallExpression) selector;
            PsiMethod function = call.resolve();
            PsiClass containingClass = UastUtils.getContainingClass(function);
            if (function != null && containingClass != null) {
                String qualifiedName = containingClass.getQualifiedName();
                String name = call.getMethodName();
                if ((CLASS_RESOURCES.equals(qualifiedName) || CLASS_CONTEXT.equals(qualifiedName) || CLASS_FRAGMENT.equals(qualifiedName) || CLASS_V4_FRAGMENT.equals(qualifiedName) || CLS_TYPED_ARRAY.equals(qualifiedName)) && name != null && name.startsWith("get")) {
                    List<UExpression> args = call.getValueArguments();
                    if (!args.isEmpty()) {
                        return getResource(args.get(0));
                    }
                }
            }
        }
    }
    if (element instanceof UReferenceExpression) {
        ResourceUrl url = getResourceConstant(element);
        if (url != null) {
            return url;
        }
        PsiElement resolved = ((UReferenceExpression) element).resolve();
        if (resolved instanceof PsiVariable) {
            PsiVariable variable = (PsiVariable) resolved;
            UElement lastAssignment = UastLintUtils.findLastAssignment(variable, element, mContext);
            if (lastAssignment != null) {
                return getResource(lastAssignment);
            }
            return null;
        }
    }
    return null;
}
Also used : PsiVariable(com.intellij.psi.PsiVariable) PsiMethod(com.intellij.psi.PsiMethod) UParenthesizedExpression(org.jetbrains.uast.UParenthesizedExpression) UQualifiedReferenceExpression(org.jetbrains.uast.UQualifiedReferenceExpression) PsiClass(com.intellij.psi.PsiClass) UCallExpression(org.jetbrains.uast.UCallExpression) UExpression(org.jetbrains.uast.UExpression) UReferenceExpression(org.jetbrains.uast.UReferenceExpression) UElement(org.jetbrains.uast.UElement) ResourceUrl(com.android.ide.common.resources.ResourceUrl) PsiElement(com.intellij.psi.PsiElement) UIfExpression(org.jetbrains.uast.UIfExpression) Nullable(com.android.annotations.Nullable)

Example 19 with ResourceUrl

use of com.android.ide.common.resources.ResourceUrl in project kotlin by JetBrains.

the class RequiredAttributeDetector method visitMethod.

@Override
public void visitMethod(@NonNull JavaContext context, @Nullable UastVisitor visitor, @NonNull UCallExpression call, @NonNull UMethod method) {
    // Handle
    //    View#inflate(Context context, int resource, ViewGroup root)
    //    LayoutInflater#inflate(int resource, ViewGroup root)
    //    LayoutInflater#inflate(int resource, ViewGroup root, boolean attachToRoot)
    List<UExpression> args = call.getValueArguments();
    String layout = null;
    int index = 0;
    ResourceEvaluator evaluator = new ResourceEvaluator(context);
    for (UExpression expression : args) {
        ResourceUrl url = evaluator.getResource(expression);
        if (url != null && url.type == ResourceType.LAYOUT) {
            layout = url.toString();
            break;
        }
        index++;
    }
    if (layout == null) {
        // Flow analysis didn't succeed
        return;
    }
    // In all the applicable signatures, the view root argument is immediately after
    // the layout resource id.
    int viewRootPos = index + 1;
    if (viewRootPos < args.size()) {
        UExpression viewRoot = args.get(viewRootPos);
        if (UastLiteralUtils.isNullLiteral(viewRoot)) {
            // Yep, this one inflates the given view with a null parent:
            // Tag it as such. For now just use the include data structure since
            // it has the same net effect
            recordIncludeWidth(layout, true);
            recordIncludeHeight(layout, true);
        }
    }
}
Also used : UExpression(org.jetbrains.uast.UExpression) ResourceEvaluator(com.android.tools.klint.detector.api.ResourceEvaluator) ResourceUrl(com.android.ide.common.resources.ResourceUrl)

Example 20 with ResourceUrl

use of com.android.ide.common.resources.ResourceUrl in project kotlin by JetBrains.

the class ViewTypeDetector method visitMethod.

@Override
public void visitMethod(@NonNull JavaContext context, @Nullable UastVisitor visitor, @NonNull UCallExpression call, @NonNull UMethod method) {
    LintClient client = context.getClient();
    if (mIgnore == Boolean.TRUE) {
        return;
    } else if (mIgnore == null) {
        mIgnore = !context.getScope().contains(Scope.ALL_RESOURCE_FILES) && !client.supportsProjectResources();
        if (mIgnore) {
            return;
        }
    }
    assert method.getName().equals("findViewById");
    UElement node = LintUtils.skipParentheses(call);
    while (node != null && node.getUastParent() instanceof UParenthesizedExpression) {
        node = node.getUastParent();
    }
    if (node.getUastParent() instanceof UBinaryExpressionWithType) {
        UBinaryExpressionWithType cast = (UBinaryExpressionWithType) node.getUastParent();
        PsiType type = cast.getType();
        String castType = null;
        if (type instanceof PsiClassType) {
            castType = type.getCanonicalText();
        }
        if (castType == null) {
            return;
        }
        List<UExpression> args = call.getValueArguments();
        if (args.size() == 1) {
            UExpression first = args.get(0);
            ResourceUrl resourceUrl = ResourceEvaluator.getResource(context, first);
            if (resourceUrl != null && resourceUrl.type == ResourceType.ID && !resourceUrl.framework) {
                String id = resourceUrl.name;
                if (client.supportsProjectResources()) {
                    AbstractResourceRepository resources = client.getProjectResources(context.getMainProject(), true);
                    if (resources == null) {
                        return;
                    }
                    List<ResourceItem> items = resources.getResourceItem(ResourceType.ID, id);
                    if (items != null && !items.isEmpty()) {
                        Set<String> compatible = Sets.newHashSet();
                        for (ResourceItem item : items) {
                            Collection<String> tags = getViewTags(context, item);
                            if (tags != null) {
                                compatible.addAll(tags);
                            }
                        }
                        if (!compatible.isEmpty()) {
                            ArrayList<String> layoutTypes = Lists.newArrayList(compatible);
                            checkCompatible(context, castType, null, layoutTypes, cast);
                        }
                    }
                } else {
                    Object types = mIdToViewTag.get(id);
                    if (types instanceof String) {
                        String layoutType = (String) types;
                        checkCompatible(context, castType, layoutType, null, cast);
                    } else if (types instanceof List<?>) {
                        @SuppressWarnings("unchecked") List<String> layoutTypes = (List<String>) types;
                        checkCompatible(context, castType, null, layoutTypes, cast);
                    }
                }
            }
        }
    }
}
Also used : LintClient(com.android.tools.klint.client.api.LintClient) PsiClassType(com.intellij.psi.PsiClassType) AbstractResourceRepository(com.android.ide.common.res2.AbstractResourceRepository) ResourceItem(com.android.ide.common.res2.ResourceItem) ResourceUrl(com.android.ide.common.resources.ResourceUrl) PsiType(com.intellij.psi.PsiType)

Aggregations

ResourceUrl (com.android.ide.common.resources.ResourceUrl)24 PsiElement (com.intellij.psi.PsiElement)7 Nullable (com.android.annotations.Nullable)6 ResourceValue (com.android.ide.common.rendering.api.ResourceValue)5 AbstractResourceRepository (com.android.ide.common.res2.AbstractResourceRepository)5 ResourceItem (com.android.ide.common.res2.ResourceItem)5 ResourceType (com.android.resources.ResourceType)4 PsiMethod (com.intellij.psi.PsiMethod)4 ItemResourceValue (com.android.ide.common.rendering.api.ItemResourceValue)3 LintClient (com.android.tools.klint.client.api.LintClient)3 UExpression (org.jetbrains.uast.UExpression)3 StyleResourceValue (com.android.ide.common.rendering.api.StyleResourceValue)2 Module (com.intellij.openapi.module.Module)2 PsiAssignmentExpression (com.intellij.psi.PsiAssignmentExpression)2 PsiClass (com.intellij.psi.PsiClass)2 PsiConditionalExpression (com.intellij.psi.PsiConditionalExpression)2 PsiDeclarationStatement (com.intellij.psi.PsiDeclarationStatement)2 PsiExpression (com.intellij.psi.PsiExpression)2 PsiExpressionStatement (com.intellij.psi.PsiExpressionStatement)2 PsiField (com.intellij.psi.PsiField)2