Search in sources :

Example 11 with Detector

use of com.android.tools.klint.detector.api.Detector in project kotlin by JetBrains.

the class LintDriver method checkResourceFolder.

private void checkResourceFolder(@NonNull Project project, @Nullable Project main, @NonNull File dir, @NonNull ResourceFolderType type, @NonNull List<ResourceXmlDetector> xmlChecks, @Nullable List<Detector> dirChecks, @Nullable List<Detector> binaryChecks) {
    if (dirChecks != null && !dirChecks.isEmpty()) {
        ResourceContext context = new ResourceContext(this, project, main, dir, type);
        String folderName = dir.getName();
        fireEvent(EventType.SCANNING_FILE, context);
        for (Detector check : dirChecks) {
            if (check.appliesTo(type)) {
                check.beforeCheckFile(context);
                check.checkFolder(context, folderName);
                check.afterCheckFile(context);
            }
        }
        if (binaryChecks == null && xmlChecks.isEmpty()) {
            return;
        }
    }
    File[] files = dir.listFiles();
    if (files == null || files.length <= 0) {
        return;
    }
    ResourceVisitor visitor = getVisitor(type, xmlChecks, binaryChecks);
    if (visitor != null) {
        // if not, there are no applicable rules in this folder
        // Process files in alphabetical order, to ensure stable output
        // (for example for the duplicate resource detector)
        Arrays.sort(files);
        for (File file : files) {
            if (LintUtils.isXmlFile(file)) {
                XmlContext context = new XmlContext(this, project, main, file, type, visitor.getParser());
                fireEvent(EventType.SCANNING_FILE, context);
                visitor.visitFile(context, file);
            } else if (binaryChecks != null && (LintUtils.isBitmapFile(file) || type == ResourceFolderType.RAW)) {
                ResourceContext context = new ResourceContext(this, project, main, file, type);
                fireEvent(EventType.SCANNING_FILE, context);
                visitor.visitBinaryResource(context);
            }
            if (mCanceled) {
                return;
            }
        }
    }
}
Also used : ResourceContext(com.android.tools.klint.detector.api.ResourceContext) ResourceXmlDetector(com.android.tools.klint.detector.api.ResourceXmlDetector) Detector(com.android.tools.klint.detector.api.Detector) XmlContext(com.android.tools.klint.detector.api.XmlContext) File(java.io.File) PsiFile(com.intellij.psi.PsiFile)

Example 12 with Detector

use of com.android.tools.klint.detector.api.Detector in project kotlin by JetBrains.

the class LintDriver method runClassDetectors.

private void runClassDetectors(Scope scope, List<ClassEntry> entries, Project project, Project main) {
    if (mScope.contains(scope)) {
        List<Detector> classDetectors = mScopeDetectors.get(scope);
        if (classDetectors != null && !classDetectors.isEmpty() && !entries.isEmpty()) {
            AsmVisitor visitor = new AsmVisitor(mClient, classDetectors);
            String sourceContents = null;
            String sourceName = "";
            mOuterClasses = new ArrayDeque<ClassNode>();
            ClassEntry prev = null;
            for (ClassEntry entry : entries) {
                if (prev != null && prev.compareTo(entry) == 0) {
                    // Duplicate entries for some reason: ignore
                    continue;
                }
                prev = entry;
                ClassReader reader;
                ClassNode classNode;
                try {
                    reader = new ClassReader(entry.bytes);
                    classNode = new ClassNode();
                    reader.accept(classNode, 0);
                } catch (Throwable t) {
                    mClient.log(null, "Error processing %1$s: broken class file?", entry.path());
                    continue;
                }
                ClassNode peek;
                while ((peek = mOuterClasses.peek()) != null) {
                    if (classNode.name.startsWith(peek.name)) {
                        break;
                    } else {
                        mOuterClasses.pop();
                    }
                }
                mOuterClasses.push(classNode);
                if (isSuppressed(null, classNode)) {
                    // Class was annotated with suppress all -- no need to look any further
                    continue;
                }
                if (sourceContents != null) {
                    // Attempt to reuse the source buffer if initialized
                    // This means making sure that the source files
                    //    foo/bar/MyClass and foo/bar/MyClass$Bar
                    //    and foo/bar/MyClass$3 and foo/bar/MyClass$3$1 have the same prefix.
                    String newName = classNode.name;
                    int newRootLength = newName.indexOf('$');
                    if (newRootLength == -1) {
                        newRootLength = newName.length();
                    }
                    int oldRootLength = sourceName.indexOf('$');
                    if (oldRootLength == -1) {
                        oldRootLength = sourceName.length();
                    }
                    if (newRootLength != oldRootLength || !sourceName.regionMatches(0, newName, 0, newRootLength)) {
                        sourceContents = null;
                    }
                }
                ClassContext context = new ClassContext(this, project, main, entry.file, entry.jarFile, entry.binDir, entry.bytes, classNode, scope == Scope.JAVA_LIBRARIES, /*fromLibrary*/
                sourceContents);
                try {
                    visitor.runClassDetectors(context);
                } catch (Exception e) {
                    mClient.log(e, null);
                }
                if (mCanceled) {
                    return;
                }
                sourceContents = context.getSourceContents(false);
                sourceName = classNode.name;
            }
            mOuterClasses = null;
        }
    }
}
Also used : ClassNode(org.jetbrains.org.objectweb.asm.tree.ClassNode) ResourceXmlDetector(com.android.tools.klint.detector.api.ResourceXmlDetector) Detector(com.android.tools.klint.detector.api.Detector) ClassContext(com.android.tools.klint.detector.api.ClassContext) ClassReader(org.jetbrains.org.objectweb.asm.ClassReader) IOException(java.io.IOException)

