Skip to content

Commit 439605d

Browse files
authored
Merge pull request #10 from tnorbye/studio3-packaging
Add sample for Android Studio 3.x
2 parents 1355b0c + e01536a commit 439605d

27 files changed

+612
-22
lines changed

README.md

+5-21
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
Custom Lint Rules
2-
============
2+
=================
33

44
The [Android `lint` tool](http://developer.android.com/tools/help/lint.html) is a static code
55
analysis tool that checks your Android project source files for potential bugs and optimization
@@ -31,31 +31,15 @@ git clone https://github.com/googlesamples/android-custom-lint-rules.git
3131
cd android-custom-lint-rules
3232
```
3333

34-
##### Build the validator
34+
##### Build the code
3535

36-
`./gradlew build`
37-
38-
##### Copy to the lint directory
39-
40-
`cp ./build/libs/android-custom-lint-rules.jar ~/.android/lint/`
41-
42-
##### Verify whether the issues are registered with lint
43-
44-
`lint --show MainActivityDetector`
45-
46-
##### Run lint
47-
48-
`./gradlew lint`
49-
50-
> Note: If you can't run `lint` directly, you may want to include android tools `PATH` in your
51-
`~/.bash_profile`.
52-
> (i.e. `PATH=$PATH:~/Library/Android/sdk/tools`)
53-
>
54-
> Then run `source ~/.bash_profile`.
36+
For Android Studio 3.x and above, use the sample in `android-studio-3`.
37+
If you are targeting Android Studio 2.x and older, use the sample in `android-studio-2`.
5538

5639
Support
5740
-------
5841

42+
- The "lint-dev" Google group: https://groups.google.com/forum/#!forum/lint-dev
5943
- Google+ Community: https://plus.google.com/communities/105153134372062985968
6044
- Stack Overflow: http://stackoverflow.com/questions/tagged/android
6145

android-studio-2/README.md

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
See README.md in the parent directory for general information.
2+
3+
Getting Started
4+
---------------
5+
6+
##### Fetch code
7+
8+
```
9+
git clone https://github.com/googlesamples/android-custom-lint-rules.git
10+
cd android-custom-lint-rules
11+
```
12+
13+
##### Build the validator
14+
15+
`./gradlew build`
16+
17+
##### Copy to the lint directory
18+
19+
`cp ./build/libs/android-custom-lint-rules.jar ~/.android/lint/`
20+
21+
##### Verify whether the issues are registered with lint
22+
23+
`lint --show MainActivityDetector`
24+
25+
##### Run lint
26+
27+
`./gradlew lint`
28+
29+
> Note: If you can't run `lint` directly, you may want to include android tools `PATH` in your
30+
`~/.bash_profile`.
31+
> (i.e. `PATH=$PATH:~/Library/Android/sdk/tools`)
32+
>
33+
> Then run `source ~/.bash_profile`.

build.gradle renamed to android-studio-2/build.gradle

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ dependencies {
3636

3737
jar {
3838
manifest {
39-
attributes("Lint-Registry-v2": "com.example.google.lint.MyIssueRegistry")
39+
attributes("Lint-Registry": "com.example.google.lint.MyIssueRegistry")
4040
}
4141
}
4242

File renamed without changes.
File renamed without changes.

android-studio-3/README.md

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

android-studio-3/build.gradle

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Top-level build file where you can add configuration options common to all sub-projects/modules.
2+
3+
buildscript {
4+
ext {
5+
gradlePluginVersion = '3.0.0-beta5'
6+
lintVersion = '26.0.0-beta5'
7+
}
8+
9+
repositories {
10+
google()
11+
jcenter()
12+
}
13+
dependencies {
14+
classpath "com.android.tools.build:gradle:$gradlePluginVersion"
15+
16+
// NOTE: Do not place your application dependencies here; they belong
17+
// in the individual module build.gradle files
18+
}
19+
}
20+
21+
allprojects {
22+
repositories {
23+
google()
24+
jcenter()
25+
}
26+
}
27+
28+
task clean(type: Delete) {
29+
delete rootProject.buildDir
30+
}

android-studio-3/checks/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/build

android-studio-3/checks/build.gradle

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
apply plugin: 'java-library'
2+
3+
dependencies {
4+
compileOnly "com.android.tools.lint:lint-api:$lintVersion"
5+
compileOnly "com.android.tools.lint:lint-checks:$lintVersion"
6+
testCompile "junit:junit:4.12"
7+
testCompile "com.android.tools.lint:lint:$lintVersion"
8+
testCompile "com.android.tools.lint:lint-tests:$lintVersion"
9+
testCompile "com.android.tools:testutils:$lintVersion"
10+
}
11+
12+
sourceCompatibility = "1.8"
13+
targetCompatibility = "1.8"
14+
15+
jar {
16+
manifest {
17+
// Only use the "-v2" key here if your checks have been updated to the
18+
// new 3.0 APIs (including UAST)
19+
attributes("Lint-Registry-v2": "com.example.lint.checks.SampleIssueRegistry")
20+
}
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
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.UElementHandler;
19+
import com.android.tools.lint.detector.api.Category;
20+
import com.android.tools.lint.detector.api.Detector;
21+
import com.android.tools.lint.detector.api.Detector.UastScanner;
22+
import com.android.tools.lint.detector.api.Implementation;
23+
import com.android.tools.lint.detector.api.Issue;
24+
import com.android.tools.lint.detector.api.JavaContext;
25+
import com.android.tools.lint.detector.api.Scope;
26+
import com.android.tools.lint.detector.api.Severity;
27+
28+
import org.jetbrains.uast.UElement;
29+
import org.jetbrains.uast.ULiteralExpression;
30+
import org.jetbrains.uast.UastLiteralUtils;
31+
32+
import java.util.Collections;
33+
import java.util.List;
34+
35+
/**
36+
* Sample detector showing how to analyze Kotlin/Java code.
37+
* This example flags all string literals in the code that contain
38+
* the word "lint".
39+
*/
40+
public class SampleCodeDetector extends Detector implements UastScanner {
41+
/** Issue describing the problem and pointing to the detector implementation */
42+
public static final Issue ISSUE = Issue.create(
43+
// ID: used in @SuppressLint warnings etc
44+
"ShortUniqueId",
45+
46+
// Title -- shown in the IDE's preference dialog, as category headers in the
47+
// Analysis results window, etc
48+
"Lint Mentions",
49+
50+
// Full explanation of the issue; you can use some markdown markup such as
51+
// `monospace`, *italic*, and **bold**.
52+
"This check highlights string literals in code which mentions " +
53+
"the word `lint`. Blah blah blah.\n" +
54+
"\n" +
55+
"Another paragraph here.\n",
56+
Category.CORRECTNESS,
57+
6,
58+
Severity.WARNING,
59+
new Implementation(
60+
SampleCodeDetector.class,
61+
Scope.JAVA_FILE_SCOPE));
62+
63+
@Override
64+
public List<Class<? extends UElement>> getApplicableUastTypes() {
65+
return Collections.singletonList(ULiteralExpression.class);
66+
}
67+
68+
@Override
69+
public UElementHandler createUastHandler(JavaContext context) {
70+
// Not: Visiting UAST nodes is a pretty general purpose mechanism;
71+
// Lint has specialized support to do common things like "visit every class
72+
// that extends a given super class or implements a given interface", and
73+
// "visit every call site that calls a method by a given name" etc.
74+
// Take a careful look at UastScanner and the various existing lint check
75+
// implementations before doing things the "hard way".
76+
// Also be aware of context.getJavaEvaluator() which provides a lot of
77+
// utility functionality.
78+
return new UElementHandler() {
79+
@Override
80+
public void visitLiteralExpression(ULiteralExpression expression) {
81+
String string = UastLiteralUtils.getValueIfStringLiteral(expression);
82+
if (string == null) {
83+
return;
84+
}
85+
86+
if (string.contains("lint") && string.matches(".*\\blint\\b.*")) {
87+
context.report(ISSUE, expression, context.getLocation(expression),
88+
"This code mentions `lint`: **Congratulations**");
89+
}
90+
}
91+
};
92+
}
93+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
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.Issue;
20+
21+
import java.util.Collections;
22+
import java.util.List;
23+
24+
/*
25+
* The list of issues that will be checked when running <code>lint</code>.
26+
*/
27+
public class SampleIssueRegistry extends IssueRegistry {
28+
@Override
29+
public List<Issue> getIssues() {
30+
return Collections.singletonList(SampleCodeDetector.ISSUE);
31+
}
32+
}
33+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
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+
import java.util.Collections;
23+
import java.util.List;
24+
25+
public class SampleCodeDetectorTest extends LintDetectorTest {
26+
public void testBasic() {
27+
lint().files(
28+
java("" +
29+
"package test.pkg;\n" +
30+
"public class TestClass1 {\n" +
31+
" // In a comment, mentioning \"lint\" has no effect\n" +
32+
" private static String s1 = \"Ignore non-word usages: linting\";\n" +
33+
" private static String s2 = \"Let's say it: lint\";\n" +
34+
"}"))
35+
.run()
36+
.expect("src/test/pkg/TestClass1.java:5: Warning: This code mentions lint: Congratulations [ShortUniqueId]\n" +
37+
" private static String s2 = \"Let's say it: lint\";\n" +
38+
" ~~~~~~~~~~~~~~~~~~~~\n" +
39+
"0 errors, 1 warnings\n");
40+
}
41+
42+
@Override
43+
protected Detector getDetector() {
44+
return new SampleCodeDetector();
45+
}
46+
47+
@Override
48+
protected List<Issue> getIssues() {
49+
return Collections.singletonList(SampleCodeDetector.ISSUE);
50+
}
51+
}

android-studio-3/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-4.1-all.zip

0 commit comments

Comments
 (0)