blob: 00ad0c6336ec6eba69eabcccc28c25ff3a407099 [file] [log] [blame]
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.tools.lint.detector.api
import org.objectweb.asm.tree.AbstractInsnNode
import org.objectweb.asm.tree.ClassNode
import org.objectweb.asm.tree.MethodInsnNode
import org.objectweb.asm.tree.MethodNode
/** Specialized interface for detectors that scan bytecode / compiled class files */
interface ClassScanner : FileScanner {
/**
* Returns the list of node types (corresponding to the constants in the
* [AbstractInsnNode] class) that this scanner applies to. The
* [.checkInstruction] method will be called for each match.
*
* @return an array containing all the node types this detector should be
* called for, or null if none.
*/
fun getApplicableAsmNodeTypes(): IntArray?
/**
* Process a given instruction node, and register lint issues if
* applicable.
*
* @param context the context of the lint check, pointing to for example
* the file
* @param classNode the root class node
* @param method the method node containing the call
* @param instruction the actual instruction
*/
fun checkInstruction(
context: ClassContext,
classNode: ClassNode,
method: MethodNode,
instruction: AbstractInsnNode
)
/**
* Return the list of method call names (in VM format, e.g. `"<init>"` for
* constructors, etc) for method calls this detector is interested in,
* or null. T his will be used to dispatch calls to
* [.checkCall]
* for only the method calls in owners that the detector is interested
* in.
*
* **NOTE**: If you return non null from this method, then **only**
* [.checkCall] will be called if a suitable method is found;
* [.checkClass] will not be called under any circumstances.
*
* This makes it easy to write detectors that focus on some fixed calls,
* and allows lint to make a single pass over the bytecode over a class,
* and efficiently dispatch method calls to any detectors that are
* interested in it. Without this, each new lint check interested in a
* single method, would be doing a complete pass through all the
* bytecode instructions of the class via the
* [.checkClass] method, which would make
* each newly added lint check make lint slower. Now a single dispatch
* map is used instead, and for each encountered call in the single
* dispatch, it looks up in the map which if any detectors are
* interested in the given call name, and dispatches to each one in
* turn.
*
* @return a list of applicable method names, or null.
*/
fun getApplicableCallNames(): List<String>?
/**
* Just like [Detector.getApplicableCallNames], but for the owner
* field instead. The [.checkCall]
* method will be called for all [MethodInsnNode] instances where the
* owner field matches any of the members returned in this node.
*
*
* Note that if your detector provides both a name and an owner, the
* method will be called for any nodes matching either the name **or**
* the owner, not only where they match **both**. Note also that it will
* be called twice - once for the name match, and (at least once) for the owner
* match.
*
* @return a list of applicable owner names, or null.
*/
fun getApplicableCallOwners(): List<String>?
/**
* Process a given method call node, and register lint issues if
* applicable. This is similar to the
* [.checkInstruction]
* method, but has the additional advantage that it is only called for known
* method names or method owners, according to
* [.getApplicableCallNames] and [.getApplicableCallOwners].
*
* @param context the context of the lint check, pointing to for example
* the file
* @param classNode the root class node
* @param method the method node containing the call
* @param call the actual method call node
*/
fun checkCall(
context: ClassContext,
classNode: ClassNode,
method: MethodNode,
call: MethodInsnNode
)
/**
* Checks the given class' bytecode for issues.
*
* @param context the context of the lint check, pointing to for example
* the file
* @param classNode the root class node
*/
fun checkClass(context: ClassContext, classNode: ClassNode)
}