Search in sources :

Example 1 with PsiVariable

use of com.intellij.psi.PsiVariable in project intellij-community by JetBrains.

the class LocalVarAnalyzer method searchForVarsToWrap.

public static Result searchForVarsToWrap(GroovyPsiElement root, Result analyzedVars, ExpressionContext context) {
    LocalVarAnalyzer visitor = new LocalVarAnalyzer();
    root.accept(visitor);
    Map<PsiVariable, String> varToName = analyzedVars == null ? new HashMap<>() : analyzedVars.varToName;
    Set<PsiVariable> toWrap = analyzedVars == null ? new HashSet<>() : analyzedVars.toWrap;
    Set<PsiVariable> toMakeFinal = analyzedVars == null ? new HashSet<>() : analyzedVars.toMakeFinal;
    for (PsiVariable v : visitor.touched) {
        if (visitor.rewritten.contains(v)) {
            toWrap.add(v);
            if (v instanceof PsiParameter) {
                varToName.put(v, GenerationUtil.suggestVarName(v.getType(), root, context));
            } else {
                varToName.put(v, v.getName());
            }
        } else {
            toMakeFinal.add(v);
            varToName.put(v, v.getName());
        }
    }
    return analyzedVars == null ? new Result(toMakeFinal, toWrap, varToName) : analyzedVars;
}
Also used : PsiParameter(com.intellij.psi.PsiParameter) PsiVariable(com.intellij.psi.PsiVariable)

Example 2 with PsiVariable

use of com.intellij.psi.PsiVariable in project kotlin by JetBrains.

the class ConstantEvaluator method isArrayLiteral.

/**
     * Returns true if the node is pointing to a an array literal
     */
public static boolean isArrayLiteral(@Nullable UElement node, @NonNull JavaContext context) {
    if (node instanceof UReferenceExpression) {
        PsiElement resolved = ((UReferenceExpression) node).resolve();
        if (resolved instanceof PsiVariable) {
            PsiVariable variable = (PsiVariable) resolved;
            UExpression lastAssignment = UastLintUtils.findLastAssignment(variable, node, context);
            if (lastAssignment != null) {
                return isArrayLiteral(lastAssignment, context);
            }
        }
    } else if (UastExpressionUtils.isNewArrayWithDimensions(node)) {
        return true;
    } else if (UastExpressionUtils.isNewArrayWithInitializer(node)) {
        return true;
    } else if (node instanceof UParenthesizedExpression) {
        UParenthesizedExpression parenthesizedExpression = (UParenthesizedExpression) node;
        UExpression expression = parenthesizedExpression.getExpression();
        return isArrayLiteral(expression, context);
    } else if (UastExpressionUtils.isTypeCast(node)) {
        UBinaryExpressionWithType castExpression = (UBinaryExpressionWithType) node;
        assert castExpression != null;
        UExpression operand = castExpression.getOperand();
        return isArrayLiteral(operand, context);
    }
    return false;
}
Also used : PsiVariable(com.intellij.psi.PsiVariable) UReferenceExpression(org.jetbrains.uast.UReferenceExpression) PsiElement(com.intellij.psi.PsiElement)

Example 3 with PsiVariable

use of com.intellij.psi.PsiVariable in project kotlin by JetBrains.

the class StringFormatDetector method checkStringFormatCall.

/**
     * Check the given String.format call (with the given arguments) to see if the string format is
     * being used correctly
     *  @param context           the context to report errors to
     * @param calledMethod      the method being called
     * @param call              the AST node for the {@link String#format}
     * @param specifiesLocale   whether the first parameter is a locale string, shifting the
     */
