Skip to content

Commit 1f405fb

Browse files
authored
Merge pull request #24 from tnorbye/master
Add sample for Studio 4.0
2 parents eb815a7 + 389322b commit 1f405fb

File tree

17 files changed

+561
-0
lines changed

17 files changed

+561
-0
lines changed

android-studio-4/README.md

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Sample Lint Checks
2+
3+
This project shows how Android Studio 4 handles packaging of lint rules.
4+
5+
## Lint Check Jar Library
6+
7+
First, there's the lint check implementation itself. That's done in the
8+
"checks" project, which just applies the Gradle "java" plugin, and
9+
that project produces a jar. Note that the dependencies for the lint
10+
check project (other than its testing dependencies) must all be "compileOnly":
11+
12+
dependencies {
13+
compileOnly "com.android.tools.lint:lint-api:$lintVersion"
14+
compileOnly "com.android.tools.lint:lint-checks:$lintVersion"
15+
...
16+
17+
## Lint Check AAR Library
18+
19+
Next, there's a separate Android library project, called "library". This
20+
library doesn't have any code on its own (though it could). However,
21+
in its build.gradle, it specifies this:
22+
23+
dependencies {
24+
lintPublish project(':checks')
25+
}
26+
27+
This tells the Gradle plugin to take the output from the "checks" project
28+
and package that as a "lint.jar" payload inside this library's AAR file.
29+
When that's done, any other projects that depends on this library will
30+
automatically be using the lint checks.
31+
32+
## App Modules
33+
34+
Note that you don't have to go through the extra "library indirection"
35+
if you have a lint check that you only want to apply to one or more
36+
app modules. You can simply include the `lintChecks` dependency as shown
37+
above there as well, and then lint will include these rules when analyzing
38+
the project.
39+
40+
## Lint Version
41+
42+
The lint version of the libraries (specified in this project as the
43+
`lintVersion` variable in build.gradle) should be the same version
44+
that is used by the Gradle plugin.
45+
46+
If the Gradle plugin version is *X*.*Y*.*Z*, then the Lint library
47+
version is *X+23*.*Y*.*Z*.

android-studio-4/build.gradle

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
buildscript {
2+
ext {
3+
gradlePluginVersion = '4.0.0-alpha08'
4+
lintVersion = '27.0.0-alpha08'
5+
kotlinVersion = '1.3.61'
6+
}
7+
8+
repositories {
9+
google()
10+
jcenter()
11+
}
12+
dependencies {
13+
classpath "com.android.tools.build:gradle:$gradlePluginVersion"
14+
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
15+
}
16+
}
17+
18+
allprojects {
19+
repositories {
20+
google()
21+
jcenter()
22+
}
23+
}
24+
25+
task clean(type: Delete) {
26+
delete rootProject.buildDir
27+
}

android-studio-4/checks/.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/build
2+
lint-report.html
3+
lint-results.txt

android-studio-4/checks/build.gradle

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
apply plugin: 'java-library'
2+
apply plugin: 'kotlin'
3+
apply plugin: 'com.android.lint'
4+
5+
lintOptions {
6+
htmlReport true
7+
htmlOutput file("lint-report.html")
8+
textReport true
9+
absolutePaths false
10+
ignoreTestSources true
11+
}
12+
13+
dependencies {
14+
// For a description of the below dependencies, see the main project README
15+
compileOnly "com.android.tools.lint:lint-api:$lintVersion"
16+
compileOnly "com.android.tools.lint:lint-checks:$lintVersion"
17+
compileOnly "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion"
18+
testImplementation "junit:junit:4.13"
19+
testImplementation "com.android.tools.lint:lint:$lintVersion"
20+
testImplementation "com.android.tools.lint:lint-tests:$lintVersion"
21+
testImplementation "com.android.tools:testutils:$lintVersion"
22+
}
23+
24+
sourceCompatibility = "1.8"
25+
targetCompatibility = "1.8"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/*
2+
* Copyright (C) 2020 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.example.lint.checks
17+
18+
import com.android.tools.lint.client.api.UElementHandler
19+
import com.android.tools.lint.detector.api.*
20+
import com.android.tools.lint.detector.api.Detector.UastScanner
21+
import org.jetbrains.uast.UElement
22+
import org.jetbrains.uast.ULiteralExpression
23+
import org.jetbrains.uast.evaluateString
24+
25+
/**
26+
* Sample detector showing how to analyze Kotlin/Java code.
27+
* This example flags all string literals in the code that contain
28+
* the word "lint".
29+
*/
30+
@Suppress("UnstableApiUsage")
31+
class SampleCodeDetector : Detector(), UastScanner {
32+
override fun getApplicableUastTypes(): List<Class<out UElement?>>? {
33+
return listOf(ULiteralExpression::class.java)
34+
}
35+
36+
override fun createUastHandler(context: JavaContext): UElementHandler? {
37+
// Note: Visiting UAST nodes is a pretty general purpose mechanism;
38+
// Lint has specialized support to do common things like "visit every class
39+
// that extends a given super class or implements a given interface", and
40+
// "visit every call site that calls a method by a given name" etc.
41+
// Take a careful look at UastScanner and the various existing lint check
42+
// implementations before doing things the "hard way".
43+
// Also be aware of context.getJavaEvaluator() which provides a lot of
44+
// utility functionality.
45+
return object : UElementHandler() {
46+
override fun visitLiteralExpression(node: ULiteralExpression) {
47+
val string = node.evaluateString() ?: return
48+
if (string.contains("lint") && string.matches(Regex(".*\\blint\\b.*"))) {
49+
context.report(ISSUE, node, context.getLocation(node),
50+
"This code mentions `lint`: **Congratulations**")
51+
}
52+
}
53+
}
54+
}
55+
56+
companion object {
57+
/** Issue describing the problem and pointing to the detector implementation */
58+
@JvmField
59+
val ISSUE: Issue = Issue.create(
60+
// ID: used in @SuppressLint warnings etc
61+
id = "ShortUniqueId",
62+
// Title -- shown in the IDE's preference dialog, as category headers in the
63+
// Analysis results window, etc
64+
briefDescription = "Lint Mentions",
65+
// Full explanation of the issue; you can use some markdown markup such as
66+
// `monospace`, *italic*, and **bold**.
67+
explanation = """
68+
This check highlights string literals in code which mentions the word `lint`. \
69+
Blah blah blah.
70+
71+
Another paragraph here.
72+
""", // no need to .trimIndent(), lint does that automatically
73+
category = Category.CORRECTNESS,
74+
priority = 6,
75+
severity = Severity.WARNING,
76+
implementation = Implementation(
77+
SampleCodeDetector::class.java,
78+
Scope.JAVA_FILE_SCOPE))
79+
}
80+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* Copyright (C) 2017 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.example.lint.checks
17+
18+
import com.android.tools.lint.client.api.IssueRegistry
19+
import com.android.tools.lint.detector.api.CURRENT_API
20+
21+
/*
22+
* The list of issues that will be checked when running <code>lint</code>.
23+
*/
24+
@Suppress("UnstableApiUsage")
25+
class SampleIssueRegistry : IssueRegistry() {
26+
override val issues = listOf(SampleCodeDetector.ISSUE)
27+
28+
override val api: Int
29+
get() = CURRENT_API
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
com.example.lint.checks.SampleIssueRegistry
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Copyright (C) 2017 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package com.example.lint.checks
17+
18+
import com.android.tools.lint.checks.infrastructure.LintDetectorTest
19+
import com.android.tools.lint.detector.api.Detector
20+
import com.android.tools.lint.detector.api.Issue
21+
22+
@Suppress("UnstableApiUsage")
23+
class SampleCodeDetectorTest : LintDetectorTest() {
24+
fun testBasic() {
25+
lint().files(
26+
java("""
27+
package test.pkg;
28+
public class TestClass1 {
29+
// In a comment, mentioning "lint" has no effect
30+
private static String s1 = "Ignore non-word usages: linting";
31+
private static String s2 = "Let's say it: lint";
32+
}
33+
"""
34+
).indented())
35+
.run()
36+
.expect("""
37+
src/test/pkg/TestClass1.java:5: Warning: This code mentions lint: Congratulations [ShortUniqueId]
38+
private static String s2 = "Let's say it: lint";
39+
~~~~~~~~~~~~~~~~~~~~
40+
0 errors, 1 warnings
41+
"""
42+
)
43+
}
44+
45+
override fun getDetector(): Detector {
46+
return SampleCodeDetector()
47+
}
48+
49+
override fun getIssues(): List<Issue> {
50+
return listOf(SampleCodeDetector.ISSUE)
51+
}
52+
}

android-studio-4/gradle.properties

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Project-wide Gradle settings.
2+
3+
# IDE (e.g. Android Studio) users:
4+
# Gradle settings configured through the IDE *will override*
5+
# any settings specified in this file.
6+
7+
# For more details on how to configure your build environment visit
8+
# http://www.gradle.org/docs/current/userguide/build_environment.html
9+
10+
# Specifies the JVM arguments used for the daemon process.
11+
# The setting is particularly useful for tweaking memory settings.
12+
org.gradle.jvmargs=-Xmx1536m
13+
14+
# When configured, Gradle will run in incubating parallel mode.
15+
# This option should only be used with decoupled projects. More details, visit
16+
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
17+
# org.gradle.parallel=true
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#Fri Sep 01 06:52:38 PDT 2017
2+
distributionBase=GRADLE_USER_HOME
3+
distributionPath=wrapper/dists
4+
zipStoreBase=GRADLE_USER_HOME
5+
zipStorePath=wrapper/dists
6+
distributionUrl=https\://services.gradle.org/distributions/gradle-6.1-rc-1-all.zip

0 commit comments

Comments
 (0)