com.android.tools.lint.client.api.JavaParser Java Examples

The following examples show how to use com.android.tools.lint.client.api.JavaParser. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: GetSignaturesDetector.java    From javaide with GNU General Public License v3.0 6 votes vote down vote up
@Override
public void visitMethod(@NonNull JavaContext context, @Nullable AstVisitor visitor,
        @NonNull MethodInvocation node) {
    ResolvedNode resolved = context.resolve(node);

    if (!(resolved instanceof ResolvedMethod) ||
            !((ResolvedMethod) resolved).getContainingClass()
                    .isSubclassOf(PACKAGE_MANAGER_CLASS, false)) {
        return;
    }
    StrictListAccessor<Expression, MethodInvocation> argumentList = node.astArguments();

    // Ignore if the method doesn't fit our description.
    if (argumentList != null && argumentList.size() == 2) {
        TypeDescriptor firstParameterType = context.getType(argumentList.first());
        if (firstParameterType != null
            && firstParameterType.matchesSignature(JavaParser.TYPE_STRING)) {
            maybeReportIssue(calculateValue(context, argumentList.last()), context, node);
        }
    }
}
 
Example #2
Source File: WrongCallDetector.java    From javaide with GNU General Public License v3.0 6 votes vote down vote up
private static void report(JavaContext context, MethodInvocation node) {
    // Make sure the call is on a view
    JavaParser.ResolvedNode resolved = context.resolve(node);
    if (resolved instanceof JavaParser.ResolvedMethod) {
        JavaParser.ResolvedMethod method = (JavaParser.ResolvedMethod) resolved;
        JavaParser.ResolvedClass containingClass = method.getContainingClass();
        if (!containingClass.isSubclassOf(CLASS_VIEW, false)) {
            return;
        }
    }

    String name = node.astName().astValue();
    String suggestion = Character.toLowerCase(name.charAt(2)) + name.substring(3);
    String message = String.format(
            // Keep in sync with {@link #getOldValue} and {@link #getNewValue} below!
            "Suspicious method call; should probably call \"`%1$s`\" rather than \"`%2$s`\"",
            suggestion, name);
    context.report(ISSUE, node, context.getLocation(node.astName()), message);
}
 
Example #3
Source File: LogDetector.java    From MeituanLintDemo with Apache License 2.0 6 votes vote down vote up
@Override
public AstVisitor createJavaVisitor(final JavaContext context) {
    return new ForwardingAstVisitor() {
        @Override
        public boolean visitMethodInvocation(MethodInvocation node) {
            JavaParser.ResolvedNode resolve = context.resolve(node);
            if (resolve instanceof JavaParser.ResolvedMethod) {
                JavaParser.ResolvedMethod method = (JavaParser.ResolvedMethod) resolve;
                // 方法所在的类校验
                JavaParser.ResolvedClass containingClass = method.getContainingClass();
                if (containingClass.matches("android.util.Log")) {
                    context.report(ISSUE, node, context.getLocation(node),
                                   "请使用Ln,避免使用Log");
                    return true;
                }
                if (node.toString().startsWith("System.out.println")) {
                    context.report(ISSUE, node, context.getLocation(node),
                                   "请使用Ln,避免使用System.out.println");
                    return true;
                }
            }
            return super.visitMethodInvocation(node);
        }
    };
}
 
Example #4
Source File: JavaContext.java    From javaide with GNU General Public License v3.0 5 votes vote down vote up
/**
 * Returns true if the given method invocation node corresponds to a call on a
 * {@code android.content.Context}
 *
 * @param node the method call node
 * @return true iff the method call is on a class extending context
 */
public boolean isContextMethod(@NonNull MethodInvocation node) {
    // Method name used in many other contexts where it doesn't have the
    // same semantics; only use this one if we can resolve types
    // and we're certain this is the Context method
    ResolvedNode resolved = resolve(node);
    if (resolved instanceof JavaParser.ResolvedMethod) {
        JavaParser.ResolvedMethod method = (JavaParser.ResolvedMethod) resolved;
        ResolvedClass containingClass = method.getContainingClass();
        if (containingClass.isSubclassOf(CLASS_CONTEXT, false)) {
            return true;
        }
    }
    return false;
}
 