Example 13 with Detector

use of com.android.tools.klint.detector.api.Detector in project kotlin by JetBrains.

the class LintDriver method runFileDetectors.

private void runFileDetectors(@NonNull Project project, @Nullable Project main) {
    // Look up manifest information (but not for library projects)
    if (project.isAndroidProject()) {
        for (File manifestFile : project.getManifestFiles()) {
            XmlParser parser = mClient.getXmlParser();
            if (parser != null) {
                XmlContext context = new XmlContext(this, project, main, manifestFile, null, parser);
                context.document = parser.parseXml(context);
                if (context.document != null) {
                    try {
                        project.readManifest(context.document);
                        if ((!project.isLibrary() || (main != null && main.isMergingManifests())) && mScope.contains(Scope.MANIFEST)) {
                            List<Detector> detectors = mScopeDetectors.get(Scope.MANIFEST);
                            if (detectors != null) {
                                ResourceVisitor v = new ResourceVisitor(parser, detectors, null);
                                fireEvent(EventType.SCANNING_FILE, context);
                                v.visitFile(context, manifestFile);
                            }
                        }
                    } finally {
                        if (context.document != null) {
                            // else: freed by XmlVisitor above
                            parser.dispose(context, context.document);
                        }
                    }
                }
            }
        }
        // in a single pass through the resource directories.
        if (mScope.contains(Scope.ALL_RESOURCE_FILES) || mScope.contains(Scope.RESOURCE_FILE) || mScope.contains(Scope.RESOURCE_FOLDER) || mScope.contains(Scope.BINARY_RESOURCE_FILE)) {
            List<Detector> dirChecks = mScopeDetectors.get(Scope.RESOURCE_FOLDER);
            List<Detector> binaryChecks = mScopeDetectors.get(Scope.BINARY_RESOURCE_FILE);
            List<Detector> checks = union(mScopeDetectors.get(Scope.RESOURCE_FILE), mScopeDetectors.get(Scope.ALL_RESOURCE_FILES));
            boolean haveXmlChecks = checks != null && !checks.isEmpty();
            List<ResourceXmlDetector> xmlDetectors;
            if (haveXmlChecks) {
                xmlDetectors = new ArrayList<ResourceXmlDetector>(checks.size());
                for (Detector detector : checks) {
                    if (detector instanceof ResourceXmlDetector) {
                        xmlDetectors.add((ResourceXmlDetector) detector);
                    }
                }
                haveXmlChecks = !xmlDetectors.isEmpty();
            } else {
                xmlDetectors = Collections.emptyList();
            }
            if (haveXmlChecks || dirChecks != null && !dirChecks.isEmpty() || binaryChecks != null && !binaryChecks.isEmpty()) {
                List<File> files = project.getSubset();
                if (files != null) {
                    checkIndividualResources(project, main, xmlDetectors, dirChecks, binaryChecks, files);
                } else {
                    List<File> resourceFolders = project.getResourceFolders();
                    if (!resourceFolders.isEmpty()) {
                        for (File res : resourceFolders) {
                            checkResFolder(project, main, res, xmlDetectors, dirChecks, binaryChecks);
                        }
                    }
                }
            }
        }
        if (mCanceled) {
            return;
        }
    }
    if (mScope.contains(Scope.JAVA_FILE) || mScope.contains(Scope.ALL_JAVA_FILES)) {
        List<Detector> checks = union(mScopeDetectors.get(Scope.JAVA_FILE), mScopeDetectors.get(Scope.ALL_JAVA_FILES));
        if (checks != null && !checks.isEmpty()) {
            List<File> files = project.getSubset();
            if (files != null) {
                checkIndividualJavaFiles(project, main, checks, files);
            } else {
                List<File> sourceFolders = project.getJavaSourceFolders();
                if (mScope.contains(Scope.TEST_SOURCES)) {
                    List<File> testFolders = project.getTestSourceFolders();
                    if (!testFolders.isEmpty()) {
                        List<File> combined = Lists.newArrayListWithExpectedSize(sourceFolders.size() + testFolders.size());
                        combined.addAll(sourceFolders);
                        combined.addAll(testFolders);
                        sourceFolders = combined;
                    }
                }
                checkJava(project, main, sourceFolders, checks);
            }
        }
    }
    if (mCanceled) {
        return;
    }
    if (mScope.contains(Scope.CLASS_FILE) || mScope.contains(Scope.ALL_CLASS_FILES) || mScope.contains(Scope.JAVA_LIBRARIES)) {
        checkClasses(project, main);
    }
    if (mCanceled) {
        return;
    }
    if (mScope.contains(Scope.GRADLE_FILE)) {
        checkBuildScripts(project, main);
    }
    if (mCanceled) {
        return;
    }
    if (mScope.contains(Scope.OTHER)) {
        List<Detector> checks = mScopeDetectors.get(Scope.OTHER);
        if (checks != null) {
            OtherFileVisitor visitor = new OtherFileVisitor(checks);
            visitor.scan(this, project, main);
        }
    }
    if (mCanceled) {
        return;
    }
    if (project == main && mScope.contains(Scope.PROGUARD_FILE) && project.isAndroidProject()) {
        checkProGuard(project, main);
    }
    if (project == main && mScope.contains(Scope.PROPERTY_FILE)) {
        checkProperties(project, main);
    }
}
Also used : ResourceXmlDetector(com.android.tools.klint.detector.api.ResourceXmlDetector) Detector(com.android.tools.klint.detector.api.Detector) XmlContext(com.android.tools.klint.detector.api.XmlContext) ResourceXmlDetector(com.android.tools.klint.detector.api.ResourceXmlDetector) File(java.io.File) PsiFile(com.intellij.psi.PsiFile)