private void checkStringFormatCall(JavaContext context, PsiMethod calledMethod, UCallExpression call, boolean specifiesLocale) {
    int argIndex = specifiesLocale ? 1 : 0;
    List<UExpression> args = call.getValueArguments();
    if (args.size() <= argIndex) {
        return;
    }
    UExpression argument = args.get(argIndex);
    ResourceUrl resource = ResourceEvaluator.getResource(context, argument);
    if (resource == null || resource.framework || resource.type != ResourceType.STRING) {
        return;
    }
    String name = resource.name;
    if (mIgnoreStrings != null && mIgnoreStrings.contains(name)) {
        return;
    }
    boolean passingVarArgsArray = false;
    int callCount = args.size() - 1 - argIndex;
    if (callCount == 1) {
        // If instead of a varargs call like
        //    getString(R.string.foo, arg1, arg2, arg3)
        // the code is calling the varargs method with a packed Object array, as in
        //    getString(R.string.foo, new Object[] { arg1, arg2, arg3 })
        // we'll need to handle that such that we don't think this is a single
        // argument
        UExpression lastArg = args.get(args.size() - 1);
        PsiParameterList parameterList = calledMethod.getParameterList();
        int parameterCount = parameterList.getParametersCount();
        if (parameterCount > 0 && parameterList.getParameters()[parameterCount - 1].isVarArgs()) {
            boolean knownArity = false;
            boolean argWasReference = false;
            if (lastArg instanceof UReferenceExpression) {
                PsiElement resolved = ((UReferenceExpression) lastArg).resolve();
                if (resolved instanceof PsiVariable) {
                    UExpression initializer = context.getUastContext().getInitializerBody((PsiVariable) resolved);
                    if (initializer != null && (UastExpressionUtils.isNewArray(initializer) || UastExpressionUtils.isArrayInitializer(initializer))) {
                        argWasReference = true;
                        // Now handled by check below
                        lastArg = initializer;
                    }
                }
            }
            if (UastExpressionUtils.isNewArray(lastArg) || UastExpressionUtils.isArrayInitializer(lastArg)) {
                UCallExpression arrayInitializer = (UCallExpression) lastArg;
                if (UastExpressionUtils.isNewArrayWithInitializer(lastArg) || UastExpressionUtils.isArrayInitializer(lastArg)) {
                    callCount = arrayInitializer.getValueArgumentCount();
                    knownArity = true;
                } else if (UastExpressionUtils.isNewArrayWithDimensions(lastArg)) {
                    List<UExpression> arrayDimensions = arrayInitializer.getValueArguments();
                    if (arrayDimensions.size() == 1) {
                        UExpression first = arrayDimensions.get(0);
                        if (first instanceof ULiteralExpression) {
                            Object o = ((ULiteralExpression) first).getValue();
                            if (o instanceof Integer) {
                                callCount = (Integer) o;
                                knownArity = true;
                            }
                        }
                    }
                }
                if (!knownArity) {
                    if (!argWasReference) {
                        return;
                    }
                } else {
                    passingVarArgsArray = true;
                }
            }
        }
    }
    if (callCount > 0 && mNotFormatStrings.containsKey(name)) {
        checkNotFormattedHandle(context, call, name, mNotFormatStrings.get(name));
        return;
    }
    List<Pair<Handle, String>> list = mFormatStrings != null ? mFormatStrings.get(name) : null;
    if (list == null) {
        LintClient client = context.getClient();
        if (client.supportsProjectResources() && !context.getScope().contains(Scope.RESOURCE_FILE)) {
            AbstractResourceRepository resources = client.getProjectResources(context.getMainProject(), true);
            List<ResourceItem> items;
            if (resources != null) {
                items = resources.getResourceItem(ResourceType.STRING, name);
            } else {
                // Must be a non-Android module
                items = null;
            }
            if (items != null) {
                for (final ResourceItem item : items) {
                    ResourceValue v = item.getResourceValue(false);
                    if (v != null) {
                        String value = v.getRawXmlValue();
                        if (value != null) {
                            // Make sure it's really a formatting string,
                            // not for example "Battery remaining: 90%"
                            boolean isFormattingString = value.indexOf('%') != -1;
                            for (int j = 0, m = value.length(); j < m && isFormattingString; j++) {
                                char c = value.charAt(j);
                                if (c == '\\') {
                                    j++;
                                } else if (c == '%') {
                                    Matcher matcher = FORMAT.matcher(value);
                                    if (!matcher.find(j)) {
                                        isFormattingString = false;
                                    } else {
                                        String conversion = matcher.group(6);
                                        int conversionClass = getConversionClass(conversion.charAt(0));
                                        if (conversionClass == CONVERSION_CLASS_UNKNOWN || matcher.group(5) != null) {
                                            // Some date format etc - don't process
                                            return;
                                        }
                                    }
                                    // Don't process second % in a %%
                                    j++;
                                }
                            // If the user marked the string with
                            }
                            Handle handle = client.createResourceItemHandle(item);
                            if (isFormattingString) {
                                if (list == null) {
                                    list = Lists.newArrayList();
                                    if (mFormatStrings == null) {
                                        mFormatStrings = Maps.newHashMap();
                                    }
                                    mFormatStrings.put(name, list);
                                }
                                list.add(Pair.of(handle, value));
                            } else if (callCount > 0) {
                                checkNotFormattedHandle(context, call, name, handle);
                            }
                        }
                    }
                }
            }
        } else {
            return;
        }
    }
    if (list != null) {
        Set<String> reported = null;
        for (Pair<Handle, String> pair : list) {
            String s = pair.getSecond();
            if (reported != null && reported.contains(s)) {
                continue;
            }
            int count = getFormatArgumentCount(s, null);
            Handle handle = pair.getFirst();
            if (count != callCount) {
                Location location = context.getUastLocation(call);
                Location secondary = handle.resolve();
                secondary.setMessage(String.format("This definition requires %1$d arguments", count));
                location.setSecondary(secondary);
                String message = String.format("Wrong argument count, format string `%1$s` requires `%2$d` but format " + "call supplies `%3$d`", name, count, callCount);
                context.report(ARG_TYPES, call, location, message);
                if (reported == null) {
                    reported = Sets.newHashSet();
                }
                reported.add(s);
            } else {
                if (passingVarArgsArray) {
                    // flag parameters on the Object[] instead of the wrapped parameters
                    return;
                }
                for (int i = 1; i <= count; i++) {
                    int argumentIndex = i + argIndex;
                    PsiType type = args.get(argumentIndex).getExpressionType();
                    if (type != null) {
                        boolean valid = true;
                        String formatType = getFormatArgumentType(s, i);
                        if (formatType == null) {
                            continue;
                        }
                        char last = formatType.charAt(formatType.length() - 1);
                        if (formatType.length() >= 2 && Character.toLowerCase(formatType.charAt(formatType.length() - 2)) == 't') {
                            // TODO
                            continue;
                        }
                        switch(last) {
                            // unusual and probably not intended.
                            case 'b':
                            case 'B':
                                valid = isBooleanType(type);
                                break;
                            // Numeric: integer and floats in various formats
                            case 'x':
                            case 'X':
                            case 'd':
                            case 'o':
                            case 'e':
                            case 'E':
                            case 'f':
                            case 'g':
                            case 'G':
                            case 'a':
                            case 'A':
                                valid = isNumericType(type, true);
                                break;
                            case 'c':
                            case 'C':
                                // Unicode character
                                valid = isCharacterType(type);
                                break;
                            case 'h':
                            // Hex print of hash code of objects
                            case 'H':
                            case 's':
                            case 'S':
                                // String. Can pass anything, but warn about
                                // numbers since you may have meant more
                                // specific formatting. Use special issue
                                // explanation for this?
                                valid = !isBooleanType(type) && !isNumericType(type, false);
                                break;
                        }
                        if (!valid) {
                            Location location = context.getUastLocation(args.get(argumentIndex));
                            Location secondary = handle.resolve();
                            secondary.setMessage("Conflicting argument declaration here");
                            location.setSecondary(secondary);
                            String suggestion = null;
                            if (isBooleanType(type)) {
                                suggestion = "`b`";
                            } else if (isCharacterType(type)) {
                                suggestion = "'c'";
                            } else if (PsiType.INT.equals(type) || PsiType.LONG.equals(type) || PsiType.BYTE.equals(type) || PsiType.SHORT.equals(type)) {
                                suggestion = "`d`, 'o' or `x`";
                            } else if (PsiType.FLOAT.equals(type) || PsiType.DOUBLE.equals(type)) {
                                suggestion = "`e`, 'f', 'g' or `a`";
                            } else if (type instanceof PsiClassType) {
                                String fqn = type.getCanonicalText();
                                if (TYPE_INTEGER_WRAPPER.equals(fqn) || TYPE_LONG_WRAPPER.equals(fqn) || TYPE_BYTE_WRAPPER.equals(fqn) || TYPE_SHORT_WRAPPER.equals(fqn)) {
                                    suggestion = "`d`, 'o' or `x`";
                                } else if (TYPE_FLOAT_WRAPPER.equals(fqn) || TYPE_DOUBLE_WRAPPER.equals(fqn)) {
                                    suggestion = "`d`, 'o' or `x`";
                                } else if (TYPE_OBJECT.equals(fqn)) {
                                    suggestion = "'s' or 'h'";
                                }
                            }
                            if (suggestion != null) {
                                suggestion = " (Did you mean formatting character " + suggestion + "?)";
                            } else {
                                suggestion = "";
                            }
                            String canonicalText = type.getCanonicalText();
                            canonicalText = canonicalText.substring(canonicalText.lastIndexOf('.') + 1);
                            String message = String.format("Wrong argument type for formatting argument '#%1$d' " + "in `%2$s`: conversion is '`%3$s`', received `%4$s` " + "(argument #%5$d in method call)%6$s", i, name, formatType, canonicalText, argumentIndex + 1, suggestion);
                            context.report(ARG_TYPES, call, location, message);
                            if (reported == null) {
                                reported = Sets.newHashSet();
                            }
                            reported.add(s);
                        }
                    }
                }
            }
        }
    }
}
Also used : ULiteralExpression(org.jetbrains.uast.ULiteralExpression) Matcher(java.util.regex.Matcher) UCallExpression(org.jetbrains.uast.UCallExpression) AbstractResourceRepository(com.android.ide.common.res2.AbstractResourceRepository) ResourceValue(com.android.ide.common.rendering.api.ResourceValue) List(java.util.List) ArrayList(java.util.ArrayList) ImmutableList(com.google.common.collect.ImmutableList) NodeList(org.w3c.dom.NodeList) PsiParameterList(com.intellij.psi.PsiParameterList) ResourceUrl(com.android.ide.common.resources.ResourceUrl) PsiElement(com.intellij.psi.PsiElement) Pair(com.android.utils.Pair) PsiType(com.intellij.psi.PsiType) PsiVariable(com.intellij.psi.PsiVariable) LintClient(com.android.tools.klint.client.api.LintClient) Handle(com.android.tools.klint.detector.api.Location.Handle) UExpression(org.jetbrains.uast.UExpression) PsiClassType(com.intellij.psi.PsiClassType) UReferenceExpression(org.jetbrains.uast.UReferenceExpression) PsiParameterList(com.intellij.psi.PsiParameterList) ResourceItem(com.android.ide.common.res2.ResourceItem) Location(com.android.tools.klint.detector.api.Location)