Example #5
Source File: ParcelDetector.java    From javaide with GNU General Public License v3.0 5 votes vote down vote up
@Override
public boolean visitClassDeclaration(ClassDeclaration node) {
    // Only applies to concrete classes
    int flags = node.astModifiers().getExplicitModifierFlags();
    if ((flags & (Opcodes.ACC_INTERFACE | Opcodes.ACC_ABSTRACT)) != 0) {
        return true;
    }

    if (node.astImplementing() != null)
        for (TypeReference reference : node.astImplementing()) {
            String name = reference.astParts().last().astIdentifier().astValue();
            if (name.equals("Parcelable")) {
                JavaParser.ResolvedNode resolved = mContext.resolve(node);
                if (resolved instanceof ResolvedClass) {
                    ResolvedClass cls = (ResolvedClass) resolved;
                    ResolvedField field = cls.getField("CREATOR", false);
                    if (field == null) {
                        // Make doubly sure that we're really implementing
                        // android.os.Parcelable
                        JavaParser.ResolvedNode r = mContext.resolve(reference);
                        if (r instanceof ResolvedClass) {
                            ResolvedClass parcelable = (ResolvedClass) r;
                            if (!parcelable.isSubclassOf("android.os.Parcelable", false)) {
                                return true;
                            }
                        }
                        Location location = mContext.getLocation(node.astName());
                        mContext.report(ISSUE, node, location,
                                "This class implements `Parcelable` but does not "
                                        + "provide a `CREATOR` field");
                    }
                }
                break;
            }
        }

    return true;
}
 
Example #6
Source File: StringFormatDetector.java    From javaide with GNU General Public License v3.0 5 votes vote down vote up
private static boolean isSharedPreferenceGetString(@NonNull JavaContext context,
        @NonNull MethodInvocation call) {
    if (!GET_STRING_METHOD.equals(call.astName().astValue())) {
        return false;
    }

    JavaParser.ResolvedNode resolved = context.resolve(call);
    if (resolved instanceof JavaParser.ResolvedMethod) {
        JavaParser.ResolvedMethod resolvedMethod = (JavaParser.ResolvedMethod) resolved;
        JavaParser.ResolvedClass containingClass = resolvedMethod.getContainingClass();
        return containingClass.isSubclassOf(ANDROID_CONTENT_SHARED_PREFERENCES, false);
    }

    return false; // not certain
}
 
Example #7
Source File: EcjParserTest.java    From javaide with GNU General Public License v3.0 5 votes vote down vote up
public void testTryCatchHang() throws Exception {
    // Ensure that we're really using this parser
    JavaParser javaParser = createClient().getJavaParser(null);
    assertNotNull(javaParser);
    assertTrue(javaParser.getClass().getName(), javaParser instanceof EcjParser);

    // See https://code.google.com/p/projectlombok/issues/detail?id=573#c6
    // With lombok.ast 0.2.1 and the parboiled-based Java parser this test will hang forever.
    assertEquals(
            "No warnings.",

            lintProject("src/test/pkg/TryCatchHang.java.txt=>src/test/pkg/TryCatchHang.java"));
}
 
Example #8
Source File: UnsafeAndroidDetector.java    From SafelyAndroid with MIT License 5 votes vote down vote up
private boolean isInsideDialogFragment(JavaContext context, MethodInvocation node) {
    Node parent = node.getParent();
    while (parent != null) {
        Object resolvedNode = context.resolve(parent);
        if (resolvedNode instanceof JavaParser.ResolvedMethod) {
            JavaParser.ResolvedMethod method = (JavaParser.ResolvedMethod) resolvedNode;
            if (isDialogFragment(method.getContainingClass())) {
                return true;
            }
        }
        parent = parent.getParent();
    }
    return false;
}
 
Example #9
Source File: UnsafeAndroidDetector.java    From SafelyAndroid with MIT License 5 votes vote down vote up
private boolean isDialogFragment(JavaParser.ResolvedClass clazz) {
    JavaParser.ResolvedClass superClazz = clazz;
    while (superClazz != null) {
        String name = superClazz.getName();
        if (DIALOG_FRAGMENT.equals(name) || V4_DIALOG_FRAGMENT.equals(name)) {
            return true;
        }
        superClazz = superClazz.getSuperClass();
    }
    return false;
}
 
