我认为通过实现自定义的linter来学习静态代码分析既有趣又有益。我一直在尝试声明以下依赖项:
dependencies {
compileOnly "com.android.tools.lint:lint-api:30.1.2"
compileOnly "com.android.tools.lint:lint-checks:30.1.2"
}
但是Gradle报错说无法解析这些依赖项。经过一番了解,我发现MavenCentral和Google针对这些库似乎有不同的版本号,其中Google使用的是上面代码片段中描述的版本,而MavenCentral的最新版本是25.3.0。如果我使用MavenCentral上描述的版本号替换掉这些版本号,则Gradle可以解析这些依赖项,但我的自定义linter代码将完全被标红并出现错误。
Cannot access 'java.lang.Object' which is a supertype of my_custom_linter. Check your module classpath for missing or conflicting dependencies
有许多关于此错误的SO帖子,而那些已经解决的很少,都是通过使用可用依赖项的最新版本来解决的,在我的情况下,这又回到了本文描述的第一个错误。
项目级别的build.gradle
:
buildscript {
repositories {
google()
}
dependencies {
classpath "com.android.tools.build:gradle:7.0.4"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.10"
}
}
plugins {
id 'com.android.application' version '7.1.2' apply false
id 'com.android.library' version '7.1.2' apply false
id 'org.jetbrains.kotlin.android' version '1.6.10' apply false
id 'org.jetbrains.kotlin.jvm' version '1.6.10' apply false
}
task clean(type: Delete) {
delete rootProject.buildDir
}
build.gradle
中的 Lint 模块:
plugins {
id 'java-library'
id 'org.jetbrains.kotlin.jvm'
}
java {
sourceCompatibility = JavaVersion.VERSION_1_7
targetCompatibility = JavaVersion.VERSION_1_7
}
dependencies {
compileOnly "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.6.10"
compileOnly "com.android.tools.lint:lint-api:25.3.0"
compileOnly "com.android.tools.lint:lint-checks:25.3.0"
}
jar {
manifest {
attributes("Lint-Registry": "com.example.lint_checks.LintRegistry")
}
}
应用模块build.gradle
文件:
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
}
android {
compileSdk 32
defaultConfig {
...
}
buildTypes {
...
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
kotlinOptions {
jvmTarget = '1.7'
}
buildFeatures {
viewBinding true
}
}
dependencies {
lintChecks project(path: ":lint-checks")
...
}
settings.gradle
pluginManagement {
repositories {
gradlePluginPortal()
google()
mavenCentral()
}
}
dependencyResolutionManagement {
repositories {
google()
mavenCentral()
}
}
rootProject.name = "Custom Linter"
include ':app'
include ':lint-checks'
InputTypeDetector.kt
(自定义的 Lint 类):
/* Entire class highlighted by IDE with error message:
Cannot access 'java.lang.Object' which is a supertype of 'com.example.lint_checks.InputTypeDetector'. Check your module classpath for missing or conflicting dependencies */
class InputTypeDetector: LayoutDetector() {
companion object {
@JvmStatic
internal val ISSUE_MISSING_INPUT_TYPE = Issue.create(
id = "MissingInputType",
briefDescription = "Specify inputType attribute to get proper keyboard shown by system.",
explanation = "You should specify an inputType for each EditText so that you can get the proper keyboard to be shown by system.",
category = Category.USABILITY,
priority = 8,
severity = Severity.ERROR,
implementation = Implementation(
InputTypeDetector::class.java,
Scope.ALL_RESOURCES_SCOPE
)
).addMoreInfo("https://developer.android.com/training/keyboard-input/style")
}
override fun getApplicableElements(): Collection<String>? {
return listOf(
SdkConstants.EDIT_TEXT,
"androidx.appcompat.widget.AppCompatEditText",
"android.support.v7.widget.AppCompatEditText"
)
}
override fun visitElement(context: XmlContext, element: CoroutineContext.Element) {
if (!element.hasAttribute(SdkConstants.ATTR_INPUT_TYPE)) { // Check if the element has the `android:inputType` attribute
context.report(
issue = ISSUE_MISSING_INPUT_TYPE, // The issue that we defined above
location = context.getLocation(element),
message = ISSUE_MISSING_INPUT_TYPE.getExplanation(TextFormat.TEXT)
)
}
}
}
更新:
我已验证lint-api
和lint-checks
jar文件位于我的项目的外部库目录中。当请求版本25.3.0时,Gradle已经解析并下载了这些依赖项。为什么我会收到关于访问java.lang.Object
和检查我的类路径的错误?
我一直在遵循这个教程
build.gradle
文件中将Gradle插件版本更改为1.3.71并进行同步,仍然会出现错误Plugin version (1.6.10) is not the same as library version (1.3.71)
。但是,在Linux机器上进行此更改后,所有错误消息都消失了,我可以毫无问题地运行./gradle lint
。我不确定问题是什么,但我认为涉及到Gradle插件未按照Mac版Android Studio指定的方式更改。 - John Harrington