Example 14 with Detector

use of com.android.tools.klint.detector.api.Detector in project kotlin by JetBrains.

the class LintDriver method visitJavaFiles.

private void visitJavaFiles(@NonNull List<Detector> checks, JavaParser javaParser, List<JavaContext> contexts) {
    // Temporary: we still have some builtin checks that aren't migrated to
    // PSI. Until that's complete, remove them from the list here
    //List<Detector> scanners = checks;
    List<Detector> scanners = Lists.newArrayListWithCapacity(0);
    List<Detector> uastScanners = Lists.newArrayListWithCapacity(checks.size());
    for (Detector detector : checks) {
        if (detector instanceof Detector.JavaPsiScanner) {
            scanners.add(detector);
        } else if (detector instanceof Detector.UastScanner) {
            uastScanners.add(detector);
        }
    }
    if (!scanners.isEmpty()) {
        JavaPsiVisitor visitor = new JavaPsiVisitor(javaParser, scanners);
        visitor.prepare(contexts);
        for (JavaContext context : contexts) {
            fireEvent(EventType.SCANNING_FILE, context);
            visitor.visitFile(context);
            if (mCanceled) {
                return;
            }
        }
        visitor.dispose();
    }
    if (!uastScanners.isEmpty()) {
        final UElementVisitor uElementVisitor = new UElementVisitor(javaParser, uastScanners);
        uElementVisitor.prepare(contexts);
        for (final JavaContext context : contexts) {
            fireEvent(EventType.SCANNING_FILE, context);
            ApplicationManager.getApplication().runReadAction(new Runnable() {

                @Override
                public void run() {
                    uElementVisitor.visitFile(context);
                }
            });
            if (mCanceled) {
                return;
            }
        }
        uElementVisitor.dispose();
    }
    //noinspection ConstantConditions
    if (mRunCompatChecks) {
        // Filter the checks to only those that implement JavaScanner
        List<Detector> filtered = Lists.newArrayListWithCapacity(checks.size());
        for (Detector detector : checks) {
            if (detector instanceof Detector.JavaScanner) {
                filtered.add(detector);
            }
        }
        if (!filtered.isEmpty()) {
            List<String> detectorNames = Lists.newArrayListWithCapacity(filtered.size());
            for (Detector detector : filtered) {
                detectorNames.add(detector.getClass().getName());
            }
            Collections.sort(detectorNames);
            /* Let's not complain quite yet
                String message = String.format("Lint found one or more custom checks using its "
                        + "older Java API; these checks are still run in compatibility mode, "
                        + "but this causes duplicated parsing, and in the next version lint "
                        + "will no longer include this legacy mode. Make sure the following "
                        + "lint detectors are upgraded to the new API: %1$s",
                        Joiner.on(", ").join(detectorNames));
                JavaContext first = contexts.get(0);
                Project project = first.getProject();
                Location location = Location.create(project.getDir());
                mClient.report(first,
                        IssueRegistry.LINT_ERROR,
                        project.getConfiguration(this).getSeverity(IssueRegistry.LINT_ERROR),
                        location, message, TextFormat.RAW);
                */
            JavaVisitor oldVisitor = new JavaVisitor(javaParser, filtered);
            oldVisitor.prepare(contexts);
            for (JavaContext context : contexts) {
                fireEvent(EventType.SCANNING_FILE, context);
                oldVisitor.visitFile(context);
                if (mCanceled) {
                    return;
                }
            }
            oldVisitor.dispose();
        }
    }
}
Also used : JavaContext(com.android.tools.klint.detector.api.JavaContext) ResourceXmlDetector(com.android.tools.klint.detector.api.ResourceXmlDetector) Detector(com.android.tools.klint.detector.api.Detector)