Example 4 with PsiVariable

use of com.intellij.psi.PsiVariable in project intellij-community by JetBrains.

the class ConvertToInstanceMethodDialog method doAction.

protected void doAction() {
    final PsiVariable targetVariable = (PsiVariable) myList.getSelectedValue();
    LOG.assertTrue(targetVariable instanceof PsiParameter, targetVariable);
    final ConvertToInstanceMethodProcessor processor = new ConvertToInstanceMethodProcessor(myMethod.getProject(), myMethod, (PsiParameter) targetVariable, myVisibilityPanel.getVisibility());
    if (!verifyTargetClass(processor.getTargetClass()))
        return;
    invokeRefactoring(processor);
}
Also used : PsiParameter(com.intellij.psi.PsiParameter) PsiVariable(com.intellij.psi.PsiVariable)

Example 5 with PsiVariable

use of com.intellij.psi.PsiVariable in project intellij-community by JetBrains.

the class SuggestVariableNameMacro method getNames.

private static String[] getNames(final ExpressionContext context) {
    String[] names = ExpressionUtil.getNames(context);
    if (names == null || names.length == 0)
        return names;
    PsiFile file = PsiDocumentManager.getInstance(context.getProject()).getPsiFile(context.getEditor().getDocument());
    PsiElement e = file.findElementAt(context.getStartOffset());
    PsiVariable[] vars = MacroUtil.getVariablesVisibleAt(e, "");
    LinkedList<String> namesList = new LinkedList<>(Arrays.asList(names));
    for (PsiVariable var : vars) {
        if (e.equals(var.getNameIdentifier()))
            continue;
        namesList.remove(var.getName());
    }
    if (namesList.isEmpty()) {
        String name = names[0];
        index: for (int j = 1; ; j++) {
            String name1 = name + j;
            for (PsiVariable var : vars) {
                if (name1.equals(var.getName()) && !var.getNameIdentifier().equals(e))
                    continue index;
            }
            return new String[] { name1 };
        }
    }
    return ArrayUtil.toStringArray(namesList);
}
Also used : PsiVariable(com.intellij.psi.PsiVariable) PsiFile(com.intellij.psi.PsiFile) PsiElement(com.intellij.psi.PsiElement) LinkedList(java.util.LinkedList)

