├── sample ├── .gitignore ├── build.gradle └── src │ ├── test │ ├── resources │ │ └── AndroidManifest.xml │ └── java │ │ └── de │ │ └── ad │ │ └── android │ │ └── tools │ │ └── lint │ │ └── HelloWorldDetectorTest.java │ └── main │ └── java │ └── de │ └── ad │ └── android │ └── tools │ └── lint │ └── HelloWorldDetector.java ├── assertj ├── .gitignore ├── build.gradle └── src │ ├── test │ └── java │ │ └── com │ │ └── ad │ │ └── android │ │ └── tools │ │ └── lint │ │ └── assertj │ │ └── WarningAssertTest.java │ └── main │ └── java │ └── com │ └── ad │ └── android │ └── tools │ └── lint │ └── assertj │ └── WarningAssert.java ├── hamcrest ├── .gitignore ├── build.gradle └── src │ ├── test │ └── java │ │ └── com │ │ └── ad │ │ └── android │ │ └── tools │ │ └── lint │ │ └── hamcrest │ │ └── WarningMatcherTest.java │ └── main │ └── java │ └── com │ └── ad │ └── android │ └── tools │ └── lint │ └── hamcrest │ └── WarningMatcher.java ├── library ├── .gitignore ├── src │ ├── main │ │ └── java │ │ │ └── com │ │ │ └── ad │ │ │ └── android │ │ │ └── tools │ │ │ └── lint │ │ │ ├── Wrapper.java │ │ │ ├── TestFile.java │ │ │ ├── LintDetectorTestWrapper.java │ │ │ └── Lint.java │ └── test │ │ └── java │ │ └── com │ │ └── ad │ │ └── android │ │ └── tools │ │ └── lint │ │ ├── LintDetectorTestWrapperTest.java │ │ ├── LintRuleTest.java │ │ ├── LintTest.java │ │ └── Helper.java └── build.gradle ├── .gitignore ├── settings.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .travis.yml ├── LICENSE ├── bintray.gradle ├── gradlew.bat ├── README.md └── gradlew /sample/.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | *.iml -------------------------------------------------------------------------------- /assertj/.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | *.iml -------------------------------------------------------------------------------- /hamcrest/.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | *.iml -------------------------------------------------------------------------------- /library/.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | *.iml -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle/ 2 | .idea/ 3 | build/ 4 | gradle.properties -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include 'library' 2 | include 'assertj' 3 | include 'hamcrest' 4 | include 'sample' 5 | 6 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a11n/lint-junit-rule/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Sep 30 11:08:34 CEST 2015 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-2.4-all.zip 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | 3 | jdk: 4 | - oraclejdk8 5 | 6 | after_success: 7 | - gradle jacocoTestReport coveralls 8 | 9 | branches: 10 | except: 11 | - gh-pages 12 | 13 | notifications: 14 | email: false 15 | 16 | script: ./gradlew clean test 17 | 18 | cache: 19 | directories: 20 | - $HOME/.gradle 21 | -------------------------------------------------------------------------------- /hamcrest/build.gradle: -------------------------------------------------------------------------------- 1 | version '0.3.0' 2 | 3 | apply plugin: 'java' 4 | apply from: '../bintray.gradle' 5 | 6 | repositories { 7 | mavenCentral() 8 | } 9 | 10 | dependencies { 11 | compile 'com.android.tools.lint:lint-tests:24.3.1' 12 | compile group: 'org.hamcrest', name: 'hamcrest-core', version: '1.3' 13 | testCompile group: 'junit', name: 'junit', version: '4.11' 14 | } 15 | 16 | publishing.publications.mavenJava(MavenPublication) { 17 | groupId 'de.ad' 18 | artifactId 'lint-hamcrest' 19 | } 20 | 21 | bintray.pkg { 22 | name = 'de.ad:lint-hamcrest' 23 | desc = 'Hamcrest matchers for Android Lint Warnings.' 24 | labels += 'hamcrest' 25 | } -------------------------------------------------------------------------------- /sample/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'java' 2 | 3 | version = '1.0.0' 4 | 5 | repositories { 6 | jcenter() 7 | maven { 8 | url 'https://dl.bintray.com/android/android-tools' 9 | } 10 | maven { 11 | url 'https://dl.bintray.com/a11n/maven/' 12 | } 13 | } 14 | 15 | dependencies { 16 | compile 'com.android.tools.lint:lint-api:24.3.1' 17 | testCompile 'junit:junit:4.12' 18 | 19 | testCompile 'de.ad:lint-junit-rule:0.3.0' 20 | 21 | testCompile 'org.assertj:assertj-core:2.2.0' 22 | testCompile 'de.ad:lint-assertj:0.3.0' 23 | 24 | testCompile group: 'org.hamcrest', name: 'hamcrest-core', version: '1.3' 25 | testCompile 'de.ad:lint-hamcrest:0.3.0' 26 | } -------------------------------------------------------------------------------- /assertj/build.gradle: -------------------------------------------------------------------------------- 1 | version '0.3.0' 2 | 3 | apply plugin: 'java' 4 | apply from: '../bintray.gradle' 5 | 6 | repositories { 7 | mavenCentral() 8 | } 9 | 10 | dependencies { 11 | compile 'org.assertj:assertj-core:2.2.0' 12 | compile 'com.android.tools.lint:lint-tests:24.3.1' 13 | testCompile group: 'junit', name: 'junit', version: '4.11' 14 | testCompile "org.mockito:mockito-core:1.9.5" 15 | } 16 | 17 | publishing.publications.mavenJava(MavenPublication) { 18 | groupId 'de.ad' 19 | artifactId 'lint-assertj' 20 | } 21 | 22 | bintray.pkg { 23 | name = 'de.ad:lint-assertj' 24 | desc = 'AssertJ assertions for Android Lint Warnings.' 25 | labels += 'AssertJ' 26 | } 27 | -------------------------------------------------------------------------------- /library/src/main/java/com/ad/android/tools/lint/Wrapper.java: -------------------------------------------------------------------------------- 1 | package com.ad.android.tools.lint; 2 | 3 | import com.android.tools.lint.Warning; 4 | import com.android.tools.lint.checks.infrastructure.LintDetectorTest; 5 | import com.android.tools.lint.detector.api.Detector; 6 | import com.android.tools.lint.detector.api.Issue; 7 | import java.io.File; 8 | import java.io.InputStream; 9 | import java.util.List; 10 | import org.jetbrains.annotations.NotNull; 11 | import org.junit.Ignore; 12 | 13 | interface Wrapper { 14 | 15 | void analyze(Detector detector, List issues, String... files) throws Exception; 16 | 17 | void analyze(Detector detector, List issues, TestFile... files) 18 | throws Exception; 19 | 20 | List getWarnings(); 21 | } 22 | -------------------------------------------------------------------------------- /sample/src/test/resources/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /library/src/main/java/com/ad/android/tools/lint/TestFile.java: -------------------------------------------------------------------------------- 1 | package com.ad.android.tools.lint; 2 | 3 | import com.android.annotations.NonNull; 4 | import org.intellij.lang.annotations.Language; 5 | 6 | class TestFile { 7 | private final String to; 8 | private final String source; 9 | 10 | @NonNull 11 | public static TestFile java(@NonNull String to, @NonNull @Language("JAVA") String source) { 12 | return new TestFile(to, source); 13 | } 14 | 15 | @NonNull 16 | public static TestFile xml(@NonNull String to, @NonNull @Language("XML") String source) { 17 | return new TestFile(to, source); 18 | } 19 | 20 | private TestFile(String to, String source) { 21 | this.to = to; 22 | this.source = source; 23 | } 24 | 25 | public String getTo() { 26 | return to; 27 | } 28 | 29 | public String getSource() { 30 | return source; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /assertj/src/test/java/com/ad/android/tools/lint/assertj/WarningAssertTest.java: -------------------------------------------------------------------------------- 1 | package com.ad.android.tools.lint.assertj; 2 | 3 | import com.android.tools.lint.Warning; 4 | import java.io.File; 5 | import java.util.Arrays; 6 | import java.util.List; 7 | import org.junit.Test; 8 | 9 | public class WarningAssertTest { 10 | @Test 11 | public void testHasWarnings() throws Exception { 12 | Warning firstWarning = new Warning(null, "Message 1", null, null); 13 | firstWarning.file = new File("File1.java"); 14 | firstWarning.line = 8; 15 | 16 | Warning secondWarning = new Warning(null, "Message 2", null, null); 17 | secondWarning.file = new File("File2.xml"); 18 | secondWarning.line = 14; 19 | 20 | List lintResult = Arrays.asList(firstWarning, secondWarning); 21 | 22 | WarningAssert.assertThat(lintResult) 23 | .hasWarnings(2) 24 | .in("File1.java", "File2.xml") 25 | .atLine(8, 14) 26 | .withMessage("Message 1", "Message 2"); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /library/build.gradle: -------------------------------------------------------------------------------- 1 | version = '0.3.0' 2 | 3 | apply plugin: 'java' 4 | apply plugin: 'jacoco' 5 | apply plugin: 'com.github.kt3k.coveralls' 6 | apply from: '../bintray.gradle' 7 | 8 | repositories { 9 | jcenter() 10 | maven { 11 | url 'https://dl.bintray.com/android/android-tools' 12 | } 13 | } 14 | 15 | dependencies { 16 | compile 'com.android.tools.lint:lint-tests:24.3.1' 17 | compile group: 'junit', name: 'junit', version: '4.11' 18 | testCompile "org.mockito:mockito-core:1.9.5" 19 | testCompile 'org.assertj:assertj-core:3.1.0' 20 | } 21 | 22 | jacocoTestReport { 23 | reports { 24 | xml.enabled = true // coveralls plugin depends on xml format report 25 | html.enabled = true 26 | } 27 | } 28 | 29 | jar { 30 | from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } } 31 | } 32 | 33 | publishing.publications.mavenJava(MavenPublication) { 34 | groupId 'de.ad' 35 | artifactId 'lint-junit-rule' 36 | } 37 | 38 | bintray.pkg { 39 | name = 'de.ad:lint-junit-rule' 40 | desc = 'A JUnit rule which allows unit testing of custom Lint rules.' 41 | } 42 | -------------------------------------------------------------------------------- /library/src/test/java/com/ad/android/tools/lint/LintDetectorTestWrapperTest.java: -------------------------------------------------------------------------------- 1 | package com.ad.android.tools.lint; 2 | 3 | import org.junit.Test; 4 | 5 | import static com.ad.android.tools.lint.TestFile.xml; 6 | 7 | public class LintDetectorTestWrapperTest { 8 | @Test(expected = IllegalStateException.class) 9 | public void shouldThrowIllegalState() throws Exception { 10 | LintDetectorTestWrapper wrapper = new LintDetectorTestWrapper(); 11 | 12 | wrapper.analyze(null, null, xml("file", "")); 13 | } 14 | 15 | @Test 16 | public void shouldAnalyzeFile() throws Exception { 17 | LintDetectorTestWrapper wrapper = new LintDetectorTestWrapper(); 18 | wrapper.setTestLintClient(Helper.dummyClient()); 19 | 20 | Helper.createTestFile(this, "file"); 21 | 22 | wrapper.analyze(null, null, "file"); 23 | } 24 | 25 | @Test 26 | public void shouldAnalyzeProject() throws Exception { 27 | LintDetectorTestWrapper wrapper = new LintDetectorTestWrapper(); 28 | wrapper.setTestLintClient(Helper.dummyClient()); 29 | 30 | wrapper.analyze(null, null, xml("file", "")); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 André Diermann 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /bintray.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'maven-publish' 2 | apply plugin: 'com.jfrog.bintray' 3 | 4 | task sourcesJar(type: Jar, dependsOn: classes) { 5 | classifier = 'sources' 6 | from sourceSets.main.allSource 7 | } 8 | 9 | task javadocJar(type: Jar, dependsOn: javadoc) { 10 | classifier = 'javadoc' 11 | from javadoc.destinationDir 12 | } 13 | 14 | artifacts { 15 | archives sourcesJar, javadocJar 16 | } 17 | 18 | publishing { 19 | publications { 20 | mavenJava(MavenPublication) { 21 | from components.java 22 | 23 | artifact sourcesJar 24 | artifact javadocJar 25 | } 26 | } 27 | } 28 | 29 | bintray { 30 | user = project.hasProperty('bintray_user') ? bintray_user : '' 31 | key = project.hasProperty('bintray_key') ? bintray_key : '' 32 | publications = ['mavenJava'] 33 | dryRun = false 34 | publish = false 35 | pkg { 36 | repo = 'maven' 37 | websiteUrl = 'https://github.com/a11n/lint-junit-rule' 38 | issueTrackerUrl = 'https://github.com/a11n/lint-junit-rule/issues' 39 | vcsUrl = 'https://github.com/a11n/lint-junit-rule.git' 40 | licenses = ['MIT'] 41 | labels = ['Android', 'lint', 'JUnit'] 42 | publicDownloadNumbers = false 43 | version { 44 | name = project.version 45 | desc = '' 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /assertj/src/main/java/com/ad/android/tools/lint/assertj/WarningAssert.java: -------------------------------------------------------------------------------- 1 | package com.ad.android.tools.lint.assertj; 2 | 3 | import com.android.tools.lint.Warning; 4 | import java.util.List; 5 | import org.assertj.core.api.AbstractListAssert; 6 | 7 | public class WarningAssert extends AbstractListAssert, Warning> { 8 | private WarningAssert(List actual) { 9 | super(actual, WarningAssert.class); 10 | } 11 | 12 | public static WarningAssert assertThat(List actual) { 13 | return new WarningAssert(actual); 14 | } 15 | 16 | public WarningAssert hasWarnings(int count) { 17 | if (actual.size() != count) { 18 | failWithMessage("Expected warning's size to be <%d> but was <%d>", count, actual.size()); 19 | } 20 | 21 | return this; 22 | } 23 | 24 | public WarningAssert in(String... filenames) { 25 | assertThat(actual).extracting("file.name").containsExactly(filenames); 26 | 27 | return this; 28 | } 29 | 30 | public WarningAssert atLine(Integer... lines) { 31 | assertThat(actual).extracting("line").containsExactly(lines); 32 | 33 | return this; 34 | } 35 | 36 | public WarningAssert withMessage(String... messages) { 37 | assertThat(actual).extracting("message").containsExactly(messages); 38 | 39 | return this; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /hamcrest/src/test/java/com/ad/android/tools/lint/hamcrest/WarningMatcherTest.java: -------------------------------------------------------------------------------- 1 | package com.ad.android.tools.lint.hamcrest; 2 | 3 | import com.android.tools.lint.Warning; 4 | import java.io.File; 5 | import java.util.Arrays; 6 | import java.util.List; 7 | import org.junit.Test; 8 | 9 | import static com.ad.android.tools.lint.hamcrest.WarningMatcher.atLine; 10 | import static com.ad.android.tools.lint.hamcrest.WarningMatcher.hasWarnings; 11 | import static com.ad.android.tools.lint.hamcrest.WarningMatcher.in; 12 | import static com.ad.android.tools.lint.hamcrest.WarningMatcher.withMessage; 13 | import static org.hamcrest.MatcherAssert.assertThat; 14 | 15 | public class WarningMatcherTest { 16 | @Test 17 | public void test() throws Exception { 18 | Warning firstWarning = new Warning(null, "Message 1", null, null); 19 | firstWarning.file = new File("File1.java"); 20 | firstWarning.line = 8; 21 | 22 | Warning secondWarning = new Warning(null, "Message 2", null, null); 23 | secondWarning.file = new File("File2.xml"); 24 | secondWarning.line = 14; 25 | 26 | List lintResult = Arrays.asList(firstWarning, secondWarning); 27 | 28 | assertThat(lintResult, 29 | hasWarnings(in("File1.java", "File2.xml"), atLine(8, 14), 30 | withMessage("Message 1", "Message 2"))); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /sample/src/test/java/de/ad/android/tools/lint/HelloWorldDetectorTest.java: -------------------------------------------------------------------------------- 1 | package de.ad.android.tools.lint; 2 | 3 | import com.ad.android.tools.lint.Lint; 4 | import com.ad.android.tools.lint.assertj.WarningAssert; 5 | import com.android.tools.lint.Warning; 6 | import java.util.List; 7 | import org.hamcrest.MatcherAssert; 8 | import org.junit.Rule; 9 | import org.junit.Test; 10 | 11 | import static com.ad.android.tools.lint.hamcrest.WarningMatcher.atLine; 12 | import static com.ad.android.tools.lint.hamcrest.WarningMatcher.hasWarnings; 13 | import static com.ad.android.tools.lint.hamcrest.WarningMatcher.in; 14 | import static com.ad.android.tools.lint.hamcrest.WarningMatcher.withMessage; 15 | 16 | public class HelloWorldDetectorTest { 17 | @Rule public Lint lint = new Lint(new HelloWorldDetector(), HelloWorldDetector.ISSUE); 18 | 19 | @Test 20 | public void shouldDetectWarning() throws Exception { 21 | List lintResult = lint.files("AndroidManifest.xml"); 22 | 23 | //AssertJ 24 | WarningAssert.assertThat(lintResult) 25 | .hasWarnings(1) 26 | .in("AndroidManifest.xml") 27 | .atLine(7) 28 | .withMessage("Unexpected title \"@string/app_name\". Should be \"Hello world.\"."); 29 | 30 | //Hamcrest 31 | MatcherAssert.assertThat(lintResult, 32 | hasWarnings( 33 | in("AndroidManifest.xml"), 34 | atLine(7), 35 | withMessage("Unexpected title \"@string/app_name\". Should be \"Hello world.\"."))); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /library/src/test/java/com/ad/android/tools/lint/LintRuleTest.java: -------------------------------------------------------------------------------- 1 | package com.ad.android.tools.lint; 2 | 3 | import com.android.tools.lint.Warning; 4 | import java.util.List; 5 | import org.junit.Before; 6 | import org.junit.Rule; 7 | import org.junit.Test; 8 | 9 | import static com.ad.android.tools.lint.TestFile.java; 10 | import static com.ad.android.tools.lint.TestFile.xml; 11 | import static org.assertj.core.api.Assertions.assertThat; 12 | import static org.assertj.core.api.StrictAssertions.tuple; 13 | 14 | public class LintRuleTest { 15 | @Rule public Lint lint = new Lint(Helper.dummyDetector(), Helper.dummyIssue()); 16 | 17 | @Before 18 | public void setUp() throws Exception { 19 | Lint.wrapper = Helper.dummyWrapper(); 20 | } 21 | 22 | @Test 23 | public void shouldLintFilesAndReturnWarnings() throws Exception { 24 | List warnings = lint.files("file1", "file2"); 25 | 26 | assertThat(warnings).extracting("file.name", "line", "message") 27 | .containsExactly( 28 | tuple("file1", 1, "Warning 1"), 29 | tuple("file2", 2, "Warning 2")); 30 | } 31 | 32 | @Test 33 | public void shouldLintProjectAndReturnWarnings() throws Exception { 34 | List warnings = lint.project( 35 | xml("file1", ""), 36 | java("file2", "public class Class{}")); 37 | 38 | assertThat(warnings).extracting("file.name", "line", "message") 39 | .containsExactly( 40 | tuple("file1", 1, "Warning 1"), 41 | tuple("file2", 2, "Warning 2")); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /library/src/test/java/com/ad/android/tools/lint/LintTest.java: -------------------------------------------------------------------------------- 1 | package com.ad.android.tools.lint; 2 | 3 | import com.android.tools.lint.Warning; 4 | import com.android.tools.lint.detector.api.Detector; 5 | import com.android.tools.lint.detector.api.Issue; 6 | import java.util.List; 7 | import org.junit.Before; 8 | import org.junit.Test; 9 | 10 | import static com.ad.android.tools.lint.TestFile.java; 11 | import static com.ad.android.tools.lint.TestFile.xml; 12 | import static org.assertj.core.api.Assertions.assertThat; 13 | 14 | public class LintTest { 15 | @Before 16 | public void setUp() throws Exception { 17 | Lint.wrapper = Helper.dummyWrapper(); 18 | } 19 | 20 | @Test 21 | public void shouldAnalyzeExternalResourceAndReturnWarnings() throws Exception { 22 | String[] files = { "file" }; 23 | Detector detector = Helper.dummyDetector(); 24 | Issue[] issues = { Helper.dummyIssue() }; 25 | Lint lint = new Lint(detector, issues); 26 | 27 | List warnings = lint.files(files); 28 | 29 | assertThat(warnings).isEqualTo(Helper.dummyWarnings()); 30 | } 31 | 32 | @Test 33 | public void shouldAnalyzeInlineResourceAndReturnWarnings() throws Exception { 34 | TestFile[] files = { 35 | xml("file1", ""), 36 | java("file2", "public class Class{}") }; 37 | Detector detector = Helper.dummyDetector(); 38 | Issue[] issues = { Helper.dummyIssue() }; 39 | Lint lint = new Lint(detector, issues); 40 | 41 | List warnings = lint.project(files); 42 | 43 | assertThat(warnings).isEqualTo(Helper.dummyWarnings()); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /library/src/test/java/com/ad/android/tools/lint/Helper.java: -------------------------------------------------------------------------------- 1 | package com.ad.android.tools.lint; 2 | 3 | import com.android.tools.lint.Warning; 4 | import com.android.tools.lint.detector.api.Category; 5 | import com.android.tools.lint.detector.api.Detector; 6 | import com.android.tools.lint.detector.api.Implementation; 7 | import com.android.tools.lint.detector.api.Issue; 8 | import com.android.tools.lint.detector.api.Project; 9 | import com.android.tools.lint.detector.api.Severity; 10 | import java.io.File; 11 | import java.io.IOException; 12 | import java.net.URISyntaxException; 13 | import java.net.URL; 14 | import java.util.Arrays; 15 | import java.util.List; 16 | 17 | import static org.mockito.Mockito.mock; 18 | import static org.mockito.Mockito.when; 19 | 20 | class Helper { 21 | public static Detector dummyDetector() { 22 | return mock(Detector.class); 23 | } 24 | 25 | public static Issue dummyIssue() { 26 | return Issue.create("", " ", " ", Category.LINT, 0, Severity.IGNORE, 27 | mock(Implementation.class)); 28 | } 29 | 30 | public static Wrapper dummyWrapper() { 31 | Wrapper detectorTest = mock(Wrapper.class); 32 | 33 | when(detectorTest.getWarnings()).thenReturn(dummyWarnings()); 34 | 35 | return detectorTest; 36 | } 37 | 38 | public static List dummyWarnings() { 39 | Warning warning1 = MockWarning.with("file1", 1, "Warning 1"); 40 | Warning warning2 = MockWarning.with("file2", 2, "Warning 2"); 41 | 42 | return Arrays.asList(warning1, warning2); 43 | } 44 | 45 | public static LintDetectorTestWrapper.ExtendedTestLintClient dummyClient() { 46 | LintDetectorTestWrapper.ExtendedTestLintClient client = mock( 47 | LintDetectorTestWrapper.ExtendedTestLintClient.class); 48 | 49 | when(client.getWarnings()).thenReturn(dummyWarnings()); 50 | 51 | return client; 52 | } 53 | 54 | public static void createTestFile(Object instance, String file) 55 | throws URISyntaxException, IOException { 56 | URL url = instance.getClass().getClassLoader().getResource("."); 57 | File resourceFolder = new File(url.toURI()); 58 | File testFile = new File(resourceFolder, file); 59 | 60 | testFile.createNewFile(); 61 | } 62 | 63 | private static class MockWarning extends Warning { 64 | 65 | private MockWarning(Issue issue, String message, Severity severity, 66 | Project project) { 67 | super(issue, message, severity, project); 68 | } 69 | 70 | public static MockWarning with(String file, int line, String message) { 71 | MockWarning mockWarning = new MockWarning(dummyIssue(), message, Severity.IGNORE, null); 72 | 73 | mockWarning.file = new File(file); 74 | mockWarning.line = line; 75 | 76 | return mockWarning; 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /sample/src/main/java/de/ad/android/tools/lint/HelloWorldDetector.java: -------------------------------------------------------------------------------- 1 | package de.ad.android.tools.lint; 2 | 3 | import com.android.annotations.NonNull; 4 | import com.android.tools.lint.detector.api.Category; 5 | import com.android.tools.lint.detector.api.Context; 6 | import com.android.tools.lint.detector.api.Detector; 7 | import com.android.tools.lint.detector.api.Implementation; 8 | import com.android.tools.lint.detector.api.Issue; 9 | import com.android.tools.lint.detector.api.Scope; 10 | import com.android.tools.lint.detector.api.Severity; 11 | import com.android.tools.lint.detector.api.XmlContext; 12 | import java.io.File; 13 | import java.util.Arrays; 14 | import java.util.Collection; 15 | import org.w3c.dom.Attr; 16 | import org.w3c.dom.Element; 17 | 18 | import static com.android.SdkConstants.ANDROID_MANIFEST_XML; 19 | import static com.android.SdkConstants.ATTR_LABEL; 20 | import static com.android.SdkConstants.TAG_APPLICATION; 21 | 22 | /** 23 | * Check which determines if application title equals "Hello world" 24 | */ 25 | public class HelloWorldDetector extends Detector 26 | implements Detector.XmlScanner { 27 | 28 | public static final Issue ISSUE = Issue.create( 29 | "HelloWorld", //ID 30 | "Unexpected application title", //brief description 31 | "The application title should state 'Hello world'", //explanation 32 | Category.CORRECTNESS, //category 33 | 5, //priority 34 | Severity.INFORMATIONAL, //severity 35 | new Implementation( //implementation 36 | HelloWorldDetector.class, //detector 37 | Scope.MANIFEST_SCOPE //scope 38 | ) 39 | ); 40 | 41 | private static final String TITLE = "Hello world"; 42 | 43 | @Override 44 | public boolean appliesTo(@NonNull Context context, @NonNull File file) { 45 | return file.getName().equals(ANDROID_MANIFEST_XML); 46 | } 47 | 48 | @Override public Collection getApplicableAttributes() { 49 | return Arrays.asList(ATTR_LABEL); 50 | } 51 | 52 | @Override public void visitAttribute(@NonNull XmlContext context, 53 | @NonNull Attr attribute) { 54 | //only check 'label' attribute of -tag 55 | String tagName = attribute.getOwnerElement().getTagName(); 56 | if (!TAG_APPLICATION.equals(tagName)) { 57 | return; 58 | } 59 | 60 | String value = attribute.getValue(); 61 | 62 | if (!TITLE.equals(value)) { 63 | context.report(ISSUE, attribute, context.getLocation(attribute), 64 | String.format( 65 | "Unexpected title \"%1$s\". Should be \"Hello world.\".", value)); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /library/src/main/java/com/ad/android/tools/lint/LintDetectorTestWrapper.java: -------------------------------------------------------------------------------- 1 | package com.ad.android.tools.lint; 2 | 3 | import com.android.tools.lint.Warning; 4 | import com.android.tools.lint.checks.infrastructure.LintDetectorTest; 5 | import com.android.tools.lint.detector.api.Detector; 6 | import com.android.tools.lint.detector.api.Issue; 7 | import java.io.File; 8 | import java.io.InputStream; 9 | import java.util.List; 10 | import org.jetbrains.annotations.NotNull; 11 | import org.junit.Ignore; 12 | 13 | @Ignore 14 | final class LintDetectorTestWrapper extends LintDetectorTest implements Wrapper { 15 | private ExtendedTestLintClient testLintClient; 16 | 17 | private Detector detector; 18 | private List issues; 19 | 20 | private List warnings; 21 | 22 | public void setTestLintClient( 23 | ExtendedTestLintClient testLintClient) { 24 | this.testLintClient = testLintClient; 25 | } 26 | 27 | @Override public void analyze(Detector detector, List issues, String... files) 28 | throws Exception { 29 | this.detector = detector; 30 | this.issues = issues; 31 | 32 | lintFiles(files); 33 | } 34 | 35 | @Override public void analyze(Detector detector, List issues, 36 | com.ad.android.tools.lint.TestFile... files) 37 | throws Exception { 38 | this.detector = detector; 39 | this.issues = issues; 40 | 41 | TestFile[] testFiles = convert(files); 42 | 43 | lintProject(testFiles); 44 | } 45 | 46 | @NotNull private TestFile[] convert(com.ad.android.tools.lint.TestFile[] files) { 47 | TestFile[] testFiles = new TestFile[files.length]; 48 | for (int i = 0; i < testFiles.length; i++) { 49 | testFiles[i] = file().to(files[i].getTo()).withSource(files[i].getSource()); 50 | } 51 | return testFiles; 52 | } 53 | 54 | public List getWarnings() { 55 | return warnings; 56 | } 57 | 58 | @Override protected Detector getDetector() { 59 | return detector; 60 | } 61 | 62 | @Override protected List getIssues() { 63 | return issues; 64 | } 65 | 66 | @Override protected String checkLint(List files) throws Exception { 67 | if(testLintClient == null) 68 | throw new IllegalStateException("Please call setExtendedTestLintClient() first."); 69 | 70 | String result = checkLint(testLintClient, files); 71 | 72 | warnings = testLintClient.getWarnings(); 73 | 74 | return result; 75 | } 76 | 77 | //this needs to be overridden (see https://code.google.com/p/android/issues/detail?id=182195) 78 | @Override protected InputStream getTestResource(String relativePath, boolean expectExists) { 79 | String path = relativePath; //$NON-NLS-1$ 80 | InputStream stream = this.getClass().getClassLoader().getResourceAsStream(path); 81 | if (!expectExists && stream == null) { 82 | return null; 83 | } 84 | return stream; 85 | } 86 | 87 | class ExtendedTestLintClient extends TestLintClient { 88 | 89 | public List getWarnings() { 90 | return mWarnings; 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # lint-junit-rule [![Build Status](https://travis-ci.org/a11n/lint-junit-rule.svg)](https://travis-ci.org/a11n/lint-junit-rule) [![Coverage Status](https://coveralls.io/repos/a11n/lint-junit-rule/badge.svg)](https://coveralls.io/r/a11n/lint-junit-rule) [ ![Download](https://api.bintray.com/packages/a11n/maven/de.ad%3Alint-junit-rule/images/download.svg) ](https://bintray.com/a11n/maven/de.ad%3Alint-junit-rule/_latestVersion) 2 | 3 | A JUnit rule which allows unit testing of custom Lint rules. 4 | 5 | If you want to learn more about custom Lint rules please check [this reference guide](https://github.com/a11n/android-lint). If you want to write your own custom Lint rule you could use [this custom Lint rule template](https://github.com/a11n/CustomLintRules). If you are still looking for more details you are welcome to check [this workshop on custom Lint rules](https://github.com/a11n/lint-workshop-slides). 6 | 7 | ## Motivation 8 | Fortunately, with the release of the **lint-tests** library **version 24.3.0** at the end of July 2015 [1] there is now official test support available for custom Lint rules. Unfortunately there are still some drawbacks: 9 | 10 | 1. You have to use the **JUnit 3** approach of extending `LintDetectorTest`. 11 | 2. The assertion options are poor, all you get is one `String`. 12 | 3. There is an issue when loading your test resources [2]. 13 | 14 | Therefore the objective of this library is to take you one step further: 15 | 16 | 1. It provides **JUnit 4** support by wrapping the official test support into a dedicated JUnit rule. 17 | 2. Furthermore it exposes the *internal* Lint `Warnings` for you which allows powerful assertions. 18 | 3. Last but not least it fixes the aforementioned issue for you which gives you a convenient way to place your test resources in *test/res*. 19 | 20 | ## Usage 21 | Import the dependency in your `build.gradle`. It's available via JCenter: 22 | 23 | ```groovy 24 | dependencies{ 25 | ... 26 | testCompile 'de.ad:lint-junit-rule:0.3.0' 27 | 28 | //optional 29 | testCompile 'de.ad:lint-assertj:0.3.0' 30 | testCompile 'de.ad:lint-hamcrest:0.3.0' 31 | } 32 | ``` 33 | Apply the rule in your test class and specify the `Detector` as well as the `Issues` under test. Next provide the files to analyze. Finally do your assertions on the populated `Warnings`: 34 | 35 | ```java 36 | @Rule public Lint lint = new Lint(new MyCustomRule(), MyCustomRule.ISSUE); 37 | 38 | @Test 39 | public void test() throws Exception { 40 | List lintResult = lint.files("AndroidManifest.xml", "res/values/strings.xml"); 41 | 42 | //AssertJ 43 | assertThat(lintResult) 44 | .hasWarnings(2) 45 | .in("AndroidManifest.xml", "strings.xml") 46 | .atLine(8, 14) 47 | .withMessage("MyCustomRule warning message.", 48 | "MyCustomRule warning message."); 49 | 50 | //Hamcrest 51 | assertThat(lintResult, 52 | hasWarnings( 53 | in("AndroidManifest.xml", "strings.xml"), 54 | atLine(8, 14), 55 | withMessage("MyCustomRule warning message.", 56 | "MyCustomRule warning message."))); 57 | } 58 | ``` 59 | **Note:** Test resources are looked-up in `test/res`. 60 | 61 | ## References 62 | 1. https://bintray.com/android/android-tools/com.android.tools.lint.lint-tests/24.3.0/view 63 | 2. https://code.google.com/p/android/issues/detail?id=182195 64 | -------------------------------------------------------------------------------- /library/src/main/java/com/ad/android/tools/lint/Lint.java: -------------------------------------------------------------------------------- 1 | package com.ad.android.tools.lint; 2 | 3 | import com.android.annotations.NonNull; 4 | import com.android.tools.lint.Warning; 5 | import com.android.tools.lint.detector.api.Detector; 6 | import com.android.tools.lint.detector.api.Issue; 7 | import java.util.Arrays; 8 | import java.util.List; 9 | import org.junit.rules.TestRule; 10 | import org.junit.runner.Description; 11 | import org.junit.runners.model.Statement; 12 | 13 | /** 14 | * A JUnit rule for unit testing custom Lint rules.

Example: 15 | *

 16 |  * 
 17 |  * {@literal @}Rule public Lint lint =
 18 |  *  new Lint(new MyCustomRule(), MyCustomRule.ISSUE);
 19 |  *
 20 |  * {@literal @}Test
 21 |  * public void test() throws Exception {
 22 |  *  List<Warning> warnings =
 23 |  *    lint.files("AndroidManifest.xml", "res/values/string.xml");
 24 |  *
 25 |  *  assertThat(warnings).hasSize(2);
 26 |  * }
 27 |  * 
 28 |  * 
29 | */ 30 | public class Lint implements TestRule { 31 | static Wrapper wrapper; 32 | 33 | static { 34 | LintDetectorTestWrapper lintDetectorTestWrapper = new LintDetectorTestWrapper(); 35 | lintDetectorTestWrapper.setTestLintClient(lintDetectorTestWrapper.new ExtendedTestLintClient()); 36 | 37 | wrapper = lintDetectorTestWrapper; 38 | } 39 | 40 | private final Detector detector; 41 | private final Issue[] issues; 42 | 43 | private String[] files; 44 | 45 | /** 46 | * Constructs a new {@code Lint} junit rule.

Example: 47 | *

 48 |    * 
 49 |    * {@literal @}Rule public Lint lint =
 50 |    *  new Lint(new MyCustomRule(), MyCustomRule.ISSUE);
 51 |    * 
 52 |    * 
53 | * 54 | * @param detector the detector under test. 55 | * @param issues the issues under test. 56 | */ 57 | public Lint(@NonNull Detector detector, @NonNull Issue... issues) { 58 | this.detector = detector; 59 | this.issues = issues; 60 | } 61 | 62 | /** 63 | * This is called by the JUnit runner.

You don't need to interact with this method. 64 | */ 65 | @Override public Statement apply(Statement base, Description description) { 66 | return new LintStatement(base); 67 | } 68 | 69 | /** 70 | * Performs a Lint analysis on the specified files.

Example: 71 | *

 72 |    * 
 73 |    *  List<Warning> warnings =
 74 |    *    lint.files("AndroidManifest.xml", "res/values/string.xml");
 75 |    *
 76 |    *  assertThat(warnings).hasSize(2);
 77 |    * 
 78 |    * 
79 | * 80 | * Note: Lint uses the specified {@link Detector} and will report the specified {@link 81 | * Issue}s. 82 | * 83 | * @param files the relative paths of the files to analyze. 84 | * @return a {@link List} of {@link Warning}s. 85 | * @throws Exception for unexpected behavior during Lint analysis (e.g. could not find or access 86 | * file) 87 | */ 88 | public List files(@NonNull String... files) throws Exception { 89 | wrapper.analyze(detector, Arrays.asList(issues), files); 90 | 91 | return wrapper.getWarnings(); 92 | } 93 | 94 | public List project(TestFile... files) throws Exception { 95 | wrapper.analyze(detector, Arrays.asList(issues), files); 96 | 97 | return wrapper.getWarnings(); 98 | } 99 | 100 | private static class LintStatement extends Statement { 101 | private Statement base; 102 | 103 | private LintStatement(Statement base) { 104 | this.base = base; 105 | } 106 | 107 | @Override public void evaluate() throws Throwable { 108 | base.evaluate(); 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /hamcrest/src/main/java/com/ad/android/tools/lint/hamcrest/WarningMatcher.java: -------------------------------------------------------------------------------- 1 | package com.ad.android.tools.lint.hamcrest; 2 | 3 | import com.android.tools.lint.Warning; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | import org.hamcrest.Description; 7 | import org.hamcrest.Matcher; 8 | import org.hamcrest.TypeSafeMatcher; 9 | import org.hamcrest.core.AllOf; 10 | 11 | public class WarningMatcher { 12 | public static Matcher> hasWarnings(Matcher>... matchers) { 13 | return new AllOf<>(Arrays.asList(matchers)); 14 | } 15 | 16 | public static Matcher> in(String... filenames) { 17 | return new FileMatcher(filenames); 18 | } 19 | 20 | public static Matcher> atLine(Integer... lines) { 21 | return new LineNumberMatcher(lines); 22 | } 23 | 24 | public static Matcher> withMessage(String... messages) { 25 | return new MessageMatcher(messages); 26 | } 27 | 28 | private static class FileMatcher extends TypeSafeMatcher> { 29 | private final String[] filenames; 30 | 31 | private String expectedValue; 32 | private String actualValue; 33 | 34 | public FileMatcher(String[] filenames) { 35 | this.filenames = filenames; 36 | } 37 | 38 | @Override protected boolean matchesSafely(List warnings) { 39 | if (warnings == null) { 40 | return false; 41 | } 42 | 43 | if (warnings.size() != filenames.length) { 44 | return false; 45 | } 46 | 47 | for (int i = 0; i < warnings.size(); i++) { 48 | expectedValue = filenames[i]; 49 | actualValue = warnings.get(i).file.getName(); 50 | if (!expectedValue.equals(actualValue)) { 51 | return false; 52 | } 53 | } 54 | 55 | return true; 56 | } 57 | 58 | @Override public void describeTo(Description description) { 59 | description.appendText("Expected file name ").appendValue(expectedValue); 60 | } 61 | 62 | @Override 63 | protected void describeMismatchSafely(List item, Description mismatchDescription) { 64 | mismatchDescription.appendText("but was ").appendValue(actualValue); 65 | } 66 | } 67 | 68 | private static class LineNumberMatcher extends TypeSafeMatcher> { 69 | private final Integer[] lines; 70 | 71 | private int expectedValue; 72 | private int actualValue; 73 | 74 | public LineNumberMatcher(Integer[] lines) { 75 | this.lines = lines; 76 | } 77 | 78 | @Override protected boolean matchesSafely(List warnings) { 79 | if (warnings == null) { 80 | return false; 81 | } 82 | 83 | if (warnings.size() != lines.length) { 84 | return false; 85 | } 86 | 87 | for (int i = 0; i < warnings.size(); i++) { 88 | expectedValue = lines[i]; 89 | actualValue = warnings.get(i).line; 90 | if (expectedValue != actualValue) { 91 | return false; 92 | } 93 | } 94 | 95 | return true; 96 | } 97 | 98 | @Override public void describeTo(Description description) { 99 | description.appendText("Expected line number ").appendValue(expectedValue); 100 | } 101 | 102 | @Override 103 | protected void describeMismatchSafely(List item, Description mismatchDescription) { 104 | mismatchDescription.appendText("but was ").appendValue(actualValue); 105 | } 106 | } 107 | 108 | private static class MessageMatcher extends TypeSafeMatcher> { 109 | private final String[] messages; 110 | 111 | private String expectedValue; 112 | private String actualValue; 113 | 114 | public MessageMatcher(String[] messages) { 115 | this.messages = messages; 116 | } 117 | 118 | @Override protected boolean matchesSafely(List warnings) { 119 | if (warnings == null) { 120 | return false; 121 | } 122 | 123 | if (warnings.size() != messages.length) { 124 | return false; 125 | } 126 | 127 | for (int i = 0; i < warnings.size(); i++) { 128 | expectedValue = messages[i]; 129 | actualValue = warnings.get(i).message; 130 | if (!expectedValue.equals(actualValue)) { 131 | return false; 132 | } 133 | } 134 | 135 | return true; 136 | } 137 | 138 | @Override public void describeTo(Description description) { 139 | description.appendText("Expected message ").appendValue(expectedValue); 140 | } 141 | 142 | @Override 143 | protected void describeMismatchSafely(List item, Description mismatchDescription) { 144 | mismatchDescription.appendText("but was ").appendValue(actualValue); 145 | } 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 46 | if $cygwin ; then 47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 48 | fi 49 | 50 | # Attempt to set APP_HOME 51 | # Resolve links: $0 may be a link 52 | PRG="$0" 53 | # Need this for relative symlinks. 54 | while [ -h "$PRG" ] ; do 55 | ls=`ls -ld "$PRG"` 56 | link=`expr "$ls" : '.*-> \(.*\)$'` 57 | if expr "$link" : '/.*' > /dev/null; then 58 | PRG="$link" 59 | else 60 | PRG=`dirname "$PRG"`"/$link" 61 | fi 62 | done 63 | SAVED="`pwd`" 64 | cd "`dirname \"$PRG\"`/" >&- 65 | APP_HOME="`pwd -P`" 66 | cd "$SAVED" >&- 67 | 68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 69 | 70 | # Determine the Java command to use to start the JVM. 71 | if [ -n "$JAVA_HOME" ] ; then 72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 73 | # IBM's JDK on AIX uses strange locations for the executables 74 | JAVACMD="$JAVA_HOME/jre/sh/java" 75 | else 76 | JAVACMD="$JAVA_HOME/bin/java" 77 | fi 78 | if [ ! -x "$JAVACMD" ] ; then 79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 80 | 81 | Please set the JAVA_HOME variable in your environment to match the 82 | location of your Java installation." 83 | fi 84 | else 85 | JAVACMD="java" 86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | 92 | # Increase the maximum file descriptors if we can. 93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 94 | MAX_FD_LIMIT=`ulimit -H -n` 95 | if [ $? -eq 0 ] ; then 96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 97 | MAX_FD="$MAX_FD_LIMIT" 98 | fi 99 | ulimit -n $MAX_FD 100 | if [ $? -ne 0 ] ; then 101 | warn "Could not set maximum file descriptor limit: $MAX_FD" 102 | fi 103 | else 104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 105 | fi 106 | fi 107 | 108 | # For Darwin, add options to specify how the application appears in the dock 109 | if $darwin; then 110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 111 | fi 112 | 113 | # For Cygwin, switch paths to Windows format before running java 114 | if $cygwin ; then 115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 158 | function splitJvmOpts() { 159 | JVM_OPTS=("$@") 160 | } 161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 163 | 164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 165 | --------------------------------------------------------------------------------