Example #10
Source File: JavaContext.java    From javaide with GNU General Public License v3.0 4 votes vote down vote up
@NonNull
public JavaParser getParser() {
    return mParser;
}
 
Example #11
Source File: SharedPrefsDetector.java    From javaide with GNU General Public License v3.0 4 votes vote down vote up
@Override
public boolean visitMethodInvocation(MethodInvocation node) {
    if (node == mTarget) {
        mSeenTarget = true;
    } else if (mAllowCommitBeforeTarget || mSeenTarget || node.astOperand() == mTarget) {
        String name = node.astName().astValue();
        boolean isCommit = "commit".equals(name);
        if (isCommit || "apply".equals(name)) { //$NON-NLS-1$ //$NON-NLS-2$
            // TODO: Do more flow analysis to see whether we're really calling commit/apply
            // on the right type of object?
            mFound = true;

            ResolvedNode resolved = mContext.resolve(node);
            if (resolved instanceof JavaParser.ResolvedMethod) {
                ResolvedMethod method = (ResolvedMethod) resolved;
                JavaParser.ResolvedClass clz = method.getContainingClass();
                if (clz.isSubclassOf("android.content.SharedPreferences.Editor", false)
                        && mContext.getProject().getMinSdkVersion().getApiLevel() >= 9) {
                    // See if the return value is read: can only replace commit with
                    // apply if the return value is not considered
                    Node parent = node.getParent();
                    boolean returnValueIgnored = false;
                    if (parent instanceof MethodDeclaration ||
                            parent instanceof ConstructorDeclaration ||
                            parent instanceof ClassDeclaration ||
                            parent instanceof Block ||
                            parent instanceof ExpressionStatement) {
                        returnValueIgnored = true;
                    } else if (parent instanceof Statement) {
                        if (parent instanceof If) {
                            returnValueIgnored = ((If) parent).astCondition() != node;
                        } else if (parent instanceof Return) {
                            returnValueIgnored = false;
                        } else if (parent instanceof VariableDeclaration) {
                            returnValueIgnored = false;
                        } else if (parent instanceof For) {
                            returnValueIgnored = ((For) parent).astCondition() != node;
                        } else if (parent instanceof While) {
                            returnValueIgnored = ((While) parent).astCondition() != node;
                        } else if (parent instanceof DoWhile) {
                            returnValueIgnored = ((DoWhile) parent).astCondition() != node;
                        } else if (parent instanceof Case) {
                            returnValueIgnored = ((Case) parent).astCondition() != node;
                        } else if (parent instanceof Assert) {
                            returnValueIgnored = ((Assert) parent).astAssertion() != node;
                        } else {
                            returnValueIgnored = true;
                        }
                    }
                    if (returnValueIgnored && isCommit) {
                        String message = "Consider using `apply()` instead; `commit` writes "
                                + "its data to persistent storage immediately, whereas "
                                + "`apply` will handle it in the background";
                        mContext.report(ISSUE, node, mContext.getLocation(node), message);
                    }
                }
            }
        }
    }

    return super.visitMethodInvocation(node);
}
 