Example 15 with Detector

use of com.android.tools.klint.detector.api.Detector in project kotlin by JetBrains.

the class LintDriver method checkPropertyFile.

private void checkPropertyFile(Project project, Project main, List<Detector> detectors, String relativePath) {
    File file = new File(project.getDir(), relativePath);
    if (file.exists()) {
        Context context = new Context(this, project, main, file);
        fireEvent(EventType.SCANNING_FILE, context);
        for (Detector detector : detectors) {
            if (detector.appliesTo(context, file)) {
                detector.beforeCheckFile(context);
                detector.run(context);
                detector.afterCheckFile(context);
            }
        }
    }
}
Also used : ClassContext(com.android.tools.klint.detector.api.ClassContext) XmlContext(com.android.tools.klint.detector.api.XmlContext) JavaContext(com.android.tools.klint.detector.api.JavaContext) ResourceContext(com.android.tools.klint.detector.api.ResourceContext) Context(com.android.tools.klint.detector.api.Context) ResourceXmlDetector(com.android.tools.klint.detector.api.ResourceXmlDetector) Detector(com.android.tools.klint.detector.api.Detector) File(java.io.File) PsiFile(com.intellij.psi.PsiFile)

Aggregations

Detector (com.android.tools.klint.detector.api.Detector)16 ResourceXmlDetector (com.android.tools.klint.detector.api.ResourceXmlDetector)11 File (java.io.File)7 XmlContext (com.android.tools.klint.detector.api.XmlContext)6 PsiFile (com.intellij.psi.PsiFile)6 ClassContext (com.android.tools.klint.detector.api.ClassContext)5 Context (com.android.tools.klint.detector.api.Context)5 JavaContext (com.android.tools.klint.detector.api.JavaContext)5 ResourceContext (com.android.tools.klint.detector.api.ResourceContext)5 ArrayList (java.util.ArrayList)5 Scope (com.android.tools.klint.detector.api.Scope)3 List (java.util.List)3 Issue (com.android.tools.klint.detector.api.Issue)2 EnumMap (java.util.EnumMap)2 EnumSet (java.util.EnumSet)2 HashMap (java.util.HashMap)2 HashSet (java.util.HashSet)2 ClassNode (org.jetbrains.org.objectweb.asm.tree.ClassNode)2 InsnList (org.jetbrains.org.objectweb.asm.tree.InsnList)2 NonNull (com.android.annotations.NonNull)1