diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml new file mode 100644 index 00000000..7ec01475 --- /dev/null +++ b/.github/workflows/android.yml @@ -0,0 +1,21 @@ +name: Android CI + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: set up JDK 1.8 + uses: actions/setup-java@v1 + with: + java-version: 1.8 + - name: Build with Gradle + run: ./gradlew build diff --git a/.github/workflows/upload_sarif.yml b/.github/workflows/upload_sarif.yml new file mode 100644 index 00000000..57708ff8 --- /dev/null +++ b/.github/workflows/upload_sarif.yml @@ -0,0 +1,22 @@ +name: "Upload SARIF" + +# Run workflow each time code is pushed to your repository and on a schedule. +# The scheduled workflow runs every at 00:00 on Sunday UTC time. +on: + push: + schedule: + - cron: '0 0 * * 0' + +jobs: + build: + runs-on: ubuntu-latest + steps: + # This step checks out a copy of your repository. + - name: Checkout repository + uses: actions/checkout@v2 + - name: Upload SARIF file + uses: github/codeql-action/upload-sarif@v1 + with: + # Path to SARIF file relative to the root of the repository + sarif_file: lint-results.sarif + checkout_path: library diff --git a/README.md b/README.md index c87ccc7f..4f14ce35 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,56 @@ The Android Lint API allows users to create custom lint rules. For example, if y This sample demonstrates how to create a custom lint checks and corresponding tests for those rules. + +# Sample Lint Checks + +This project shows how Android Studio 4 handles packaging of lint rules. + +## Lint Check Jar Library + +First, there's the lint check implementation itself. That's done in the +"checks" project, which just applies the Gradle "java" plugin, and +that project produces a jar. Note that the dependencies for the lint +check project (other than its testing dependencies) must all be "compileOnly": + + dependencies { + compileOnly "com.android.tools.lint:lint-api:$lintVersion" + compileOnly "com.android.tools.lint:lint-checks:$lintVersion" + ... + +## Lint Check AAR Library + +Next, there's a separate Android library project, called "library". This +library doesn't have any code on its own (though it could). However, +in its build.gradle, it specifies this: + + dependencies { + lintPublish project(':checks') + } + +This tells the Gradle plugin to take the output from the "checks" project +and package that as a "lint.jar" payload inside this library's AAR file. +When that's done, any other projects that depends on this library will +automatically be using the lint checks. + +## App Modules + +Note that you don't have to go through the extra "library indirection" +if you have a lint check that you only want to apply to one or more +app modules. You can simply include the `lintChecks` dependency as shown +above there as well, and then lint will include these rules when analyzing +the project. + +## Lint Version + +The lint version of the libraries (specified in this project as the +`lintVersion` variable in build.gradle) should be the same version +that is used by the Gradle plugin. + +If the Gradle plugin version is *X*.*Y*.*Z*, then the Lint library +version is *X+23*.*Y*.*Z*. + + Getting Started --------------- @@ -31,11 +81,6 @@ git clone https://github.com/googlesamples/android-custom-lint-rules.git cd android-custom-lint-rules ``` -##### Build the code - -For Android Studio 3.x and above, use the sample in `android-studio-3`. -If you are targeting Android Studio 2.x and older, use the sample in `android-studio-2`. - ##### Lint Dependencies When building your own rules, you will likely want to know which dependencies you should bring into your own project. @@ -81,3 +126,5 @@ Licensed under the Apache 2.0 license. See the LICENSE file for details. How to make contributions? -------------------------- Please read and follow the steps in the CONTRIBUTING.md + + diff --git a/android-studio-2/README.md b/android-studio-2/README.md deleted file mode 100644 index ef3f7823..00000000 --- a/android-studio-2/README.md +++ /dev/null @@ -1,33 +0,0 @@ -See README.md in the parent directory for general information. - -Getting Started ---------------- - -##### Fetch code - -``` -git clone https://github.com/googlesamples/android-custom-lint-rules.git -cd android-custom-lint-rules -``` - -##### Build the validator - -`./gradlew build` - -##### Copy to the lint directory - -`cp ./build/libs/android-custom-lint-rules.jar ~/.android/lint/` - -##### Verify whether the issues are registered with lint - -`lint --show MainActivityDetector` - -##### Run lint - -`./gradlew lint` - -> Note: If you can't run `lint` directly, you may want to include android tools `PATH` in your - `~/.bash_profile`. -> (i.e. `PATH=$PATH:~/Library/Android/sdk/tools`) -> -> Then run `source ~/.bash_profile`. diff --git a/android-studio-2/build.gradle b/android-studio-2/build.gradle deleted file mode 100644 index 7ed6cbd3..00000000 --- a/android-studio-2/build.gradle +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2015 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. - */ - -apply plugin: 'java' - -repositories { - google() - jcenter() -} - -ext { - lintVersion = '26.0.0-beta2' -} - -dependencies { - // For a description of the below dependencies, see the main project README - compile "com.android.tools.lint:lint-api:$lintVersion" - compile "com.android.tools.lint:lint-checks:$lintVersion" - testCompile "junit:junit:4.11" - testCompile "com.android.tools.lint:lint:$lintVersion" - testCompile "com.android.tools.lint:lint-tests:$lintVersion" - testCompile "com.android.tools:testutils:$lintVersion" -} - -jar { - manifest { - attributes("Lint-Registry": "com.example.google.lint.MyIssueRegistry") - } -} - -defaultTasks 'assemble' diff --git a/android-studio-2/gradle/wrapper/gradle-wrapper.properties b/android-studio-2/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index 9375478b..00000000 --- a/android-studio-2/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,6 +0,0 @@ -#Wed Aug 09 14:33:29 PDT 2017 -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-rc-1-all.zip diff --git a/android-studio-2/gradlew b/android-studio-2/gradlew deleted file mode 100755 index 91a7e269..00000000 --- a/android-studio-2/gradlew +++ /dev/null @@ -1,164 +0,0 @@ -#!/usr/bin/env bash - -############################################################################## -## -## Gradle start up script for UN*X -## -############################################################################## - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" - -warn ( ) { - echo "$*" -} - -die ( ) { - echo - echo "$*" - echo - exit 1 -} - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; -esac - -# For Cygwin, ensure paths are in UNIX format before anything is touched. -if $cygwin ; then - [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` -fi - -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >&- -APP_HOME="`pwd -P`" -cd "$SAVED" >&- - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=$((i+1)) - done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac -fi - -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") -} -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" - -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/android-studio-2/gradlew.bat b/android-studio-2/gradlew.bat deleted file mode 100644 index aec99730..00000000 --- a/android-studio-2/gradlew.bat +++ /dev/null @@ -1,90 +0,0 @@ -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windowz variants - -if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/android-studio-2/src/main/java/com/example/google/lint/MainActivityDetector.java b/android-studio-2/src/main/java/com/example/google/lint/MainActivityDetector.java deleted file mode 100644 index d74eb47a..00000000 --- a/android-studio-2/src/main/java/com/example/google/lint/MainActivityDetector.java +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (C) 2015 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.example.google.lint; - -import com.android.annotations.NonNull; -import com.android.tools.lint.detector.api.Category; -import com.android.tools.lint.detector.api.Context; -import com.android.tools.lint.detector.api.Detector; -import com.android.tools.lint.detector.api.Implementation; -import com.android.tools.lint.detector.api.Issue; -import com.android.tools.lint.detector.api.LintUtils; -import com.android.tools.lint.detector.api.Location; -import com.android.tools.lint.detector.api.ResourceXmlDetector; -import com.android.tools.lint.detector.api.Scope; -import com.android.tools.lint.detector.api.Severity; -import com.android.tools.lint.detector.api.XmlContext; -import org.w3c.dom.Element; -import org.w3c.dom.Node; - -import java.util.Collection; -import java.util.Collections; - -import static com.android.SdkConstants.ANDROID_MANIFEST_XML; -import static com.android.SdkConstants.ANDROID_URI; -import static com.android.SdkConstants.ATTR_NAME; -import static com.android.SdkConstants.TAG_ACTIVITY; -import static com.android.SdkConstants.TAG_INTENT_FILTER; -import static com.android.xml.AndroidManifest.NODE_ACTION; -import static com.android.xml.AndroidManifest.NODE_CATEGORY; -import static com.example.google.lint.ManifestConstants.ACTION_NAME_MAIN; -import static com.example.google.lint.ManifestConstants.CATEGORY_NAME_LAUNCHER; - -/** - * Checks for an activity with a launcher intent in AndroidManifest.xml. - *