Aggregations

PsiVariable (com.intellij.psi.PsiVariable)14 PsiElement (com.intellij.psi.PsiElement)9 UReferenceExpression (org.jetbrains.uast.UReferenceExpression)5 Nullable (com.android.annotations.Nullable)3 ResourceUrl (com.android.ide.common.resources.ResourceUrl)3 PsiMethod (com.intellij.psi.PsiMethod)3 UCallExpression (org.jetbrains.uast.UCallExpression)3 UExpression (org.jetbrains.uast.UExpression)3 PsiClass (com.intellij.psi.PsiClass)2 PsiFile (com.intellij.psi.PsiFile)2 PsiParameter (com.intellij.psi.PsiParameter)2 PsiType (com.intellij.psi.PsiType)2 ArrayList (java.util.ArrayList)2 UElement (org.jetbrains.uast.UElement)2 UIfExpression (org.jetbrains.uast.UIfExpression)2 UParenthesizedExpression (org.jetbrains.uast.UParenthesizedExpression)2 UQualifiedReferenceExpression (org.jetbrains.uast.UQualifiedReferenceExpression)2 ResourceValue (com.android.ide.common.rendering.api.ResourceValue)1 AbstractResourceRepository (com.android.ide.common.res2.AbstractResourceRepository)1 ResourceItem (com.android.ide.common.res2.ResourceItem)1