Example #12
Source File: RtlDetector.java    From javaide with GNU General Public License v3.0 4 votes vote down vote up
@Override
public boolean visitIdentifier(Identifier node) {
    String identifier = node.astValue();
    boolean isLeft = LEFT_FIELD.equals(identifier);
    boolean isRight = RIGHT_FIELD.equals(identifier);
    if (!isLeft && !isRight) {
        return false;
    }

    Node parent = node.getParent();
    if (parent instanceof ImportDeclaration || parent instanceof EnumConstant
            || parent instanceof VariableDefinitionEntry) {
        return false;
    }

    JavaParser.ResolvedNode resolved = mContext.resolve(node);
    if (resolved != null) {
        if (!(resolved instanceof JavaParser.ResolvedField)) {
            return false;
        } else {
            JavaParser.ResolvedField field = (JavaParser.ResolvedField) resolved;
            if (!field.getContainingClass().matches(FQCN_GRAVITY)) {
                return false;
            }
        }
    } else {
        // Can't resolve types (for example while editing code with errors):
        // rely on heuristics like import statements and class qualifiers
        if (parent instanceof Select &&
                !(GRAVITY_CLASS.equals(((Select) parent).astOperand().toString()))) {
            return false;
        }
        if (parent instanceof VariableReference) {
            // No operand: make sure it's statically imported
            if (!LintUtils.isImported(mContext.getCompilationUnit(),
                    FQCN_GRAVITY_PREFIX + identifier)) {
                return false;
            }
        }
    }

    String message = String.format(
            "Use \"`Gravity.%1$s`\" instead of \"`Gravity.%2$s`\" to ensure correct "
                    + "behavior in right-to-left locales",
            (isLeft ? GRAVITY_VALUE_START : GRAVITY_VALUE_END).toUpperCase(Locale.US),
            (isLeft ? GRAVITY_VALUE_LEFT : GRAVITY_VALUE_RIGHT).toUpperCase(Locale.US));
    Location location = mContext.getLocation(node);
    mContext.report(USE_START, node, location, message);

    return true;
}
 
Example #13
Source File: EcjParserTest.java    From javaide with GNU General Public License v3.0 4 votes vote down vote up
public AstPrettyPrinter(JavaParser resolver) {
    mResolver = resolver;
}
 
Example #14
Source File: EcjParserTest.java    From javaide with GNU General Public License v3.0 4 votes vote down vote up
private void buildNode(Node node) {
    if (node == null) {
        mIndent++;
        return;
    }
    String name = node.getClass().getSimpleName();
    String description = "";
    if (node instanceof DescribedNode) {
        description = " " + ((DescribedNode) node).getDescription();
    }

    String typeDescription = "";
    String resolutionDescription = "";
    JavaParser.TypeDescriptor t = mResolver.getType(null, node);
    if (t != null) {
        typeDescription = ", type: " + t.getName();
    }
    ResolvedNode resolved = mResolver.resolve(null, node);
    if (resolved != null) {
        String c = "unknown";
        String extra = "";
        if (resolved instanceof ResolvedClass) {
            c = "class";
        } else if (resolved instanceof ResolvedMethod) {
            c = "method";
            ResolvedMethod method = (ResolvedMethod) resolved;
            extra = method.getContainingClass().getName();
        } else if (resolved instanceof ResolvedField) {
            c = "field";
            ResolvedField field = (ResolvedField) resolved;
            extra = field.getContainingClass().getName();
        } else if (resolved instanceof ResolvedVariable) {
            c = "variable";
            ResolvedVariable variable = (ResolvedVariable) resolved;
            extra = variable.getType().getName();
        } else if (resolved instanceof ResolvedAnnotation) {
            c = "annotation";
        }
        resolutionDescription = String.format(", resolved %1$s: %2$s %3$s",
                c, resolved.getName(), extra);
    }

    add("[%1$s%2$s]%3$s%4$s\n", name, description, typeDescription, resolutionDescription);

    mIndent++;
}
 
Example #15
Source File: LintCliClient.java    From javaide with GNU General Public License v3.0 4 votes vote down vote up
@Override
public JavaParser getJavaParser(@Nullable Project project) {
    return new EcjParser(this, project);
}
 
Example #16
Source File: JavaContext.java    From javaide with GNU General Public License v3.0 3 votes vote down vote up
/**
 * Constructs a {@link JavaContext} for running lint on the given file, with
 * the given scope, in the given project reporting errors to the given
 * client.
 *
 * @param driver the driver running through the checks
 * @param project the project to run lint on which contains the given file
 * @param main the main project if this project is a library project, or
 *            null if this is not a library project. The main project is
 *            the root project of all library projects, not necessarily the
 *            directly including project.
 * @param file the file to be analyzed
 * @param parser the parser to use
 */
public JavaContext(
        @NonNull LintDriver driver,
        @NonNull Project project,
        @Nullable Project main,
        @NonNull File file,
        @NonNull JavaParser parser) {
    super(driver, project, main, file);
    mParser = parser;
}