- * NOTE: This is not a final API; if you rely on this be prepared - * to adjust your code for the next tools release. - */ -public class MainActivityDetector extends ResourceXmlDetector implements Detector.XmlScanner { - public static final Issue ISSUE = Issue.create( - "MainActivityDetector", - "Missing Launcher Activities", - "This app should have an activity with a launcher intent.", - Category.CORRECTNESS, - 8, - Severity.ERROR, - new Implementation( - MainActivityDetector.class, - Scope.MANIFEST_SCOPE)); - - /** - * This will be true if the current file we're checking has at least one activity. - */ - private boolean mHasActivity; - /** - * This will be true if the file has an activity with a launcher intent. - */ - private boolean mHasLauncherActivity; - /** - * The manifest file location for the main project, null if there is no manifest. - */ - private Location mManifestLocation; - - /** - * No-args constructor used by the lint framework to instantiate the detector. - */ - public MainActivityDetector() { - } - - @Override - public Collection getApplicableElements() { - return Collections.singleton(TAG_ACTIVITY); - } - - @Override - public void beforeCheckProject(@NonNull Context context) { - mHasActivity = false; - mHasLauncherActivity = false; - mManifestLocation = null; - } - - @Override - public void afterCheckProject(@NonNull Context context) { - // Don't report issues on libraries that may not have a launcher activity - if (context.getProject() == context.getMainProject() - && !context.getMainProject().isLibrary() - && mManifestLocation != null) { - if (!mHasActivity) { - context.report(ISSUE, mManifestLocation, - "Expecting " + ANDROID_MANIFEST_XML + " to have an <" + TAG_ACTIVITY + - "> tag."); - } else if (!mHasLauncherActivity) { - // Report the issue if the manifest file has no activity with a launcher intent. - context.report(ISSUE, mManifestLocation, - "Expecting " + ANDROID_MANIFEST_XML + - " to have an activity with a launcher intent."); - } - } - } - - @Override - public void afterCheckFile(@NonNull Context context) { - // Store a reference to the manifest file in case we need to report it's location. - if (context.getProject() == context.getMainProject()) { - mManifestLocation = Location.create(context.file); - } - } - - @Override - public void visitElement(XmlContext context, Element activityElement) { - // Checks every activity and reports an error if there is no activity with a launcher - // intent. - mHasActivity = true; - if (isMainActivity(activityElement)) { - mHasLauncherActivity = true; - } - } - - /** - * Returns true if the XML node is an activity with a launcher intent. - * - * @param activityNode The node to check. - * @return true if the node is an activity with a launcher intent. - */ - private boolean isMainActivity(Node activityNode) { - if (TAG_ACTIVITY.equals(activityNode.getNodeName())) { - // Loop through all tags - for (Element activityChild : LintUtils.getChildren(activityNode)) { - if (TAG_INTENT_FILTER.equals(activityChild.getNodeName())) { - // Check for these children nodes: - // - // - // - boolean hasLauncherCategory = false; - boolean hasMainAction = false; - - for (Element intentFilterChild : LintUtils.getChildren(activityChild)) { - // Check for category tag) - if (NODE_CATEGORY.equals(intentFilterChild.getNodeName()) - && CATEGORY_NAME_LAUNCHER.equals( - intentFilterChild.getAttributeNS(ANDROID_URI, ATTR_NAME))) { - hasLauncherCategory = true; - } - // Check for action tag - if (NODE_ACTION.equals(intentFilterChild.getNodeName()) - && ACTION_NAME_MAIN.equals( - intentFilterChild.getAttributeNS(ANDROID_URI, ATTR_NAME))) { - hasMainAction = true; - } - } - - if (hasLauncherCategory && hasMainAction) { - return true; - } - } - } - } - return false; - } -} diff --git a/android-studio-2/src/main/java/com/example/google/lint/ManifestConstants.java b/android-studio-2/src/main/java/com/example/google/lint/ManifestConstants.java deleted file mode 100644 index de7c6154..00000000 --- a/android-studio-2/src/main/java/com/example/google/lint/ManifestConstants.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2015 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.example.google.lint; - -/** - * Manifest Constant definition class. - * Amends constants not found in {@link com.android.SdkConstants}. - */ -public final class ManifestConstants { - public static final String CATEGORY_NAME_LAUNCHER = "android.intent.category.LAUNCHER"; - public static final String ACTION_NAME_MAIN = "android.intent.action.MAIN"; -} diff --git a/android-studio-2/src/main/java/com/example/google/lint/MyIssueRegistry.java b/android-studio-2/src/main/java/com/example/google/lint/MyIssueRegistry.java deleted file mode 100644 index a607b1bb..00000000 --- a/android-studio-2/src/main/java/com/example/google/lint/MyIssueRegistry.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2015 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.example.google.lint; - -import com.android.tools.lint.client.api.IssueRegistry; -import com.android.tools.lint.detector.api.Issue; - -import java.util.Collections; -import java.util.List; - -/** - * The list of issues that will be checked when running lint. - */ -@SuppressWarnings("unused") -public class MyIssueRegistry extends IssueRegistry { - @Override - public List getIssues() { - return Collections.singletonList(MainActivityDetector.ISSUE); - } -} diff --git a/android-studio-2/src/test/java/com/example/google/lint/MainActivityDetectorTest.java b/android-studio-2/src/test/java/com/example/google/lint/MainActivityDetectorTest.java deleted file mode 100644 index 6df66364..00000000 --- a/android-studio-2/src/test/java/com/example/google/lint/MainActivityDetectorTest.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (C) 2015 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.example.google.lint; - -import com.android.tools.lint.checks.infrastructure.LintDetectorTest; -import com.android.tools.lint.detector.api.Detector; -import com.android.tools.lint.detector.api.Issue; - -import java.util.Collections; -import java.util.List; - -import static com.android.SdkConstants.FN_ANDROID_MANIFEST_XML; - -/** - * NOTE: This is not a final API; if you rely on this be prepared - * to adjust your code for the next tools release. - */ -public class MainActivityDetectorTest extends LintDetectorTest { - @Override - protected Detector getDetector() { - return new MainActivityDetector(); - } - - @Override - protected List getIssues() { - return Collections.singletonList(MainActivityDetector.ISSUE); - } - - /** - * Test that a manifest with an activity with a launcher intent has no warnings. - */ - public void testHasMainActivity() { - lint().files( - xml(FN_ANDROID_MANIFEST_XML, "" + - "\n" + - "\n" + - " \n" + - " \n" + - " \n" + - "\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - "")) - .run() - .expectClean(); - } - - /** - * Test that a manifest without an activity with a launcher intent reports an error. - */ - public void testMissingMainActivity() { - String expected = "AndroidManifest.xml: Error: Expecting AndroidManifest.xml to have an " + - "activity with a launcher intent. [MainActivityDetector]\n" + - "1 errors, 0 warnings\n"; - lint().files( - xml(FN_ANDROID_MANIFEST_XML, "" + - "\n" + - "\n" + - " \n" + - " \n" + - " \n" + - " \n" + - "\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - "\n" + - " \n" + - " \n" + - "\n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - " \n" + - "")) - .run() - .expect(expected); - } - - /** - * Test that a manifest without an <application> tag reports an error. - */ - public void testMissingApplication() { - String expected = "AndroidManifest.xml: Error: Expecting AndroidManifest.xml to have an " + - " tag. [MainActivityDetector]\n" + - "1 errors, 0 warnings\n"; - lint().files( - xml(FN_ANDROID_MANIFEST_XML, "" + - "\n" + - "\n" + - "")) - .run() - .expect(expected); - } -} diff --git a/android-studio-3/README.md b/android-studio-3/README.md deleted file mode 100644 index 1ddb7f6d..00000000 --- a/android-studio-3/README.md +++ /dev/null @@ -1,48 +0,0 @@ -# Sample Lint Checks - -This project shows how Android Studio 3 (beta 5 and later) handles packaging -of lint rules. - -## Lint Check Jar Library - -First, there's the lint check implementation itself. That's done in the -"checks" project, which just applies the Gradle "java" plugin, and -that project produces a jar. Note that the dependencies for the lint -check project (other than its testing dependencies) must all be "compileOnly": - - dependencies { - compileOnly "com.android.tools.lint:lint-api:$lintVersion" - compileOnly "com.android.tools.lint:lint-checks:$lintVersion" - ... - -## Lint Check AAR Library - -Next, there's a separate Android library project, called "library". This -library doesn't have any code on its own (though it could). However, -in its build.gradle, it specifies this: - - dependencies { - lintChecks project(':checks') - } - -This tells the Gradle plugin to take the output from the "checks" project -and package that as a "lint.jar" payload inside this library's AAR file. -When that's done, any other projects that depends on this library will -automatically be using the lint checks. - -## App Modules - -Note that you don't have to go through the extra "library indirection" -if you have a lint check that you only want to apply to one or more -app modules. You can simply include the `lintChecks` dependency as shown -above there as well, and then lint will include these rules when analyzing -the project. - -## Lint Version - -The lint version of the libraries (specified in this project as the -`lintVersion` variable in build.gradle) should be the same version -that is used by the Gradle plugin. - -If the Gradle plugin version is *X*.*Y*.*Z*, then the Lint library -version is *X+23*.*Y*.*Z*. diff --git a/android-studio-3/build.gradle b/android-studio-3/build.gradle deleted file mode 100644 index f9e42121..00000000 --- a/android-studio-3/build.gradle +++ /dev/null @@ -1,24 +0,0 @@ -buildscript { - ext { - lintVersion = '26.5.0' - } - - repositories { - google() - jcenter() - } - dependencies { - classpath "com.android.tools.build:gradle:3.5.2" - } -} - -allprojects { - repositories { - google() - jcenter() - } -} - -task clean(type: Delete) { - delete rootProject.buildDir -} diff --git a/android-studio-3/checks/build.gradle b/android-studio-3/checks/build.gradle deleted file mode 100644 index b8789f32..00000000 --- a/android-studio-3/checks/build.gradle +++ /dev/null @@ -1,22 +0,0 @@ -apply plugin: 'java-library' - -dependencies { - // For a description of the below dependencies, see the main project README - compileOnly "com.android.tools.lint:lint-api:$lintVersion" - compileOnly "com.android.tools.lint:lint-checks:$lintVersion" - testImplementation "junit:junit:4.12" - testImplementation "com.android.tools.lint:lint:$lintVersion" - testImplementation "com.android.tools.lint:lint-tests:$lintVersion" - testImplementation "com.android.tools:testutils:$lintVersion" -} - -sourceCompatibility = "1.8" -targetCompatibility = "1.8" - -jar { - manifest { - // Only use the "-v2" key here if your checks have been updated to the - // new 3.0 APIs (including UAST) - attributes("Lint-Registry-v2": "com.example.lint.checks.SampleIssueRegistry") - } -} diff --git a/android-studio-3/checks/src/main/java/com/example/lint/checks/SampleCodeDetector.java b/android-studio-3/checks/src/main/java/com/example/lint/checks/SampleCodeDetector.java deleted file mode 100644 index 45acc6ed..00000000 --- a/android-studio-3/checks/src/main/java/com/example/lint/checks/SampleCodeDetector.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * 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.example.lint.checks; - -import com.android.tools.lint.client.api.UElementHandler; -import com.android.tools.lint.detector.api.Category; -import com.android.tools.lint.detector.api.Detector; -import com.android.tools.lint.detector.api.Detector.UastScanner; -import com.android.tools.lint.detector.api.Implementation; -import com.android.tools.lint.detector.api.Issue; -import com.android.tools.lint.detector.api.JavaContext; -import com.android.tools.lint.detector.api.Scope; -import com.android.tools.lint.detector.api.Severity; - -import org.jetbrains.uast.UElement; -import org.jetbrains.uast.ULiteralExpression; -import org.jetbrains.uast.UastLiteralUtils; - -import java.util.Collections; -import java.util.List; - -/** - * Sample detector showing how to analyze Kotlin/Java code. - * This example flags all string literals in the code that contain - * the word "lint". - */ -public class SampleCodeDetector extends Detector implements UastScanner { - /** Issue describing the problem and pointing to the detector implementation */ - public static final Issue ISSUE = Issue.create( - // ID: used in @SuppressLint warnings etc - "ShortUniqueId", - - // Title -- shown in the IDE's preference dialog, as category headers in the - // Analysis results window, etc - "Lint Mentions", - - // Full explanation of the issue; you can use some markdown markup such as - // `monospace`, *italic*, and **bold**. - "This check highlights string literals in code which mentions " + - "the word `lint`. Blah blah blah.\n" + - "\n" + - "Another paragraph here.\n", - Category.CORRECTNESS, - 6, - Severity.WARNING, - new Implementation( - SampleCodeDetector.class, - Scope.JAVA_FILE_SCOPE)); - - @Override - public List> getApplicableUastTypes() { - return Collections.singletonList(ULiteralExpression.class); - } - - @Override - public UElementHandler createUastHandler(JavaContext context) { - // Note: Visiting UAST nodes is a pretty general purpose mechanism; - // Lint has specialized support to do common things like "visit every class - // that extends a given super class or implements a given interface", and - // "visit every call site that calls a method by a given name" etc. - // Take a careful look at UastScanner and the various existing lint check - // implementations before doing things the "hard way". - // Also be aware of context.getJavaEvaluator() which provides a lot of - // utility functionality. - return new UElementHandler() { - @Override - public void visitLiteralExpression(ULiteralExpression expression) { - String string = UastLiteralUtils.getValueIfStringLiteral(expression); - if (string == null) { - return; - } - - if (string.contains("lint") && string.matches(".*\\blint\\b.*")) { - context.report(ISSUE, expression, context.getLocation(expression), - "This code mentions `lint`: **Congratulations**"); - } - } - }; - } -} diff --git a/android-studio-3/checks/src/main/java/com/example/lint/checks/SampleIssueRegistry.java b/android-studio-3/checks/src/main/java/com/example/lint/checks/SampleIssueRegistry.java deleted file mode 100644 index 92cd6b14..00000000 --- a/android-studio-3/checks/src/main/java/com/example/lint/checks/SampleIssueRegistry.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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.example.lint.checks; - -import com.android.tools.lint.client.api.IssueRegistry; -import com.android.tools.lint.detector.api.ApiKt; -import com.android.tools.lint.detector.api.Issue; - -import java.util.Collections; -import java.util.List; - -/* - * The list of issues that will be checked when running lint. - */ -public class SampleIssueRegistry extends IssueRegistry { - @Override - public List getIssues() { - return Collections.singletonList(SampleCodeDetector.ISSUE); - } - - @Override - public int getApi() { - return ApiKt.CURRENT_API; - } -} - diff --git a/android-studio-3/checks/src/test/java/com/example/lint/checks/SampleCodeDetectorTest.java b/android-studio-3/checks/src/test/java/com/example/lint/checks/SampleCodeDetectorTest.java deleted file mode 100644 index e6c7e8a4..00000000 --- a/android-studio-3/checks/src/test/java/com/example/lint/checks/SampleCodeDetectorTest.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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.example.lint.checks; - -import com.android.tools.lint.checks.infrastructure.LintDetectorTest; -import com.android.tools.lint.detector.api.Detector; -import com.android.tools.lint.detector.api.Issue; - -import java.util.Collections; -import java.util.List; - -public class SampleCodeDetectorTest extends LintDetectorTest { - public void testBasic() { - lint().files( - java("" + - "package test.pkg;\n" + - "public class TestClass1 {\n" + - " // In a comment, mentioning \"lint\" has no effect\n" + - " private static String s1 = \"Ignore non-word usages: linting\";\n" + - " private static String s2 = \"Let's say it: lint\";\n" + - "}")) - .run() - .expect("src/test/pkg/TestClass1.java:5: Warning: This code mentions lint: Congratulations [ShortUniqueId]\n" + - " private static String s2 = \"Let's say it: lint\";\n" + - " ~~~~~~~~~~~~~~~~~~~~\n" + - "0 errors, 1 warnings\n"); - } - - @Override - protected Detector getDetector() { - return new SampleCodeDetector(); - } - - @Override - protected List getIssues() { - return Collections.singletonList(SampleCodeDetector.ISSUE); - } -} \ No newline at end of file diff --git a/android-studio-3/gradle/wrapper/gradle-wrapper.jar b/android-studio-3/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 13372aef..00000000 Binary files a/android-studio-3/gradle/wrapper/gradle-wrapper.jar and /dev/null differ diff --git a/android-studio-3/gradlew.bat b/android-studio-3/gradlew.bat deleted file mode 100644 index aec99730..00000000 --- a/android-studio-3/gradlew.bat +++ /dev/null @@ -1,90 +0,0 @@ -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windowz variants - -if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/android-studio-3/library/build.gradle b/android-studio-3/library/build.gradle deleted file mode 100644 index 90f7ba01..00000000 --- a/android-studio-3/library/build.gradle +++ /dev/null @@ -1,18 +0,0 @@ -apply plugin: 'com.android.library' - -android { - compileSdkVersion 29 - defaultConfig { - minSdkVersion 15 - targetSdkVersion 29 - } - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } -} - -/** Package the given lint checks library into this AAR */ -dependencies { - lintChecks project(':checks') -} diff --git a/android-studio-4/README.md b/android-studio-4/README.md deleted file mode 100644 index e025c26a..00000000 --- a/android-studio-4/README.md +++ /dev/null @@ -1,47 +0,0 @@ -# Sample Lint Checks - -This project shows how Android Studio 4 handles packaging of lint rules. - -## Lint Check Jar Library - -First, there's the lint check implementation itself. That's done in the -"checks" project, which just applies the Gradle "java" plugin, and -that project produces a jar. Note that the dependencies for the lint -check project (other than its testing dependencies) must all be "compileOnly": - - dependencies { - compileOnly "com.android.tools.lint:lint-api:$lintVersion" - compileOnly "com.android.tools.lint:lint-checks:$lintVersion" - ... - -## Lint Check AAR Library - -Next, there's a separate Android library project, called "library". This -library doesn't have any code on its own (though it could). However, -in its build.gradle, it specifies this: - - dependencies { - lintPublish project(':checks') - } - -This tells the Gradle plugin to take the output from the "checks" project -and package that as a "lint.jar" payload inside this library's AAR file. -When that's done, any other projects that depends on this library will -automatically be using the lint checks. - -## App Modules - -Note that you don't have to go through the extra "library indirection" -if you have a lint check that you only want to apply to one or more -app modules. You can simply include the `lintChecks` dependency as shown -above there as well, and then lint will include these rules when analyzing -the project. - -## Lint Version - -The lint version of the libraries (specified in this project as the -`lintVersion` variable in build.gradle) should be the same version -that is used by the Gradle plugin. - -If the Gradle plugin version is *X*.*Y*.*Z*, then the Lint library -version is *X+23*.*Y*.*Z*. diff --git a/android-studio-4/gradle.properties b/android-studio-4/gradle.properties deleted file mode 100644 index aac7c9b4..00000000 --- a/android-studio-4/gradle.properties +++ /dev/null @@ -1,17 +0,0 @@ -# Project-wide Gradle settings. - -# IDE (e.g. Android Studio) users: -# Gradle settings configured through the IDE *will override* -# any settings specified in this file. - -# For more details on how to configure your build environment visit -# http://www.gradle.org/docs/current/userguide/build_environment.html - -# Specifies the JVM arguments used for the daemon process. -# The setting is particularly useful for tweaking memory settings. -org.gradle.jvmargs=-Xmx1536m - -# When configured, Gradle will run in incubating parallel mode. -# This option should only be used with decoupled projects. More details, visit -# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects -# org.gradle.parallel=true diff --git a/android-studio-4/gradle/wrapper/gradle-wrapper.jar b/android-studio-4/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 13372aef..00000000 Binary files a/android-studio-4/gradle/wrapper/gradle-wrapper.jar and /dev/null differ diff --git a/android-studio-4/gradle/wrapper/gradle-wrapper.properties b/android-studio-4/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index 0755eca4..00000000 --- a/android-studio-4/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,6 +0,0 @@ -#Fri Sep 01 06:52:38 PDT 2017 -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.1-rc-1-all.zip diff --git a/android-studio-4/gradlew b/android-studio-4/gradlew deleted file mode 100755 index 9d82f789..00000000 --- a/android-studio-4/gradlew +++ /dev/null @@ -1,160 +0,0 @@ -#!/usr/bin/env bash - -############################################################################## -## -## Gradle start up script for UN*X -## -############################################################################## - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" - -warn ( ) { - echo "$*" -} - -die ( ) { - echo - echo "$*" - echo - exit 1 -} - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; -esac - -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=$((i+1)) - done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac -fi - -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") -} -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" - -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/android-studio-4/library/src/main/AndroidManifest.xml b/android-studio-4/library/src/main/AndroidManifest.xml deleted file mode 100644 index 843049f7..00000000 --- a/android-studio-4/library/src/main/AndroidManifest.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/android-studio-4/settings.gradle b/android-studio-4/settings.gradle deleted file mode 100644 index b613efff..00000000 --- a/android-studio-4/settings.gradle +++ /dev/null @@ -1 +0,0 @@ -include ':checks', ':library' diff --git a/android-studio-4/build.gradle b/build.gradle similarity index 100% rename from android-studio-4/build.gradle rename to build.gradle diff --git a/android-studio-4/checks/.gitignore b/checks/.gitignore similarity index 100% rename from android-studio-4/checks/.gitignore rename to checks/.gitignore diff --git a/android-studio-4/checks/build.gradle b/checks/build.gradle similarity index 100% rename from android-studio-4/checks/build.gradle rename to checks/build.gradle diff --git a/android-studio-4/checks/src/main/java/com/example/lint/checks/SampleCodeDetector.kt b/checks/src/main/java/com/example/lint/checks/SampleCodeDetector.kt similarity index 100% rename from android-studio-4/checks/src/main/java/com/example/lint/checks/SampleCodeDetector.kt rename to checks/src/main/java/com/example/lint/checks/SampleCodeDetector.kt diff --git a/android-studio-4/checks/src/main/java/com/example/lint/checks/SampleIssueRegistry.kt b/checks/src/main/java/com/example/lint/checks/SampleIssueRegistry.kt similarity index 100% rename from android-studio-4/checks/src/main/java/com/example/lint/checks/SampleIssueRegistry.kt rename to checks/src/main/java/com/example/lint/checks/SampleIssueRegistry.kt diff --git a/android-studio-4/checks/src/main/resources/META-INF/services/com.android.tools.lint.client.api.IssueRegistry b/checks/src/main/resources/META-INF/services/com.android.tools.lint.client.api.IssueRegistry similarity index 100% rename from android-studio-4/checks/src/main/resources/META-INF/services/com.android.tools.lint.client.api.IssueRegistry rename to checks/src/main/resources/META-INF/services/com.android.tools.lint.client.api.IssueRegistry diff --git a/android-studio-4/checks/src/test/java/com/example/lint/checks/SampleCodeDetectorTest.kt b/checks/src/test/java/com/example/lint/checks/SampleCodeDetectorTest.kt similarity index 100% rename from android-studio-4/checks/src/test/java/com/example/lint/checks/SampleCodeDetectorTest.kt rename to checks/src/test/java/com/example/lint/checks/SampleCodeDetectorTest.kt diff --git a/android-studio-3/gradle.properties b/gradle.properties similarity index 100% rename from android-studio-3/gradle.properties rename to gradle.properties diff --git a/android-studio-2/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar similarity index 100% rename from android-studio-2/gradle/wrapper/gradle-wrapper.jar rename to gradle/wrapper/gradle-wrapper.jar diff --git a/android-studio-3/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties similarity index 93% rename from android-studio-3/gradle/wrapper/gradle-wrapper.properties rename to gradle/wrapper/gradle-wrapper.properties index f0f067c5..7d4126d0 100644 --- a/android-studio-3/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.0-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-all.zip diff --git a/android-studio-3/gradlew b/gradlew similarity index 100% rename from android-studio-3/gradlew rename to gradlew diff --git a/android-studio-4/gradlew.bat b/gradlew.bat similarity index 100% rename from android-studio-4/gradlew.bat rename to gradlew.bat diff --git a/android-studio-4/library/.gitignore b/library/.gitignore similarity index 100% rename from android-studio-4/library/.gitignore rename to library/.gitignore diff --git a/android-studio-4/library/build.gradle b/library/build.gradle similarity index 64% rename from android-studio-4/library/build.gradle rename to library/build.gradle index 2261372a..83ede8a2 100644 --- a/android-studio-4/library/build.gradle +++ b/library/build.gradle @@ -10,6 +10,13 @@ android { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } + lintOptions { + textReport true + textOutput file("../lint-results.sarif") + // try to get additional issues flagged in the report + checkAllWarnings true + //checkDependencies true + } } /** Package the given lint checks library into this AAR */ diff --git a/android-studio-3/library/src/main/AndroidManifest.xml b/library/src/main/AndroidManifest.xml similarity index 100% rename from android-studio-3/library/src/main/AndroidManifest.xml rename to library/src/main/AndroidManifest.xml diff --git a/library/src/main/java/com/android/tools/demo/Test.java b/library/src/main/java/com/android/tools/demo/Test.java new file mode 100644 index 00000000..a663283e --- /dev/null +++ b/library/src/main/java/com/android/tools/demo/Test.java @@ -0,0 +1,12 @@ +package com.android.tools.demo; + +public class Test { + public void test() { + String s = "/sdcard/path"; // not allowed + String t = "/sdcard/path2"; // not allowed + String u = "/sdcard/path3"; // not allowed + String v = "/sdcard/path4"; // not allowed + Integer i = new Integer(42); + Integer j = new Integer(43); + } +} diff --git a/library/src/main/res/values-nb/strings.xml b/library/src/main/res/values-nb/strings.xml new file mode 100644 index 00000000..c733d2ab --- /dev/null +++ b/library/src/main/res/values-nb/strings.xml @@ -0,0 +1,5 @@ + + My String + My String 3 + Extra + diff --git a/library/src/main/res/values/strings.xml b/library/src/main/res/values/strings.xml new file mode 100644 index 00000000..795d9050 --- /dev/null +++ b/library/src/main/res/values/strings.xml @@ -0,0 +1,4 @@ + + My String + My String2 + diff --git a/lint-results.sarif b/lint-results.sarif new file mode 100644 index 00000000..6df7f508 --- /dev/null +++ b/lint-results.sarif @@ -0,0 +1,778 @@ +{ + "$schema" : "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json", + "version" : "2.1.0", + "runs" : [ + { + "tool": { + "driver": { + "name": "Android Lint", + "fullName": "Android Lint (in gradle)", + "version": "4.2.0-dev", + "organization": "Google", + "informationUri": "https://developer.android.com/studio/write/lint", + "fullDescription": { + "text": "Static analysis originally for Android source code but now performing general analysis" + }, + "language": "en-US", + "rules": [ + { + "id": "ExtraTranslation", + "shortDescription": { + "text": "Extra translation" + }, + "fullDescription": { + "text": "If a string appears in a specific language translation file, but there is no corresponding string in the default locale, then this string is probably unused. (It's technically possible that your application is only intended to run in a specific locale, but it's still a good idea to provide a fallback.)\n\nNote that these strings can lead to crashes if the string is looked up on any locale not providing a translation, so it's important to clean them up." + }, + "defaultConfiguration": { + "level": "error", + "rank": 50 + }, + "properties": { + "tags": [ + "Messages", + "Correctness" + ] + } + }, + { + "id": "MinSdkTooLow", + "shortDescription": { + "text": "API Version Too Low" + }, + "fullDescription": { + "text": "The value of the minSdkVersion property is too low and can be incremented without noticeably reducing the number of supported devices.", + "markdown": "The value of the `minSdkVersion` property is too low and can be incremented without noticeably reducing the number of supported devices." + }, + "defaultConfiguration": { + "level": "warning", + "rank": 70 + }, + "properties": { + "tags": [ + "Correctness" + ] + } + }, + { + "id": "MissingTranslation", + "shortDescription": { + "text": "Incomplete translation" + }, + "fullDescription": { + "text": "If an application has more than one locale, then all the strings declared in one language should also be translated in all other languages.\n\nIf the string should not be translated, you can add the attribute translatable=\"false\" on the element, or you can define all your non-translatable strings in a resource file called donottranslate.xml. Or, you can ignore the issue with a tools:ignore=\"MissingTranslation\" attribute.\n\nYou can tell lint (and other tools) which language is the default language in your res/values/ folder by specifying tools:locale=\"languageCode\" for the root element in your resource file. (The tools prefix refers to the namespace declaration http://schemas.android.com/tools.)", + "markdown": "If an application has more than one locale, then all the strings declared in one language should also be translated in all other languages.\n\nIf the string should **not** be translated, you can add the attribute `translatable=\"false\"` on the `` element, or you can define all your non-translatable strings in a resource file called `donottranslate.xml`. Or, you can ignore the issue with a `tools:ignore=\"MissingTranslation\"` attribute.\n\nYou can tell lint (and other tools) which language is the default language in your `res/values/` folder by specifying `tools:locale=\"languageCode\"` for the root `` element in your resource file. (The `tools` prefix refers to the namespace declaration `http://schemas.android.com/tools`.)" + }, + "defaultConfiguration": { + "level": "error", + "rank": 30 + }, + "properties": { + "tags": [ + "Messages", + "Correctness" + ] + } + }, + { + "id": "OldTargetApi", + "shortDescription": { + "text": "Target SDK attribute is not targeting latest version" + }, + "fullDescription": { + "text": "When your application runs on a version of Android that is more recent than your targetSdkVersion specifies that it has been tested with, various compatibility modes kick in. This ensures that your application continues to work, but it may look out of place. For example, if the targetSdkVersion is less than 14, your app may get an option button in the UI.\n\nTo fix this issue, set the targetSdkVersion to the highest available value. Then test your app to make sure everything works correctly. You may want to consult the compatibility notes to see what changes apply to each version you are adding support for: https://developer.android.com/reference/android/os/Build.VERSION_CODES.html as well as follow this guide:\nhttps://developer.android.com/distribute/best-practices/develop/target-sdk.html", + "markdown": "When your application runs on a version of Android that is more recent than your `targetSdkVersion` specifies that it has been tested with, various compatibility modes kick in. This ensures that your application continues to work, but it may look out of place. For example, if the `targetSdkVersion` is less than 14, your app may get an option button in the UI.\n\nTo fix this issue, set the `targetSdkVersion` to the highest available value. Then test your app to make sure everything works correctly. You may want to consult the compatibility notes to see what changes apply to each version you are adding support for: https://developer.android.com/reference/android/os/Build.VERSION_CODES.html as well as follow this guide:\nhttps://developer.android.com/distribute/best-practices/develop/target-sdk.html" + }, + "defaultConfiguration": { + "level": "warning", + "rank": 50 + }, + "properties": { + "tags": [ + "Correctness" + ] + } + }, + { + "id": "SdCardPath", + "shortDescription": { + "text": "Hardcoded reference to /sdcard", + "markdown": "Hardcoded reference to `/sdcard`" + }, + "fullDescription": { + "text": "Your code should not reference the /sdcard path directly; instead use Environment.getExternalStorageDirectory().getPath().\n\nSimilarly, do not reference the /data/data/ path directly; it can vary in multi-user scenarios. Instead, use Context.getFilesDir().getPath().", + "markdown": "Your code should not reference the `/sdcard` path directly; instead use `Environment.getExternalStorageDirectory().getPath()`.\n\nSimilarly, do not reference the `/data/data/` path directly; it can vary in multi-user scenarios. Instead, use `Context.getFilesDir().getPath()`." + }, + "defaultConfiguration": { + "level": "warning", + "rank": 50 + }, + "properties": { + "tags": [ + "Correctness" + ] + } + }, + { + "id": "UseValueOf", + "shortDescription": { + "text": "Should use valueOf instead of new", + "markdown": "Should use `valueOf` instead of `new`" + }, + "fullDescription": { + "text": "You should not call the constructor for wrapper classes directly, such as`new Integer(42)`. Instead, call the valueOf factory method, such as Integer.valueOf(42). This will typically use less memory because common integers such as 0 and 1 will share a single instance.", + "markdown": "You should not call the constructor for wrapper classes directly, such as`new Integer(42)`. Instead, call the `valueOf` factory method, such as `Integer.valueOf(42)`. This will typically use less memory because common integers such as 0 and 1 will share a single instance." + }, + "defaultConfiguration": { + "level": "warning", + "rank": 70 + }, + "properties": { + "tags": [ + "Performance" + ] + } + } + ] + } + }, + "originalUriBaseIds": { + "%SRCROOT%": { + "uri": "file:///home/tnorbye/dev/github/tnorbye/new/android-custom-lint-rules/" + } + }, + "results": [ + { + "ruleId": "OldTargetApi", + "ruleIndex": 3, + "message": { + "text": "Not targeting the latest versions of Android; compatibility modes apply. Consider testing and updating this version. Consult the android.os.Build.VERSION_CODES javadoc for details." + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uriBaseId": "%SRCROOT%", + "uri": "library/build.gradle" + }, + "region": { + "startLine": 7, + "startColumn": 26, + "endLine": 7, + "endColumn": 28, + "charOffset": 142, + "charLength": 2, + "snippet": { + "text": "29" + } + }, + "contextRegion": { + "startLine": 5, + "endLine": 10, + "snippet": { + "text": " defaultConfig {\n minSdkVersion 15\n targetSdkVersion 29\n }" + } + } + } + } + ], + "fixes": [ + { + "description": { + "text": "Update targetSdkVersion to 30" + }, + "artifactChanges": [ + { + "artifactLocation": { + "uriBaseId": "%SRCROOT%", + "uri": "library/build.gradle" + }, + "replacements": [ + { + "deletedRegion": { + "startLine": 7, + "startColumn": 27, + "charOffset": 142, + "endLine": 7, + "endColumn": 1, + "charLength": 2 + }, + "insertedContent": { + "text": "30\n" + } + } + ] + } + ] + } + ], + "partialFingerprints": { + "sourceContext/v1": "a6596680a2a6f042" + } + }, + { + "ruleId": "SdCardPath", + "ruleIndex": 4, + "message": { + "text": "Do not hardcode \"/sdcard/\"; use Environment.getExternalStorageDirectory().getPath() instead", + "markdown": "Do not hardcode \"/sdcard/\"; use `Environment.getExternalStorageDirectory().getPath()` instead" + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uriBaseId": "%SRCROOT%", + "uri": "library/src/main/java/com/android/tools/demo/Test.java" + }, + "region": { + "startLine": 5, + "startColumn": 20, + "endLine": 5, + "endColumn": 34, + "charOffset": 97, + "charLength": 14, + "snippet": { + "text": "\"/sdcard/path\"" + } + }, + "contextRegion": { + "startLine": 3, + "endLine": 8, + "snippet": { + "text": "public class Test {\n public void test() {\n String s = \"/sdcard/path\"; // not allowed\n String t = \"/sdcard/path2\"; // not allowed" + } + } + } + } + ], + "partialFingerprints": { + "sourceContext/v1": "cd98c7d9da9ce2f6" + } + }, + { + "ruleId": "SdCardPath", + "ruleIndex": 4, + "message": { + "text": "Do not hardcode \"/sdcard/\"; use Environment.getExternalStorageDirectory().getPath() instead", + "markdown": "Do not hardcode \"/sdcard/\"; use `Environment.getExternalStorageDirectory().getPath()` instead" + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uriBaseId": "%SRCROOT%", + "uri": "library/src/main/java/com/android/tools/demo/Test.java" + }, + "region": { + "startLine": 6, + "startColumn": 20, + "endLine": 6, + "endColumn": 35, + "charOffset": 147, + "charLength": 15, + "snippet": { + "text": "\"/sdcard/path2\"" + } + }, + "contextRegion": { + "startLine": 4, + "endLine": 9, + "snippet": { + "text": " public void test() {\n String s = \"/sdcard/path\"; // not allowed\n String t = \"/sdcard/path2\"; // not allowed\n String u = \"/sdcard/path3\"; // not allowed" + } + } + } + } + ], + "partialFingerprints": { + "sourceContext/v1": "596372887d2b3fef" + } + }, + { + "ruleId": "SdCardPath", + "ruleIndex": 4, + "message": { + "text": "Do not hardcode \"/sdcard/\"; use Environment.getExternalStorageDirectory().getPath() instead", + "markdown": "Do not hardcode \"/sdcard/\"; use `Environment.getExternalStorageDirectory().getPath()` instead" + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uriBaseId": "%SRCROOT%", + "uri": "library/src/main/java/com/android/tools/demo/Test.java" + }, + "region": { + "startLine": 7, + "startColumn": 20, + "endLine": 7, + "endColumn": 35, + "charOffset": 198, + "charLength": 15, + "snippet": { + "text": "\"/sdcard/path3\"" + } + }, + "contextRegion": { + "startLine": 5, + "endLine": 10, + "snippet": { + "text": " String s = \"/sdcard/path\"; // not allowed\n String t = \"/sdcard/path2\"; // not allowed\n String u = \"/sdcard/path3\"; // not allowed\n String v = \"/sdcard/path4\"; // not allowed" + } + } + } + } + ], + "partialFingerprints": { + "sourceContext/v1": "bd6969b6f5454adc" + } + }, + { + "ruleId": "SdCardPath", + "ruleIndex": 4, + "message": { + "text": "Do not hardcode \"/sdcard/\"; use Environment.getExternalStorageDirectory().getPath() instead", + "markdown": "Do not hardcode \"/sdcard/\"; use `Environment.getExternalStorageDirectory().getPath()` instead" + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uriBaseId": "%SRCROOT%", + "uri": "library/src/main/java/com/android/tools/demo/Test.java" + }, + "region": { + "startLine": 8, + "startColumn": 20, + "endLine": 8, + "endColumn": 35, + "charOffset": 249, + "charLength": 15, + "snippet": { + "text": "\"/sdcard/path4\"" + } + }, + "contextRegion": { + "startLine": 6, + "endLine": 11, + "snippet": { + "text": " String t = \"/sdcard/path2\"; // not allowed\n String u = \"/sdcard/path3\"; // not allowed\n String v = \"/sdcard/path4\"; // not allowed\n\tInteger i = new Integer(42);" + } + } + } + } + ], + "partialFingerprints": { + "sourceContext/v1": "df599c64bb238ee1" + } + }, + { + "ruleId": "MinSdkTooLow", + "ruleIndex": 1, + "message": { + "text": "The value of minSdkVersion is too low. It can be incremented without noticeably reducing the number of supported devices." + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uriBaseId": "%SRCROOT%", + "uri": "library/build.gradle" + }, + "region": { + "startLine": 6, + "startColumn": 9, + "endLine": 6, + "endColumn": 25, + "charOffset": 100, + "charLength": 16, + "snippet": { + "text": "minSdkVersion 15" + } + }, + "contextRegion": { + "startLine": 4, + "endLine": 9, + "snippet": { + "text": " compileSdkVersion 29\n defaultConfig {\n minSdkVersion 15\n targetSdkVersion 29" + } + } + } + } + ], + "fixes": [ + { + "description": { + "text": "Update minSdkVersion to 16" + }, + "artifactChanges": [ + { + "artifactLocation": { + "uriBaseId": "%SRCROOT%", + "uri": "library/build.gradle" + }, + "replacements": [ + { + "deletedRegion": { + "startLine": 6, + "startColumn": 24, + "charOffset": 114, + "endLine": 6, + "endColumn": 1, + "charLength": 2 + }, + "insertedContent": { + "text": "16\n" + } + } + ] + } + ] + } + ], + "partialFingerprints": { + "sourceContext/v1": "9bbfa38d306eaf34" + } + }, + { + "ruleId": "MissingTranslation", + "ruleIndex": 2, + "message": { + "text": "\"my_string2\" is not translated in \"nb\" (Norwegian Bokmål)" + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uriBaseId": "%SRCROOT%", + "uri": "library/src/main/res/values/strings.xml" + }, + "region": { + "startLine": 3, + "startColumn": 13, + "endLine": 3, + "endColumn": 30, + "charOffset": 72, + "charLength": 17, + "snippet": { + "text": "name=\"my_string2\"" + } + }, + "contextRegion": { + "startLine": 1, + "endLine": 6, + "snippet": { + "text": "\n My String\n My String2\n" + } + } + } + } + ], + "fixes": [ + { + "description": { + "text": "Mark non-translatable" + }, + "artifactChanges": [ + { + "artifactLocation": { + "uriBaseId": "%SRCROOT%", + "uri": "library/src/main/res/values/strings.xml" + }, + "replacements": [ + { + "deletedRegion": { + "startLine": 3, + "startColumn": 31, + "charOffset": 89 + }, + "insertedContent": { + "text": " translatable=\"false\"\n" + } + } + ] + } + ] + } + ], + "partialFingerprints": { + "sourceContext/v1": "3afe0201c83edf52" + } + }, + { + "ruleId": "ExtraTranslation", + "ruleIndex": 0, + "message": { + "text": "\"my_string3\" is translated here but not found in default locale" + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uriBaseId": "%SRCROOT%", + "uri": "library/src/main/res/values-nb/strings.xml" + }, + "region": { + "startLine": 3, + "startColumn": 13, + "endLine": 3, + "endColumn": 30, + "charOffset": 72, + "charLength": 17, + "snippet": { + "text": "name=\"my_string3\"" + } + }, + "contextRegion": { + "startLine": 1, + "endLine": 6, + "snippet": { + "text": "\n My String\n My String 3\n Extra" + } + } + } + } + ], + "fixes": [ + { + "description": { + "text": "Remove translation" + }, + "artifactChanges": [ + { + "artifactLocation": { + "uriBaseId": "%SRCROOT%", + "uri": "library/src/main/res/values-nb/strings.xml" + }, + "replacements": [ + { + "deletedRegion": { + "startLine": 3, + "startColumn": 2, + "charOffset": 60, + "endLine": 4, + "endColumn": 2, + "charLength": 51 + }, + "insertedContent": { + "text": "\n" + } + } + ] + } + ] + } + ], + "partialFingerprints": { + "sourceContext/v1": "e5abdc0d96209e12" + } + }, + { + "ruleId": "ExtraTranslation", + "ruleIndex": 0, + "message": { + "text": "\"extra\" is translated here but not found in default locale" + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uriBaseId": "%SRCROOT%", + "uri": "library/src/main/res/values-nb/strings.xml" + }, + "region": { + "startLine": 4, + "startColumn": 13, + "endLine": 4, + "endColumn": 25, + "charOffset": 123, + "charLength": 12, + "snippet": { + "text": "name=\"extra\"" + } + }, + "contextRegion": { + "startLine": 2, + "endLine": 7, + "snippet": { + "text": " My String\n My String 3\n Extra\n" + } + } + } + } + ], + "fixes": [ + { + "description": { + "text": "Remove translation" + }, + "artifactChanges": [ + { + "artifactLocation": { + "uriBaseId": "%SRCROOT%", + "uri": "library/src/main/res/values-nb/strings.xml" + }, + "replacements": [ + { + "deletedRegion": { + "startLine": 4, + "startColumn": 2, + "charOffset": 111, + "endLine": 5, + "endColumn": 2, + "charLength": 40 + }, + "insertedContent": { + "text": "\n" + } + } + ] + } + ] + } + ], + "partialFingerprints": { + "sourceContext/v1": "25f1bf2d60354314" + } + }, + { + "ruleId": "UseValueOf", + "ruleIndex": 5, + "message": { + "text": "Use Integer.valueOf(42) instead", + "markdown": "Use `Integer.valueOf(42)` instead" + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uriBaseId": "%SRCROOT%", + "uri": "library/src/main/java/com/android/tools/demo/Test.java" + }, + "region": { + "startLine": 9, + "startColumn": 14, + "endLine": 9, + "endColumn": 29, + "charOffset": 294, + "charLength": 15, + "snippet": { + "text": "new Integer(42)" + } + }, + "contextRegion": { + "startLine": 7, + "endLine": 12, + "snippet": { + "text": " String u = \"/sdcard/path3\"; // not allowed\n String v = \"/sdcard/path4\"; // not allowed\n\tInteger i = new Integer(42);\n\tInteger j = new Integer(43);" + } + } + } + } + ], + "fixes": [ + { + "description": { + "text": "Replace with valueOf()" + }, + "artifactChanges": [ + { + "artifactLocation": { + "uriBaseId": "%SRCROOT%", + "uri": "library/src/main/java/com/android/tools/demo/Test.java" + }, + "replacements": [ + { + "deletedRegion": { + "startLine": 9, + "startColumn": 15, + "charOffset": 294, + "endLine": 9, + "endColumn": 26, + "charLength": 11 + }, + "insertedContent": { + "text": "Integer.valueOf\n" + } + } + ] + } + ] + } + ], + "partialFingerprints": { + "sourceContext/v1": "d2f4a31ec843a711" + } + }, + { + "ruleId": "UseValueOf", + "ruleIndex": 5, + "message": { + "text": "Use Integer.valueOf(43) instead", + "markdown": "Use `Integer.valueOf(43)` instead" + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uriBaseId": "%SRCROOT%", + "uri": "library/src/main/java/com/android/tools/demo/Test.java" + }, + "region": { + "startLine": 10, + "startColumn": 14, + "endLine": 10, + "endColumn": 29, + "charOffset": 324, + "charLength": 15, + "snippet": { + "text": "new Integer(43)" + } + }, + "contextRegion": { + "startLine": 8, + "endLine": 13, + "snippet": { + "text": " String v = \"/sdcard/path4\"; // not allowed\n\tInteger i = new Integer(42);\n\tInteger j = new Integer(43);\n }" + } + } + } + } + ], + "fixes": [ + { + "description": { + "text": "Replace with valueOf()" + }, + "artifactChanges": [ + { + "artifactLocation": { + "uriBaseId": "%SRCROOT%", + "uri": "library/src/main/java/com/android/tools/demo/Test.java" + }, + "replacements": [ + { + "deletedRegion": { + "startLine": 10, + "startColumn": 15, + "charOffset": 324, + "endLine": 10, + "endColumn": 26, + "charLength": 11 + }, + "insertedContent": { + "text": "Integer.valueOf\n" + } + } + ] + } + ] + } + ], + "partialFingerprints": { + "sourceContext/v1": "0048434594d4b6cc" + } + } + ] + } + ] +} diff --git a/android-studio-3/settings.gradle b/settings.gradle similarity index 100% rename from android-studio-3/settings.gradle rename to settings.gradle