mirror of
https://github.com/jlengrand/error-prone-support.git
synced 2026-03-10 15:49:33 +00:00
Compare commits
15 Commits
junie-init
...
workshop
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
90fb015fa0 | ||
|
|
1d457c73e1 | ||
|
|
06aa53e9b9 | ||
|
|
f45899fba8 | ||
|
|
7b8a53ca9b | ||
|
|
e5045b0fdc | ||
|
|
d028146bd6 | ||
|
|
2843f47d67 | ||
|
|
c87db5536d | ||
|
|
561c8caf77 | ||
|
|
a279585a02 | ||
|
|
6312386ce2 | ||
|
|
f1c76411a3 | ||
|
|
f773f6e686 | ||
|
|
fe3e065394 |
@@ -1,3 +1,4 @@
|
|||||||
--batch-mode
|
--batch-mode
|
||||||
--errors
|
--errors
|
||||||
--strict-checksums
|
--strict-checksums
|
||||||
|
-Dstyle.color=always
|
||||||
|
|||||||
BIN
.mvn/wrapper/maven-wrapper.jar
vendored
Normal file
BIN
.mvn/wrapper/maven-wrapper.jar
vendored
Normal file
Binary file not shown.
18
.mvn/wrapper/maven-wrapper.properties
vendored
Normal file
18
.mvn/wrapper/maven-wrapper.properties
vendored
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
# or more contributor license agreements. See the NOTICE file
|
||||||
|
# distributed with this work for additional information
|
||||||
|
# regarding copyright ownership. The ASF licenses this file
|
||||||
|
# to you 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.
|
||||||
|
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.6/apache-maven-3.9.6-bin.zip
|
||||||
|
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar
|
||||||
@@ -313,9 +313,6 @@
|
|||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</path>
|
</path>
|
||||||
</annotationProcessorPaths>
|
</annotationProcessorPaths>
|
||||||
<compilerArgs combine.children="append">
|
|
||||||
<arg>-Xplugin:DocumentationGenerator -XoutputDirectory=${project.build.directory}/docs</arg>
|
|
||||||
</compilerArgs>
|
|
||||||
</configuration>
|
</configuration>
|
||||||
<executions>
|
<executions>
|
||||||
<!-- The Refaster input/output test classes used by
|
<!-- The Refaster input/output test classes used by
|
||||||
|
|||||||
@@ -118,9 +118,6 @@
|
|||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</path>
|
</path>
|
||||||
</annotationProcessorPaths>
|
</annotationProcessorPaths>
|
||||||
<compilerArgs combine.children="append">
|
|
||||||
<arg>-Xplugin:DocumentationGenerator -XoutputDirectory=${project.build.directory}/docs</arg>
|
|
||||||
</compilerArgs>
|
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ additional_source_directories='${project.basedir}${file.separator}src${file.sepa
|
|||||||
shared_error_prone_flags='-XepExcludedPaths:(\Q${project.basedir}${file.separator}src${file.separator}\E(it|test|xdocs-examples)\Q${file.separator}resources\E|\Q${project.build.directory}${file.separator}\E).*'
|
shared_error_prone_flags='-XepExcludedPaths:(\Q${project.basedir}${file.separator}src${file.separator}\E(it|test|xdocs-examples)\Q${file.separator}resources\E|\Q${project.build.directory}${file.separator}\E).*'
|
||||||
patch_error_prone_flags=''
|
patch_error_prone_flags=''
|
||||||
validation_error_prone_flags=''
|
validation_error_prone_flags=''
|
||||||
|
patch_error_prone_flags='-XepOpt:Refaster:NamePattern=.*Workshop.*"'
|
||||||
|
validation_error_prone_flags='-XepOpt:Refaster:NamePattern=.*Workshop.*"'
|
||||||
# Validation skips some tests:
|
# Validation skips some tests:
|
||||||
# - The `metadataFilesGenerationAllFiles` test is skipped because it makes line
|
# - The `metadataFilesGenerationAllFiles` test is skipped because it makes line
|
||||||
# number assertions that will fail when the code is formatted or patched.
|
# number assertions that will fail when the code is formatted or patched.
|
||||||
|
|||||||
308
mvnw
vendored
Executable file
308
mvnw
vendored
Executable file
@@ -0,0 +1,308 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
# Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
# or more contributor license agreements. See the NOTICE file
|
||||||
|
# distributed with this work for additional information
|
||||||
|
# regarding copyright ownership. The ASF licenses this file
|
||||||
|
# to you 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.
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
# Apache Maven Wrapper startup batch script, version 3.2.0
|
||||||
|
#
|
||||||
|
# Required ENV vars:
|
||||||
|
# ------------------
|
||||||
|
# JAVA_HOME - location of a JDK home dir
|
||||||
|
#
|
||||||
|
# Optional ENV vars
|
||||||
|
# -----------------
|
||||||
|
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||||
|
# e.g. to debug Maven itself, use
|
||||||
|
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||||
|
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
if [ -z "$MAVEN_SKIP_RC" ] ; then
|
||||||
|
|
||||||
|
if [ -f /usr/local/etc/mavenrc ] ; then
|
||||||
|
. /usr/local/etc/mavenrc
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f /etc/mavenrc ] ; then
|
||||||
|
. /etc/mavenrc
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f "$HOME/.mavenrc" ] ; then
|
||||||
|
. "$HOME/.mavenrc"
|
||||||
|
fi
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
# OS specific support. $var _must_ be set to either true or false.
|
||||||
|
cygwin=false;
|
||||||
|
darwin=false;
|
||||||
|
mingw=false
|
||||||
|
case "$(uname)" in
|
||||||
|
CYGWIN*) cygwin=true ;;
|
||||||
|
MINGW*) mingw=true;;
|
||||||
|
Darwin*) darwin=true
|
||||||
|
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
|
||||||
|
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
|
||||||
|
if [ -z "$JAVA_HOME" ]; then
|
||||||
|
if [ -x "/usr/libexec/java_home" ]; then
|
||||||
|
JAVA_HOME="$(/usr/libexec/java_home)"; export JAVA_HOME
|
||||||
|
else
|
||||||
|
JAVA_HOME="/Library/Java/Home"; export JAVA_HOME
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [ -z "$JAVA_HOME" ] ; then
|
||||||
|
if [ -r /etc/gentoo-release ] ; then
|
||||||
|
JAVA_HOME=$(java-config --jre-home)
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Cygwin, ensure paths are in UNIX format before anything is touched
|
||||||
|
if $cygwin ; then
|
||||||
|
[ -n "$JAVA_HOME" ] &&
|
||||||
|
JAVA_HOME=$(cygpath --unix "$JAVA_HOME")
|
||||||
|
[ -n "$CLASSPATH" ] &&
|
||||||
|
CLASSPATH=$(cygpath --path --unix "$CLASSPATH")
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Mingw, ensure paths are in UNIX format before anything is touched
|
||||||
|
if $mingw ; then
|
||||||
|
[ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] &&
|
||||||
|
JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); pwd)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$JAVA_HOME" ]; then
|
||||||
|
javaExecutable="$(which javac)"
|
||||||
|
if [ -n "$javaExecutable" ] && ! [ "$(expr "\"$javaExecutable\"" : '\([^ ]*\)')" = "no" ]; then
|
||||||
|
# readlink(1) is not available as standard on Solaris 10.
|
||||||
|
readLink=$(which readlink)
|
||||||
|
if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then
|
||||||
|
if $darwin ; then
|
||||||
|
javaHome="$(dirname "\"$javaExecutable\"")"
|
||||||
|
javaExecutable="$(cd "\"$javaHome\"" && pwd -P)/javac"
|
||||||
|
else
|
||||||
|
javaExecutable="$(readlink -f "\"$javaExecutable\"")"
|
||||||
|
fi
|
||||||
|
javaHome="$(dirname "\"$javaExecutable\"")"
|
||||||
|
javaHome=$(expr "$javaHome" : '\(.*\)/bin')
|
||||||
|
JAVA_HOME="$javaHome"
|
||||||
|
export JAVA_HOME
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$JAVACMD" ] ; then
|
||||||
|
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
|
||||||
|
else
|
||||||
|
JAVACMD="$(\unset -f command 2>/dev/null; \command -v java)"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -x "$JAVACMD" ] ; then
|
||||||
|
echo "Error: JAVA_HOME is not defined correctly." >&2
|
||||||
|
echo " We cannot execute $JAVACMD" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$JAVA_HOME" ] ; then
|
||||||
|
echo "Warning: JAVA_HOME environment variable is not set."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# traverses directory structure from process work directory to filesystem root
|
||||||
|
# first directory with .mvn subdirectory is considered project base directory
|
||||||
|
find_maven_basedir() {
|
||||||
|
if [ -z "$1" ]
|
||||||
|
then
|
||||||
|
echo "Path not specified to find_maven_basedir"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
basedir="$1"
|
||||||
|
wdir="$1"
|
||||||
|
while [ "$wdir" != '/' ] ; do
|
||||||
|
if [ -d "$wdir"/.mvn ] ; then
|
||||||
|
basedir=$wdir
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
|
||||||
|
if [ -d "${wdir}" ]; then
|
||||||
|
wdir=$(cd "$wdir/.." || exit 1; pwd)
|
||||||
|
fi
|
||||||
|
# end of workaround
|
||||||
|
done
|
||||||
|
printf '%s' "$(cd "$basedir" || exit 1; pwd)"
|
||||||
|
}
|
||||||
|
|
||||||
|
# concatenates all lines of a file
|
||||||
|
concat_lines() {
|
||||||
|
if [ -f "$1" ]; then
|
||||||
|
# Remove \r in case we run on Windows within Git Bash
|
||||||
|
# and check out the repository with auto CRLF management
|
||||||
|
# enabled. Otherwise, we may read lines that are delimited with
|
||||||
|
# \r\n and produce $'-Xarg\r' rather than -Xarg due to word
|
||||||
|
# splitting rules.
|
||||||
|
tr -s '\r\n' ' ' < "$1"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
log() {
|
||||||
|
if [ "$MVNW_VERBOSE" = true ]; then
|
||||||
|
printf '%s\n' "$1"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
BASE_DIR=$(find_maven_basedir "$(dirname "$0")")
|
||||||
|
if [ -z "$BASE_DIR" ]; then
|
||||||
|
exit 1;
|
||||||
|
fi
|
||||||
|
|
||||||
|
MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR
|
||||||
|
log "$MAVEN_PROJECTBASEDIR"
|
||||||
|
|
||||||
|
##########################################################################################
|
||||||
|
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
|
||||||
|
# This allows using the maven wrapper in projects that prohibit checking in binary data.
|
||||||
|
##########################################################################################
|
||||||
|
wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar"
|
||||||
|
if [ -r "$wrapperJarPath" ]; then
|
||||||
|
log "Found $wrapperJarPath"
|
||||||
|
else
|
||||||
|
log "Couldn't find $wrapperJarPath, downloading it ..."
|
||||||
|
|
||||||
|
if [ -n "$MVNW_REPOURL" ]; then
|
||||||
|
wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
|
||||||
|
else
|
||||||
|
wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
|
||||||
|
fi
|
||||||
|
while IFS="=" read -r key value; do
|
||||||
|
# Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' )
|
||||||
|
safeValue=$(echo "$value" | tr -d '\r')
|
||||||
|
case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;;
|
||||||
|
esac
|
||||||
|
done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
|
||||||
|
log "Downloading from: $wrapperUrl"
|
||||||
|
|
||||||
|
if $cygwin; then
|
||||||
|
wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath")
|
||||||
|
fi
|
||||||
|
|
||||||
|
if command -v wget > /dev/null; then
|
||||||
|
log "Found wget ... using wget"
|
||||||
|
[ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet"
|
||||||
|
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
|
||||||
|
wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
|
||||||
|
else
|
||||||
|
wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
|
||||||
|
fi
|
||||||
|
elif command -v curl > /dev/null; then
|
||||||
|
log "Found curl ... using curl"
|
||||||
|
[ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent"
|
||||||
|
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
|
||||||
|
curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
|
||||||
|
else
|
||||||
|
curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
log "Falling back to using Java to download"
|
||||||
|
javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java"
|
||||||
|
javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class"
|
||||||
|
# For Cygwin, switch paths to Windows format before running javac
|
||||||
|
if $cygwin; then
|
||||||
|
javaSource=$(cygpath --path --windows "$javaSource")
|
||||||
|
javaClass=$(cygpath --path --windows "$javaClass")
|
||||||
|
fi
|
||||||
|
if [ -e "$javaSource" ]; then
|
||||||
|
if [ ! -e "$javaClass" ]; then
|
||||||
|
log " - Compiling MavenWrapperDownloader.java ..."
|
||||||
|
("$JAVA_HOME/bin/javac" "$javaSource")
|
||||||
|
fi
|
||||||
|
if [ -e "$javaClass" ]; then
|
||||||
|
log " - Running MavenWrapperDownloader.java ..."
|
||||||
|
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
##########################################################################################
|
||||||
|
# End of extension
|
||||||
|
##########################################################################################
|
||||||
|
|
||||||
|
# If specified, validate the SHA-256 sum of the Maven wrapper jar file
|
||||||
|
wrapperSha256Sum=""
|
||||||
|
while IFS="=" read -r key value; do
|
||||||
|
case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;;
|
||||||
|
esac
|
||||||
|
done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
|
||||||
|
if [ -n "$wrapperSha256Sum" ]; then
|
||||||
|
wrapperSha256Result=false
|
||||||
|
if command -v sha256sum > /dev/null; then
|
||||||
|
if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c > /dev/null 2>&1; then
|
||||||
|
wrapperSha256Result=true
|
||||||
|
fi
|
||||||
|
elif command -v shasum > /dev/null; then
|
||||||
|
if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c > /dev/null 2>&1; then
|
||||||
|
wrapperSha256Result=true
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available."
|
||||||
|
echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [ $wrapperSha256Result = false ]; then
|
||||||
|
echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2
|
||||||
|
echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2
|
||||||
|
echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
|
||||||
|
|
||||||
|
# For Cygwin, switch paths to Windows format before running java
|
||||||
|
if $cygwin; then
|
||||||
|
[ -n "$JAVA_HOME" ] &&
|
||||||
|
JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME")
|
||||||
|
[ -n "$CLASSPATH" ] &&
|
||||||
|
CLASSPATH=$(cygpath --path --windows "$CLASSPATH")
|
||||||
|
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
|
||||||
|
MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR")
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Provide a "standardized" way to retrieve the CLI args that will
|
||||||
|
# work with both Windows and non-Windows executions.
|
||||||
|
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*"
|
||||||
|
export MAVEN_CMD_LINE_ARGS
|
||||||
|
|
||||||
|
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||||
|
|
||||||
|
# shellcheck disable=SC2086 # safe args
|
||||||
|
exec "$JAVACMD" \
|
||||||
|
$MAVEN_OPTS \
|
||||||
|
$MAVEN_DEBUG_OPTS \
|
||||||
|
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
|
||||||
|
"-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
|
||||||
|
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
|
||||||
205
mvnw.cmd
vendored
Normal file
205
mvnw.cmd
vendored
Normal file
@@ -0,0 +1,205 @@
|
|||||||
|
@REM ----------------------------------------------------------------------------
|
||||||
|
@REM Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
@REM or more contributor license agreements. See the NOTICE file
|
||||||
|
@REM distributed with this work for additional information
|
||||||
|
@REM regarding copyright ownership. The ASF licenses this file
|
||||||
|
@REM to you under the Apache License, Version 2.0 (the
|
||||||
|
@REM "License"); you may not use this file except in compliance
|
||||||
|
@REM with the License. You may obtain a copy of the License at
|
||||||
|
@REM
|
||||||
|
@REM http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
@REM
|
||||||
|
@REM Unless required by applicable law or agreed to in writing,
|
||||||
|
@REM software distributed under the License is distributed on an
|
||||||
|
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
@REM KIND, either express or implied. See the License for the
|
||||||
|
@REM specific language governing permissions and limitations
|
||||||
|
@REM under the License.
|
||||||
|
@REM ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@REM ----------------------------------------------------------------------------
|
||||||
|
@REM Apache Maven Wrapper startup batch script, version 3.2.0
|
||||||
|
@REM
|
||||||
|
@REM Required ENV vars:
|
||||||
|
@REM JAVA_HOME - location of a JDK home dir
|
||||||
|
@REM
|
||||||
|
@REM Optional ENV vars
|
||||||
|
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
|
||||||
|
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
|
||||||
|
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||||
|
@REM e.g. to debug Maven itself, use
|
||||||
|
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||||
|
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
||||||
|
@REM ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
|
||||||
|
@echo off
|
||||||
|
@REM set title of command window
|
||||||
|
title %0
|
||||||
|
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
|
||||||
|
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
|
||||||
|
|
||||||
|
@REM set %HOME% to equivalent of $HOME
|
||||||
|
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
|
||||||
|
|
||||||
|
@REM Execute a user defined script before this one
|
||||||
|
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
|
||||||
|
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
|
||||||
|
if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
|
||||||
|
if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
|
||||||
|
:skipRcPre
|
||||||
|
|
||||||
|
@setlocal
|
||||||
|
|
||||||
|
set ERROR_CODE=0
|
||||||
|
|
||||||
|
@REM To isolate internal variables from possible post scripts, we use another setlocal
|
||||||
|
@setlocal
|
||||||
|
|
||||||
|
@REM ==== START VALIDATION ====
|
||||||
|
if not "%JAVA_HOME%" == "" goto OkJHome
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo Error: JAVA_HOME not found in your environment. >&2
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||||
|
echo location of your Java installation. >&2
|
||||||
|
echo.
|
||||||
|
goto error
|
||||||
|
|
||||||
|
:OkJHome
|
||||||
|
if exist "%JAVA_HOME%\bin\java.exe" goto init
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo Error: JAVA_HOME is set to an invalid directory. >&2
|
||||||
|
echo JAVA_HOME = "%JAVA_HOME%" >&2
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||||
|
echo location of your Java installation. >&2
|
||||||
|
echo.
|
||||||
|
goto error
|
||||||
|
|
||||||
|
@REM ==== END VALIDATION ====
|
||||||
|
|
||||||
|
:init
|
||||||
|
|
||||||
|
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
|
||||||
|
@REM Fallback to current working directory if not found.
|
||||||
|
|
||||||
|
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
|
||||||
|
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
|
||||||
|
|
||||||
|
set EXEC_DIR=%CD%
|
||||||
|
set WDIR=%EXEC_DIR%
|
||||||
|
:findBaseDir
|
||||||
|
IF EXIST "%WDIR%"\.mvn goto baseDirFound
|
||||||
|
cd ..
|
||||||
|
IF "%WDIR%"=="%CD%" goto baseDirNotFound
|
||||||
|
set WDIR=%CD%
|
||||||
|
goto findBaseDir
|
||||||
|
|
||||||
|
:baseDirFound
|
||||||
|
set MAVEN_PROJECTBASEDIR=%WDIR%
|
||||||
|
cd "%EXEC_DIR%"
|
||||||
|
goto endDetectBaseDir
|
||||||
|
|
||||||
|
:baseDirNotFound
|
||||||
|
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
|
||||||
|
cd "%EXEC_DIR%"
|
||||||
|
|
||||||
|
:endDetectBaseDir
|
||||||
|
|
||||||
|
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
|
||||||
|
|
||||||
|
@setlocal EnableExtensions EnableDelayedExpansion
|
||||||
|
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
|
||||||
|
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
|
||||||
|
|
||||||
|
:endReadAdditionalConfig
|
||||||
|
|
||||||
|
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
|
||||||
|
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
|
||||||
|
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||||
|
|
||||||
|
set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
|
||||||
|
|
||||||
|
FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
|
||||||
|
IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B
|
||||||
|
)
|
||||||
|
|
||||||
|
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
|
||||||
|
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
|
||||||
|
if exist %WRAPPER_JAR% (
|
||||||
|
if "%MVNW_VERBOSE%" == "true" (
|
||||||
|
echo Found %WRAPPER_JAR%
|
||||||
|
)
|
||||||
|
) else (
|
||||||
|
if not "%MVNW_REPOURL%" == "" (
|
||||||
|
SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
|
||||||
|
)
|
||||||
|
if "%MVNW_VERBOSE%" == "true" (
|
||||||
|
echo Couldn't find %WRAPPER_JAR%, downloading it ...
|
||||||
|
echo Downloading from: %WRAPPER_URL%
|
||||||
|
)
|
||||||
|
|
||||||
|
powershell -Command "&{"^
|
||||||
|
"$webclient = new-object System.Net.WebClient;"^
|
||||||
|
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
|
||||||
|
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
|
||||||
|
"}"^
|
||||||
|
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^
|
||||||
|
"}"
|
||||||
|
if "%MVNW_VERBOSE%" == "true" (
|
||||||
|
echo Finished downloading %WRAPPER_JAR%
|
||||||
|
)
|
||||||
|
)
|
||||||
|
@REM End of extension
|
||||||
|
|
||||||
|
@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file
|
||||||
|
SET WRAPPER_SHA_256_SUM=""
|
||||||
|
FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
|
||||||
|
IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B
|
||||||
|
)
|
||||||
|
IF NOT %WRAPPER_SHA_256_SUM%=="" (
|
||||||
|
powershell -Command "&{"^
|
||||||
|
"$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^
|
||||||
|
"If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^
|
||||||
|
" Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^
|
||||||
|
" Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^
|
||||||
|
" Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^
|
||||||
|
" exit 1;"^
|
||||||
|
"}"^
|
||||||
|
"}"
|
||||||
|
if ERRORLEVEL 1 goto error
|
||||||
|
)
|
||||||
|
|
||||||
|
@REM Provide a "standardized" way to retrieve the CLI args that will
|
||||||
|
@REM work with both Windows and non-Windows executions.
|
||||||
|
set MAVEN_CMD_LINE_ARGS=%*
|
||||||
|
|
||||||
|
%MAVEN_JAVA_EXE% ^
|
||||||
|
%JVM_CONFIG_MAVEN_PROPS% ^
|
||||||
|
%MAVEN_OPTS% ^
|
||||||
|
%MAVEN_DEBUG_OPTS% ^
|
||||||
|
-classpath %WRAPPER_JAR% ^
|
||||||
|
"-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
|
||||||
|
%WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
|
||||||
|
if ERRORLEVEL 1 goto error
|
||||||
|
goto end
|
||||||
|
|
||||||
|
:error
|
||||||
|
set ERROR_CODE=1
|
||||||
|
|
||||||
|
:end
|
||||||
|
@endlocal & set ERROR_CODE=%ERROR_CODE%
|
||||||
|
|
||||||
|
if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
|
||||||
|
@REM check for post script, once with legacy .bat ending and once with .cmd ending
|
||||||
|
if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
|
||||||
|
if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
|
||||||
|
:skipRcPost
|
||||||
|
|
||||||
|
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
|
||||||
|
if "%MAVEN_BATCH_PAUSE%"=="on" pause
|
||||||
|
|
||||||
|
if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
|
||||||
|
|
||||||
|
cmd /C exit /B %ERROR_CODE%
|
||||||
106
pom.xml
106
pom.xml
@@ -48,6 +48,7 @@
|
|||||||
<module>refaster-runner</module>
|
<module>refaster-runner</module>
|
||||||
<module>refaster-support</module>
|
<module>refaster-support</module>
|
||||||
<module>refaster-test-support</module>
|
<module>refaster-test-support</module>
|
||||||
|
<module>workshop</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
<scm child.scm.developerConnection.inherit.append.path="false" child.scm.url.inherit.append.path="false">
|
<scm child.scm.developerConnection.inherit.append.path="false" child.scm.url.inherit.append.path="false">
|
||||||
@@ -434,14 +435,6 @@
|
|||||||
<artifactId>byte-buddy</artifactId>
|
<artifactId>byte-buddy</artifactId>
|
||||||
<version>1.17.5</version>
|
<version>1.17.5</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- Specified so that Renovate will file Maven upgrade PRs, which
|
|
||||||
subsequently will cause `maven-enforcer-plugin` to require that
|
|
||||||
developers build the project using the latest Maven release. -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.maven</groupId>
|
|
||||||
<artifactId>maven-plugin-api</artifactId>
|
|
||||||
<version>${version.maven}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.aspectj</groupId>
|
<groupId>org.aspectj</groupId>
|
||||||
<artifactId>aspectjweaver</artifactId>
|
<artifactId>aspectjweaver</artifactId>
|
||||||
@@ -1134,9 +1127,6 @@
|
|||||||
<requireMatchingCoordinates>
|
<requireMatchingCoordinates>
|
||||||
<moduleNameMustMatchArtifactId>true</moduleNameMustMatchArtifactId>
|
<moduleNameMustMatchArtifactId>true</moduleNameMustMatchArtifactId>
|
||||||
</requireMatchingCoordinates>
|
</requireMatchingCoordinates>
|
||||||
<requireMavenVersion>
|
|
||||||
<version>${version.maven}</version>
|
|
||||||
</requireMavenVersion>
|
|
||||||
<requireNoRepositories />
|
<requireNoRepositories />
|
||||||
<requirePluginVersions />
|
<requirePluginVersions />
|
||||||
<requireUpperBoundDeps />
|
<requireUpperBoundDeps />
|
||||||
@@ -1473,37 +1463,6 @@
|
|||||||
<updateBuildOutputTimestampPolicy>never</updateBuildOutputTimestampPolicy>
|
<updateBuildOutputTimestampPolicy>never</updateBuildOutputTimestampPolicy>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
<plugin>
|
|
||||||
<groupId>org.gaul</groupId>
|
|
||||||
<artifactId>modernizer-maven-plugin</artifactId>
|
|
||||||
<version>3.1.0</version>
|
|
||||||
<configuration>
|
|
||||||
<exclusionPatterns>
|
|
||||||
<!-- The plugin suggests replacing usages of
|
|
||||||
Guava's `Iterables` class with
|
|
||||||
`java.util.stream.Stream` equivalents, but the
|
|
||||||
alternative is often more verbose, requiring
|
|
||||||
unnecessary conversions to and from streams. -->
|
|
||||||
<exclusionPattern>com/google/common/collect/Iterables\..*</exclusionPattern>
|
|
||||||
</exclusionPatterns>
|
|
||||||
<failOnViolations>false</failOnViolations>
|
|
||||||
<ignorePackages>
|
|
||||||
<!-- Some Refaster rules purposefully use outdated
|
|
||||||
patterns in their `@BeforeTemplate` methods. -->
|
|
||||||
<ignorePackage>tech.picnic.errorprone.refasterrules</ignorePackage>
|
|
||||||
</ignorePackages>
|
|
||||||
<javaVersion>${version.jdk}</javaVersion>
|
|
||||||
</configuration>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>run-modernizer</id>
|
|
||||||
<goals>
|
|
||||||
<goal>modernizer</goal>
|
|
||||||
</goals>
|
|
||||||
<phase>process-test-classes</phase>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.jacoco</groupId>
|
<groupId>org.jacoco</groupId>
|
||||||
<artifactId>jacoco-maven-plugin</artifactId>
|
<artifactId>jacoco-maven-plugin</artifactId>
|
||||||
@@ -1516,24 +1475,6 @@
|
|||||||
</excludes>
|
</excludes>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
<plugin>
|
|
||||||
<groupId>org.kordamp.maven</groupId>
|
|
||||||
<artifactId>pomchecker-maven-plugin</artifactId>
|
|
||||||
<version>1.14.0</version>
|
|
||||||
<configuration>
|
|
||||||
<failOnError>false</failOnError>
|
|
||||||
<release>false</release>
|
|
||||||
</configuration>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>check-maven-central-compliance</id>
|
|
||||||
<goals>
|
|
||||||
<goal>check-maven-central</goal>
|
|
||||||
</goals>
|
|
||||||
<phase>verify</phase>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.pitest</groupId>
|
<groupId>org.pitest</groupId>
|
||||||
<artifactId>pitest-maven</artifactId>
|
<artifactId>pitest-maven</artifactId>
|
||||||
@@ -1712,11 +1653,6 @@
|
|||||||
profile. Necessary for dealing with plugins that default to failing
|
profile. Necessary for dealing with plugins that default to failing
|
||||||
the build upon encountering a violation. -->
|
the build upon encountering a violation. -->
|
||||||
<id>avoid-errors</id>
|
<id>avoid-errors</id>
|
||||||
<activation>
|
|
||||||
<property>
|
|
||||||
<name>verification.warn</name>
|
|
||||||
</property>
|
|
||||||
</activation>
|
|
||||||
<build>
|
<build>
|
||||||
<pluginManagement>
|
<pluginManagement>
|
||||||
<plugins>
|
<plugins>
|
||||||
@@ -1737,11 +1673,6 @@
|
|||||||
that they can be disabled during development. See also the
|
that they can be disabled during development. See also the
|
||||||
`error-prone` profile defined below. -->
|
`error-prone` profile defined below. -->
|
||||||
<id>build-checks</id>
|
<id>build-checks</id>
|
||||||
<activation>
|
|
||||||
<property>
|
|
||||||
<name>!verification.skip</name>
|
|
||||||
</property>
|
|
||||||
</activation>
|
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
@@ -1833,14 +1764,6 @@
|
|||||||
<groupId>org.codehaus.mojo</groupId>
|
<groupId>org.codehaus.mojo</groupId>
|
||||||
<artifactId>tidy-maven-plugin</artifactId>
|
<artifactId>tidy-maven-plugin</artifactId>
|
||||||
</plugin>
|
</plugin>
|
||||||
<plugin>
|
|
||||||
<groupId>org.gaul</groupId>
|
|
||||||
<artifactId>modernizer-maven-plugin</artifactId>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.kordamp.maven</groupId>
|
|
||||||
<artifactId>pomchecker-maven-plugin</artifactId>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
</profile>
|
</profile>
|
||||||
@@ -1997,11 +1920,6 @@
|
|||||||
This profile allows one to collect all violations without failing
|
This profile allows one to collect all violations without failing
|
||||||
the build. -->
|
the build. -->
|
||||||
<id>disallow-warnings</id>
|
<id>disallow-warnings</id>
|
||||||
<activation>
|
|
||||||
<property>
|
|
||||||
<name>!verification.warn</name>
|
|
||||||
</property>
|
|
||||||
</activation>
|
|
||||||
<build>
|
<build>
|
||||||
<pluginManagement>
|
<pluginManagement>
|
||||||
<plugins>
|
<plugins>
|
||||||
@@ -2070,21 +1988,6 @@
|
|||||||
<failOnMissing>true</failOnMissing>
|
<failOnMissing>true</failOnMissing>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
<plugin>
|
|
||||||
<groupId>org.gaul</groupId>
|
|
||||||
<artifactId>modernizer-maven-plugin</artifactId>
|
|
||||||
<configuration>
|
|
||||||
<failOnViolations>true</failOnViolations>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.kordamp.maven</groupId>
|
|
||||||
<artifactId>pomchecker-maven-plugin</artifactId>
|
|
||||||
<configuration>
|
|
||||||
<failOnError>true</failOnError>
|
|
||||||
<failOnWarning>true</failOnWarning>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
</plugins>
|
||||||
</pluginManagement>
|
</pluginManagement>
|
||||||
</build>
|
</build>
|
||||||
@@ -2156,13 +2059,6 @@
|
|||||||
<artifactId>maven-gpg-plugin</artifactId>
|
<artifactId>maven-gpg-plugin</artifactId>
|
||||||
</plugin>
|
</plugin>
|
||||||
<?SORTPOM RESUME?>
|
<?SORTPOM RESUME?>
|
||||||
<plugin>
|
|
||||||
<groupId>org.kordamp.maven</groupId>
|
|
||||||
<artifactId>pomchecker-maven-plugin</artifactId>
|
|
||||||
<configuration>
|
|
||||||
<release>true</release>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
</profile>
|
</profile>
|
||||||
|
|||||||
104
workshop/README.md
Normal file
104
workshop/README.md
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
# Error Prone Workshop
|
||||||
|
|
||||||
|
Download the slides [here][eps-workshop-slides].
|
||||||
|
|
||||||
|
## Initial setup of the workshop
|
||||||
|
|
||||||
|
1. Start by cloning this repository locally from GitHub.
|
||||||
|
2. Checkout the `workshop` branch.
|
||||||
|
3. Make sure to run `mvn clean install` in the root of this repository.
|
||||||
|
4. Open your code editor and familiarize yourself with the project structure.
|
||||||
|
|
||||||
|
In IntelliJ IDEA (or your preferred editor), try to run the
|
||||||
|
`WorkshopRefasterRulesTest` test. You might see the following error:
|
||||||
|
|
||||||
|
```
|
||||||
|
java: exporting a package from system module jdk.compiler is not allowed with --release
|
||||||
|
```
|
||||||
|
|
||||||
|
If this happens, go to _File -> Settings... -> Build, Execution, Deployment ->
|
||||||
|
Compiler -> Java Compiler_ and deselect the option _Use '--release' option for
|
||||||
|
cross-compilation (Java 9 and later)_.
|
||||||
|
|
||||||
|
If you encounter any other bugs when running `mvn clean install`, make sure you
|
||||||
|
are using a recent release of JDK 17.
|
||||||
|
|
||||||
|
Now the project is ready for the workshop.
|
||||||
|
|
||||||
|
## Part 1: Writing Refaster rules
|
||||||
|
|
||||||
|
During this part of the workshop we will implement multiple Refaster rules.
|
||||||
|
|
||||||
|
Go to the `workshop` module and navigate to the
|
||||||
|
`tech.picnic.errorprone.workshop.refasterrules` package. There you can find one
|
||||||
|
example and five different exercises to do. Make sure to open the
|
||||||
|
`WorkshopRefasterRulesTest` class where you can enable tests. Per assignment
|
||||||
|
there is a test in this class that you can enable (by dropping the `@Disabled`
|
||||||
|
annotation) to validate your changes. The goal is to implement or improve the
|
||||||
|
Refaster rules such that the enabled tests pass.
|
||||||
|
|
||||||
|
Tips:
|
||||||
|
|
||||||
|
* Go through the exercises in the proposed order.
|
||||||
|
* The `XXX:` comments explain what needs to happen.
|
||||||
|
* Find the test case for each Refaster rule by looking for the name of the
|
||||||
|
Refaster rule, prefixed with `test`. For example, the
|
||||||
|
`WorkshopAssignment0Rules.java` rule collection has a Refaster rule named
|
||||||
|
`ExampleStringIsEmpty`. In the `WorkshopAssignment0RulesTestInput.java` and
|
||||||
|
`WorkshopAssignment0RulesTestOutput.java` files there is a
|
||||||
|
`testExampleStringIsEmpty` method that shows the input and output to test the
|
||||||
|
Refaster rule.
|
||||||
|
|
||||||
|
## Part 2: Writing Error Prone checks
|
||||||
|
|
||||||
|
During this part of the workshop we will implement parts of multiple Error
|
||||||
|
Prone `BugChecker`s. Each of these classes contain `XXX` comments explaining
|
||||||
|
what needs to be implemented. However, before diving in, make sure to first
|
||||||
|
navigate to a check's associated test class to drop the class-level `@Disabled`
|
||||||
|
annotation. Upon initial execution the tests will fail; the goal is to get then
|
||||||
|
to pass.
|
||||||
|
|
||||||
|
Some utility classes that you can use:
|
||||||
|
|
||||||
|
* `com.google.errorprone.util.ASTHelpers`: contains many common operations on
|
||||||
|
the Abstract Syntax Tree.
|
||||||
|
* `com.google.errorprone.fixes.SuggestedFixes`: contains helper methods for
|
||||||
|
creating `Fix`es.
|
||||||
|
|
||||||
|
### Tips and tricks
|
||||||
|
|
||||||
|
If you are working from the command line, it is suggested to run commands in
|
||||||
|
the `workshop` directory. To do this, navigate to the root of the repository
|
||||||
|
and run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd workshop
|
||||||
|
```
|
||||||
|
|
||||||
|
In case you want to do a fast build to just compile the project, run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mvn clean install -DskipTests -Dverification.skip
|
||||||
|
```
|
||||||
|
|
||||||
|
In case you want to run one test from the command line, run the following
|
||||||
|
commands:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mvn clean install -Dtest=WorkshopRefasterRulesTest -Dverification.skip
|
||||||
|
```
|
||||||
|
|
||||||
|
### Troubleshooting
|
||||||
|
|
||||||
|
Make sure to use the latest version of JDK 21 or 17.
|
||||||
|
|
||||||
|
In some specific cases the `-Dverification.skip` is not correctly processed. In
|
||||||
|
that case, use `-D"verification.skip"`.
|
||||||
|
|
||||||
|
In case there is an error mentioning the `BetaApi` check, please rebuild or try
|
||||||
|
to `Reload All Maven projects`.
|
||||||
|
|
||||||
|
|
||||||
|
[eps-github]: https://github.com/PicnicSupermarket/error-prone-support
|
||||||
|
|
||||||
|
[eps-workshop-slides]: https://docs.google.com/presentation/d/16MnDk6eW5dxKrLfG7TNUKAX-UVDJwbMz55UvKUkzeHc/edit?usp=sharing
|
||||||
155
workshop/pom.xml
Normal file
155
workshop/pom.xml
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>tech.picnic.error-prone-support</groupId>
|
||||||
|
<artifactId>error-prone-support</artifactId>
|
||||||
|
<version>0.22.1-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>workshop</artifactId>
|
||||||
|
|
||||||
|
<name>Picnic :: Error Prone Support :: Workshop</name>
|
||||||
|
<description>Project for the Error Prone Workshop.</description>
|
||||||
|
<url>https://error-prone.picnic.tech</url>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.errorprone</groupId>
|
||||||
|
<artifactId>error_prone_annotation</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.errorprone</groupId>
|
||||||
|
<artifactId>error_prone_annotations</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.errorprone</groupId>
|
||||||
|
<artifactId>error_prone_check_api</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.errorprone</groupId>
|
||||||
|
<artifactId>error_prone_core</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.errorprone</groupId>
|
||||||
|
<artifactId>error_prone_test_helpers</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>${project.groupId}</groupId>
|
||||||
|
<artifactId>error-prone-utils</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>${project.groupId}</groupId>
|
||||||
|
<artifactId>refaster-compiler</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>${project.groupId}</groupId>
|
||||||
|
<artifactId>refaster-support</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>${project.groupId}</groupId>
|
||||||
|
<artifactId>refaster-test-support</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.auto.service</groupId>
|
||||||
|
<artifactId>auto-service-annotations</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.guava</groupId>
|
||||||
|
<artifactId>guava</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>javax.annotation</groupId>
|
||||||
|
<artifactId>javax.annotation-api</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.aspectj</groupId>
|
||||||
|
<artifactId>aspectjweaver</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.assertj</groupId>
|
||||||
|
<artifactId>assertj-core</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
<artifactId>junit-jupiter-api</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
<artifactId>junit-jupiter-params</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mockito</groupId>
|
||||||
|
<artifactId>mockito-core</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.openrewrite</groupId>
|
||||||
|
<artifactId>rewrite-core</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.openrewrite</groupId>
|
||||||
|
<artifactId>rewrite-java</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.openrewrite</groupId>
|
||||||
|
<artifactId>rewrite-java-11</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.openrewrite</groupId>
|
||||||
|
<artifactId>rewrite-templating</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework</groupId>
|
||||||
|
<artifactId>spring-context</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<pluginManagement>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<annotationProcessorPaths combine.children="append">
|
||||||
|
<path>
|
||||||
|
<groupId>${project.groupId}</groupId>
|
||||||
|
<artifactId>refaster-compiler</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</path>
|
||||||
|
<path>
|
||||||
|
<groupId>${project.groupId}</groupId>
|
||||||
|
<artifactId>refaster-support</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</path>
|
||||||
|
</annotationProcessorPaths>
|
||||||
|
<compilerArgs combine.children="append">
|
||||||
|
<arg>-Xplugin:RefasterRuleCompiler</arg>
|
||||||
|
</compilerArgs>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</pluginManagement>
|
||||||
|
</build>
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package tech.picnic.errorprone.workshop.bugpatterns;
|
||||||
|
|
||||||
|
import static com.google.errorprone.BugPattern.SeverityLevel.WARNING;
|
||||||
|
import static com.google.errorprone.BugPattern.StandardTags.SIMPLIFICATION;
|
||||||
|
|
||||||
|
import com.google.auto.service.AutoService;
|
||||||
|
import com.google.errorprone.BugPattern;
|
||||||
|
import com.google.errorprone.VisitorState;
|
||||||
|
import com.google.errorprone.bugpatterns.BugChecker;
|
||||||
|
import com.google.errorprone.bugpatterns.BugChecker.MethodTreeMatcher;
|
||||||
|
import com.google.errorprone.matchers.Description;
|
||||||
|
import com.sun.source.tree.MethodTree;
|
||||||
|
|
||||||
|
/** A {@link BugChecker} that flags empty methods that seemingly can simply be deleted. */
|
||||||
|
@AutoService(BugChecker.class)
|
||||||
|
@BugPattern(
|
||||||
|
summary = "Empty method can likely be deleted",
|
||||||
|
severity = WARNING,
|
||||||
|
tags = SIMPLIFICATION)
|
||||||
|
public final class Assignment0DeleteEmptyMethod extends BugChecker implements MethodTreeMatcher {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/** Instantiates a new {@link Assignment0DeleteEmptyMethod} instance. */
|
||||||
|
public Assignment0DeleteEmptyMethod() {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Description matchMethod(MethodTree tree, VisitorState state) {
|
||||||
|
// XXX: Part 1: Ensure that we only delete methods that contain no statements.
|
||||||
|
// XXX: Part 2: Don't delete methods that are annotated with `@Override`.
|
||||||
|
|
||||||
|
return Description.NO_MATCH;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
package tech.picnic.errorprone.workshop.bugpatterns;
|
||||||
|
|
||||||
|
import static com.google.errorprone.BugPattern.SeverityLevel.SUGGESTION;
|
||||||
|
import static com.google.errorprone.BugPattern.StandardTags.SIMPLIFICATION;
|
||||||
|
import static com.google.errorprone.matchers.Matchers.allOf;
|
||||||
|
import static com.google.errorprone.matchers.Matchers.argument;
|
||||||
|
import static com.google.errorprone.matchers.Matchers.argumentCount;
|
||||||
|
import static com.google.errorprone.matchers.Matchers.instanceMethod;
|
||||||
|
import static com.google.errorprone.matchers.Matchers.nullLiteral;
|
||||||
|
|
||||||
|
import com.google.errorprone.BugPattern;
|
||||||
|
import com.google.errorprone.VisitorState;
|
||||||
|
import com.google.errorprone.bugpatterns.BugChecker;
|
||||||
|
import com.google.errorprone.bugpatterns.BugChecker.MethodInvocationTreeMatcher;
|
||||||
|
import com.google.errorprone.fixes.SuggestedFix;
|
||||||
|
import com.google.errorprone.matchers.Description;
|
||||||
|
import com.google.errorprone.matchers.Matcher;
|
||||||
|
import com.sun.source.tree.MethodInvocationTree;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link BugChecker} that flags AssertJ {@code isEqualTo(null)} checks for simplification.
|
||||||
|
*
|
||||||
|
* <p>This bug checker cannot be replaced with a simple Refaster rule, as the Refaster approach
|
||||||
|
* would require that all overloads of {@link org.assertj.core.api.Assert#isEqualTo(Object)} (such
|
||||||
|
* as {@link org.assertj.core.api.AbstractStringAssert#isEqualTo(String)}) are explicitly
|
||||||
|
* enumerated. This bug checker generically matches all such current and future overloads.
|
||||||
|
*/
|
||||||
|
@BugPattern(
|
||||||
|
summary = "Prefer `.isNull()` over `.isEqualTo(null)`",
|
||||||
|
severity = SUGGESTION,
|
||||||
|
tags = SIMPLIFICATION)
|
||||||
|
public final class Assignment1AssertJIsNullMethod extends BugChecker
|
||||||
|
implements MethodInvocationTreeMatcher {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
private static final Matcher<MethodInvocationTree> ASSERT_IS_EQUAL_TO_NULL =
|
||||||
|
allOf(
|
||||||
|
instanceMethod().onDescendantOf("org.assertj.core.api.Assert").named("isEqualTo"),
|
||||||
|
argumentCount(1),
|
||||||
|
argument(0, nullLiteral()));
|
||||||
|
|
||||||
|
/** Instantiates a new {@link Assignment1AssertJIsNullMethod} instance. */
|
||||||
|
public Assignment1AssertJIsNullMethod() {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {
|
||||||
|
// This statement filters out `MethodInvocation`s that are *not* `assertThat().isEqualTo(null)`
|
||||||
|
// statements.
|
||||||
|
if (!ASSERT_IS_EQUAL_TO_NULL.matches(tree, state)) {
|
||||||
|
return Description.NO_MATCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
SuggestedFix.Builder fix = SuggestedFix.builder();
|
||||||
|
|
||||||
|
// XXX: Using `fix.merge(<some code>);` make sure we rename the method invocation to `isNull`.
|
||||||
|
// See the `SuggestedFixes` class ;).
|
||||||
|
|
||||||
|
tree.getArguments().forEach(arg -> fix.merge(SuggestedFix.delete(arg)));
|
||||||
|
|
||||||
|
return describeMatch(tree, fix.build());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
package tech.picnic.errorprone.workshop.bugpatterns;
|
||||||
|
|
||||||
|
import static com.google.errorprone.BugPattern.SeverityLevel.SUGGESTION;
|
||||||
|
import static com.google.errorprone.BugPattern.StandardTags.SIMPLIFICATION;
|
||||||
|
import static com.google.errorprone.matchers.Matchers.staticMethod;
|
||||||
|
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
import com.google.errorprone.BugPattern;
|
||||||
|
import com.google.errorprone.VisitorState;
|
||||||
|
import com.google.errorprone.bugpatterns.BugChecker;
|
||||||
|
import com.google.errorprone.bugpatterns.BugChecker.MethodInvocationTreeMatcher;
|
||||||
|
import com.google.errorprone.fixes.SuggestedFix;
|
||||||
|
import com.google.errorprone.matchers.Description;
|
||||||
|
import com.google.errorprone.matchers.Matcher;
|
||||||
|
import com.sun.source.tree.ExpressionTree;
|
||||||
|
import com.sun.source.tree.MethodInvocationTree;
|
||||||
|
import tech.picnic.errorprone.utils.SourceCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link BugChecker} that flags method invocations for which all arguments are wrapped using
|
||||||
|
* {@link org.mockito.Mockito#eq}; this is redundant.
|
||||||
|
*/
|
||||||
|
@BugPattern(
|
||||||
|
summary = "Don't unnecessarily use Mockito's `eq(...)`",
|
||||||
|
severity = SUGGESTION,
|
||||||
|
tags = SIMPLIFICATION)
|
||||||
|
public final class Assignment2DropMockitoEq extends BugChecker
|
||||||
|
implements MethodInvocationTreeMatcher {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
private static final Matcher<ExpressionTree> MOCKITO_EQ_METHOD =
|
||||||
|
staticMethod().onClass("org.mockito.ArgumentMatchers").named("eq");
|
||||||
|
|
||||||
|
/** Instantiates a new {@link Assignment2DropMockitoEq} instance. */
|
||||||
|
public Assignment2DropMockitoEq() {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {
|
||||||
|
// XXX: Make sure to return `Description.NO_MATCH` if the `tree` doesn't have arguments, or if
|
||||||
|
// the `isEqInvocation` method below returns `false` for at least one of the arguments.
|
||||||
|
|
||||||
|
SuggestedFix.Builder suggestedFix = SuggestedFix.builder();
|
||||||
|
for (ExpressionTree arg : tree.getArguments()) {
|
||||||
|
suggestedFix.replace(
|
||||||
|
arg,
|
||||||
|
SourceCode.treeToString(
|
||||||
|
Iterables.getOnlyElement(((MethodInvocationTree) arg).getArguments()), state));
|
||||||
|
}
|
||||||
|
|
||||||
|
return describeMatch(tree, suggestedFix.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("UnusedMethod" /* Recommended to use when implementing this assignment. */)
|
||||||
|
private static boolean isEqInvocation(ExpressionTree tree, VisitorState state) {
|
||||||
|
return tree instanceof MethodInvocationTree && MOCKITO_EQ_METHOD.matches(tree, state);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
package tech.picnic.errorprone.workshop.bugpatterns;
|
||||||
|
|
||||||
|
import static com.google.errorprone.BugPattern.SeverityLevel.SUGGESTION;
|
||||||
|
import static com.google.errorprone.BugPattern.StandardTags.SIMPLIFICATION;
|
||||||
|
import static com.google.errorprone.matchers.ChildMultiMatcher.MatchType.AT_LEAST_ONE;
|
||||||
|
import static com.google.errorprone.matchers.Matchers.annotations;
|
||||||
|
import static com.google.errorprone.matchers.Matchers.isType;
|
||||||
|
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
import com.google.errorprone.BugPattern;
|
||||||
|
import com.google.errorprone.VisitorState;
|
||||||
|
import com.google.errorprone.bugpatterns.BugChecker;
|
||||||
|
import com.google.errorprone.bugpatterns.BugChecker.ClassTreeMatcher;
|
||||||
|
import com.google.errorprone.matchers.Description;
|
||||||
|
import com.google.errorprone.matchers.MultiMatcher;
|
||||||
|
import com.google.errorprone.matchers.MultiMatcher.MultiMatchResult;
|
||||||
|
import com.sun.source.tree.AnnotationTree;
|
||||||
|
import com.sun.source.tree.ClassTree;
|
||||||
|
import com.sun.source.tree.MethodTree;
|
||||||
|
import com.sun.source.tree.Tree;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import tech.picnic.errorprone.utils.SourceCode;
|
||||||
|
|
||||||
|
/** A {@link BugChecker} that flags redundant {@code @Autowired} constructor annotations. */
|
||||||
|
@BugPattern(
|
||||||
|
summary = "Omit `@Autowired` on a class' sole constructor, as it is redundant",
|
||||||
|
severity = SUGGESTION,
|
||||||
|
tags = SIMPLIFICATION)
|
||||||
|
public final class Assignment3DropAutowiredConstructorAnnotation extends BugChecker
|
||||||
|
implements ClassTreeMatcher {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
private static final MultiMatcher<Tree, AnnotationTree> AUTOWIRED_ANNOTATION =
|
||||||
|
annotations(AT_LEAST_ONE, isType("org.springframework.beans.factory.annotation.Autowired"));
|
||||||
|
|
||||||
|
/** Instantiates a new {@link Assignment3DropAutowiredConstructorAnnotation} instance. */
|
||||||
|
public Assignment3DropAutowiredConstructorAnnotation() {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Description matchClass(ClassTree tree, VisitorState state) {
|
||||||
|
// XXX: Using the `ASTHelpers#getConstructors` method, return `Description.NO_MATCH` if we do
|
||||||
|
// not have exactly 1 constructor (start by dropping `new ArrayList<>()` on the next line).
|
||||||
|
List<MethodTree> constructors = new ArrayList<>();
|
||||||
|
|
||||||
|
MultiMatchResult<AnnotationTree> hasAutowiredAnnotation =
|
||||||
|
AUTOWIRED_ANNOTATION.multiMatchResult(Iterables.getOnlyElement(constructors), state);
|
||||||
|
if (!hasAutowiredAnnotation.matches()) {
|
||||||
|
return Description.NO_MATCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
AnnotationTree annotation = hasAutowiredAnnotation.onlyMatchingNode();
|
||||||
|
return describeMatch(annotation, SourceCode.deleteWithTrailingWhitespace(annotation, state));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
package tech.picnic.errorprone.workshop.bugpatterns;
|
||||||
|
|
||||||
|
import static com.google.errorprone.BugPattern.SeverityLevel.WARNING;
|
||||||
|
import static com.google.errorprone.BugPattern.StandardTags.SIMPLIFICATION;
|
||||||
|
import static com.google.errorprone.matchers.ChildMultiMatcher.MatchType.AT_LEAST_ONE;
|
||||||
|
import static com.google.errorprone.matchers.Matchers.annotations;
|
||||||
|
import static com.google.errorprone.matchers.Matchers.anyOf;
|
||||||
|
import static com.google.errorprone.matchers.Matchers.isType;
|
||||||
|
|
||||||
|
import com.google.auto.service.AutoService;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
import com.google.errorprone.BugPattern;
|
||||||
|
import com.google.errorprone.VisitorState;
|
||||||
|
import com.google.errorprone.bugpatterns.BugChecker;
|
||||||
|
import com.google.errorprone.bugpatterns.BugChecker.MethodTreeMatcher;
|
||||||
|
import com.google.errorprone.fixes.SuggestedFix;
|
||||||
|
import com.google.errorprone.matchers.Description;
|
||||||
|
import com.google.errorprone.matchers.MultiMatcher;
|
||||||
|
import com.sun.source.tree.AnnotationTree;
|
||||||
|
import com.sun.source.tree.MethodTree;
|
||||||
|
import javax.lang.model.element.Modifier;
|
||||||
|
|
||||||
|
/** A {@link BugChecker} that flags non-canonical JUnit method declarations. */
|
||||||
|
@AutoService(BugChecker.class)
|
||||||
|
@BugPattern(
|
||||||
|
summary = "JUnit method declaration can likely be improved",
|
||||||
|
severity = WARNING,
|
||||||
|
tags = SIMPLIFICATION)
|
||||||
|
@SuppressWarnings({
|
||||||
|
"UnusedMethod",
|
||||||
|
"UnusedVariable"
|
||||||
|
} /* This check is yet to be implemented as part of the demo. */)
|
||||||
|
public final class Assignment4JUnitTestMethodDeclaration extends BugChecker
|
||||||
|
implements MethodTreeMatcher {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
private static final ImmutableSet<Modifier> ILLEGAL_MODIFIERS =
|
||||||
|
Sets.immutableEnumSet(Modifier.PRIVATE, Modifier.PROTECTED, Modifier.PUBLIC);
|
||||||
|
private static final MultiMatcher<MethodTree, AnnotationTree> TEST_METHOD =
|
||||||
|
annotations(AT_LEAST_ONE, anyOf(isType("org.junit.jupiter.api.Test")));
|
||||||
|
|
||||||
|
/** Instantiates a new {@link Assignment4JUnitTestMethodDeclaration} instance. */
|
||||||
|
public Assignment4JUnitTestMethodDeclaration() {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Description matchMethod(MethodTree tree, VisitorState state) {
|
||||||
|
// XXX: Part 1: Return `Description.NO_MATCH` if the method is not a `TEST_METHOD`.
|
||||||
|
|
||||||
|
SuggestedFix.Builder fixBuilder = SuggestedFix.builder();
|
||||||
|
|
||||||
|
// XXX: Part 2: Make sure that JUnit test methods don't use any of the modifiers from the
|
||||||
|
// `ILLEGAL_MODIFIERS` field, by using `SuggestedFixes#removeModifiers` and
|
||||||
|
// `SuggestedFix.Builder#merge`.
|
||||||
|
|
||||||
|
if (fixBuilder.isEmpty()) {
|
||||||
|
return Description.NO_MATCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
return describeMatch(tree, fixBuilder.build());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,108 @@
|
|||||||
|
package tech.picnic.errorprone.workshop.bugpatterns;
|
||||||
|
|
||||||
|
import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||||
|
import static com.google.errorprone.BugPattern.SeverityLevel.WARNING;
|
||||||
|
import static com.google.errorprone.BugPattern.StandardTags.SIMPLIFICATION;
|
||||||
|
import static com.google.errorprone.matchers.Matchers.anyOf;
|
||||||
|
import static com.google.errorprone.matchers.Matchers.staticMethod;
|
||||||
|
import static com.google.errorprone.suppliers.Suppliers.OBJECT_TYPE;
|
||||||
|
|
||||||
|
import com.google.common.primitives.Primitives;
|
||||||
|
import com.google.errorprone.BugPattern;
|
||||||
|
import com.google.errorprone.VisitorState;
|
||||||
|
import com.google.errorprone.bugpatterns.BugChecker;
|
||||||
|
import com.google.errorprone.bugpatterns.BugChecker.MethodInvocationTreeMatcher;
|
||||||
|
import com.google.errorprone.bugpatterns.TypesWithUndefinedEquality;
|
||||||
|
import com.google.errorprone.matchers.Description;
|
||||||
|
import com.google.errorprone.matchers.Matcher;
|
||||||
|
import com.google.errorprone.util.ASTHelpers;
|
||||||
|
import com.google.errorprone.util.ASTHelpers.TargetType;
|
||||||
|
import com.sun.source.tree.ExpressionTree;
|
||||||
|
import com.sun.source.tree.MemberSelectTree;
|
||||||
|
import com.sun.source.tree.MethodInvocationTree;
|
||||||
|
import com.sun.tools.javac.code.Type;
|
||||||
|
import com.sun.tools.javac.code.Types;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/** A {@link BugChecker} that flags redundant identity conversions. */
|
||||||
|
@BugPattern(
|
||||||
|
summary = "Avoid or clarify identity conversions",
|
||||||
|
severity = WARNING,
|
||||||
|
tags = SIMPLIFICATION)
|
||||||
|
public final class Assignment5DeleteIdentityConversion extends BugChecker
|
||||||
|
implements MethodInvocationTreeMatcher {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
private static final Matcher<ExpressionTree> IS_CONVERSION_METHOD =
|
||||||
|
anyOf(
|
||||||
|
staticMethod()
|
||||||
|
.onClassAny(
|
||||||
|
Primitives.allWrapperTypes().stream()
|
||||||
|
.map(Class::getName)
|
||||||
|
.collect(toImmutableSet()))
|
||||||
|
.named("valueOf"),
|
||||||
|
staticMethod().onClass(String.class.getName()).named("valueOf"),
|
||||||
|
staticMethod()
|
||||||
|
.onClassAny(
|
||||||
|
"com.google.common.collect.ImmutableBiMap",
|
||||||
|
"com.google.common.collect.ImmutableList",
|
||||||
|
"com.google.common.collect.ImmutableListMultimap",
|
||||||
|
"com.google.common.collect.ImmutableMap",
|
||||||
|
"com.google.common.collect.ImmutableMultimap",
|
||||||
|
"com.google.common.collect.ImmutableMultiset",
|
||||||
|
"com.google.common.collect.ImmutableRangeMap",
|
||||||
|
"com.google.common.collect.ImmutableRangeSet",
|
||||||
|
"com.google.common.collect.ImmutableSet",
|
||||||
|
"com.google.common.collect.ImmutableSetMultimap",
|
||||||
|
"com.google.common.collect.ImmutableTable")
|
||||||
|
.named("copyOf"),
|
||||||
|
staticMethod()
|
||||||
|
.onClass("com.google.errorprone.matchers.Matchers")
|
||||||
|
.namedAnyOf("allOf", "anyOf"));
|
||||||
|
|
||||||
|
/** Instantiates a new {@link Assignment5DeleteIdentityConversion} instance. */
|
||||||
|
public Assignment5DeleteIdentityConversion() {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {
|
||||||
|
List<? extends ExpressionTree> arguments = tree.getArguments();
|
||||||
|
// XXX: Make sure we skip invocations that do not pass exactly one argument, by using the
|
||||||
|
// `tree`.
|
||||||
|
if (!IS_CONVERSION_METHOD.matches(tree, state)) {
|
||||||
|
return Description.NO_MATCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
ExpressionTree sourceTree = arguments.get(0);
|
||||||
|
Type sourceType = ASTHelpers.getType(sourceTree);
|
||||||
|
Type resultType = ASTHelpers.getType(tree);
|
||||||
|
TargetType targetType = ASTHelpers.targetType(state);
|
||||||
|
if (sourceType == null || resultType == null || targetType == null) {
|
||||||
|
return Description.NO_MATCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!state.getTypes().isSameType(sourceType, resultType)
|
||||||
|
&& !isConvertibleWithWellDefinedEquality(sourceType, targetType.type(), state)) {
|
||||||
|
return Description.NO_MATCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sourceType.isPrimitive()
|
||||||
|
&& state.getPath().getParentPath().getLeaf() instanceof MemberSelectTree) {
|
||||||
|
return Description.NO_MATCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buildDescription(tree)
|
||||||
|
// XXX: Use the `.addFix()` to suggest replacing the original `tree` with the `sourceTree`.
|
||||||
|
// Tip: You can get the actual String representation of a Tree by using the
|
||||||
|
// `SourceCode#treeToString`.
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isConvertibleWithWellDefinedEquality(
|
||||||
|
Type sourceType, Type targetType, VisitorState state) {
|
||||||
|
Types types = state.getTypes();
|
||||||
|
return !types.isSameType(targetType, OBJECT_TYPE.get(state))
|
||||||
|
&& types.isConvertible(sourceType, targetType)
|
||||||
|
&& Arrays.stream(TypesWithUndefinedEquality.values())
|
||||||
|
.noneMatch(b -> b.matchesType(sourceType, state) || b.matchesType(targetType, state));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package tech.picnic.errorprone.workshop.refasterrules;
|
||||||
|
|
||||||
|
import com.google.errorprone.refaster.annotation.AfterTemplate;
|
||||||
|
import com.google.errorprone.refaster.annotation.BeforeTemplate;
|
||||||
|
|
||||||
|
/** Refaster rule used as example for the assignments of the workshop. */
|
||||||
|
final class WorkshopAssignment0Rules {
|
||||||
|
private WorkshopAssignment0Rules() {}
|
||||||
|
|
||||||
|
/** Prefer {@link String#isEmpty()} over alternatives that consult the string's length. */
|
||||||
|
static final class ExampleStringIsEmpty {
|
||||||
|
@BeforeTemplate
|
||||||
|
boolean before(String str) {
|
||||||
|
return str.length() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterTemplate
|
||||||
|
boolean after(String str) {
|
||||||
|
return str.isEmpty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package tech.picnic.errorprone.workshop.refasterrules;
|
||||||
|
|
||||||
|
/** Refaster rules for the first assignment of the workshop. */
|
||||||
|
final class WorkshopAssignment1Rules {
|
||||||
|
private WorkshopAssignment1Rules() {}
|
||||||
|
|
||||||
|
/** Prefer {@link String#String(char[])} over {@link String#copyValueOf(char[])}. */
|
||||||
|
static final class NewStringCharArray {
|
||||||
|
// XXX: Implement this Refaster rule.
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package tech.picnic.errorprone.workshop.refasterrules;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
|
||||||
|
/** Refaster rules for the second assignment of the workshop. */
|
||||||
|
@SuppressWarnings("UnusedTypeParameter" /* Ignore this for demo purposes. */)
|
||||||
|
final class WorkshopAssignment2Rules {
|
||||||
|
private WorkshopAssignment2Rules() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prefer {@link ImmutableList#of(Object)} over alternatives that don't communicate the
|
||||||
|
* immutability of the resulting list at the type level.
|
||||||
|
*/
|
||||||
|
static final class ImmutableListOfOne<T> {
|
||||||
|
// XXX: Implement this Refaster rule, preferably by using only one `@BeforeTemplate`.
|
||||||
|
// Tip: use the type argument.
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package tech.picnic.errorprone.workshop.refasterrules;
|
||||||
|
|
||||||
|
import com.google.common.base.Preconditions;
|
||||||
|
|
||||||
|
/** Refaster rules for the third assignment of the workshop. */
|
||||||
|
@SuppressWarnings("UnusedTypeParameter" /* Ignore this for demo purposes. */)
|
||||||
|
final class WorkshopAssignment3Rules {
|
||||||
|
private WorkshopAssignment3Rules() {}
|
||||||
|
|
||||||
|
// XXX: Tip: check the input and output files to see the *expected* refactoring.
|
||||||
|
|
||||||
|
/** Prefer {@link Preconditions#checkArgument(boolean)} over if statements. */
|
||||||
|
static final class CheckArgumentWithoutMessage {
|
||||||
|
// XXX: Implement the Refaster rule to get the test green.
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Prefer {@link Preconditions#checkArgument(boolean, Object)} over if statements. */
|
||||||
|
static final class CheckArgumentWithMessage {
|
||||||
|
// XXX: Implement the Refaster rule to get the test green.
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package tech.picnic.errorprone.workshop.refasterrules;
|
||||||
|
|
||||||
|
/** Refaster rules for the fourth assignment of the workshop. */
|
||||||
|
@SuppressWarnings("java:S1698" /* Reference comparison is valid for enums. */)
|
||||||
|
final class WorkshopAssignment4Rules {
|
||||||
|
private WorkshopAssignment4Rules() {}
|
||||||
|
|
||||||
|
// The test fails because non Enum comparisons are also rewritten.
|
||||||
|
// Fix the test by tweaking the type parameters.
|
||||||
|
|
||||||
|
// XXX: Get the test to pass by improving the Refaster rule (uncommented it first).
|
||||||
|
|
||||||
|
// static final class PrimitiveOrReferenceEqualityEnum<T> {
|
||||||
|
// @BeforeTemplate
|
||||||
|
// boolean before(T a, T b) {
|
||||||
|
// return Refaster.anyOf(a.equals(b), Objects.equals(a, b));
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// @AfterTemplate
|
||||||
|
// @AlsoNegation
|
||||||
|
// boolean after(T a, T b) {
|
||||||
|
// return a == b;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package tech.picnic.errorprone.workshop.refasterrules;
|
||||||
|
|
||||||
|
/** Refaster rules for the fifth assignment of the workshop. */
|
||||||
|
@SuppressWarnings("UnusedTypeParameter" /* Ignore this for demo purposes. */)
|
||||||
|
final class WorkshopAssignment5Rules {
|
||||||
|
private WorkshopAssignment5Rules() {}
|
||||||
|
|
||||||
|
abstract static class StreamDoAllMatch<T> {
|
||||||
|
// XXX: Implement the Refaster rule to get the test green.
|
||||||
|
// Tip: use the `@Placeholder` annotation.
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
package tech.picnic.errorprone.workshop.bugpatterns;
|
||||||
|
|
||||||
|
import com.google.errorprone.BugCheckerRefactoringTestHelper;
|
||||||
|
import com.google.errorprone.BugCheckerRefactoringTestHelper.TestMode;
|
||||||
|
import com.google.errorprone.CompilationTestHelper;
|
||||||
|
import org.junit.jupiter.api.Disabled;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
@Disabled("Enable this when implementing the BugChecker.")
|
||||||
|
final class Assignment0DeleteEmptyMethodTest {
|
||||||
|
@Test
|
||||||
|
void identification() {
|
||||||
|
CompilationTestHelper.newInstance(Assignment0DeleteEmptyMethod.class, getClass())
|
||||||
|
.addSourceLines(
|
||||||
|
"A.java",
|
||||||
|
"class A {",
|
||||||
|
" Object m1() {",
|
||||||
|
" return null;",
|
||||||
|
" }",
|
||||||
|
"",
|
||||||
|
" void m2() {",
|
||||||
|
" System.out.println(42);",
|
||||||
|
" }",
|
||||||
|
"",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" static void m3() {}",
|
||||||
|
"",
|
||||||
|
" interface F {",
|
||||||
|
" void fun();",
|
||||||
|
" }",
|
||||||
|
"}")
|
||||||
|
.addSourceLines(
|
||||||
|
"B.java",
|
||||||
|
"final class B implements A.F {",
|
||||||
|
" @Override",
|
||||||
|
" public void fun() {}",
|
||||||
|
"",
|
||||||
|
" /** Javadoc. */",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" void m4() {}",
|
||||||
|
"}")
|
||||||
|
.doTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void replacement() {
|
||||||
|
BugCheckerRefactoringTestHelper.newInstance(Assignment0DeleteEmptyMethod.class, getClass())
|
||||||
|
.addInputLines(
|
||||||
|
"A.java",
|
||||||
|
"final class A {",
|
||||||
|
"",
|
||||||
|
" void instanceMethod() {}",
|
||||||
|
"",
|
||||||
|
" static void staticMethod() {}",
|
||||||
|
"",
|
||||||
|
" static void staticMethodWithComment() {",
|
||||||
|
" System.out.println(42);",
|
||||||
|
" }",
|
||||||
|
"}")
|
||||||
|
.addOutputLines(
|
||||||
|
"A.java",
|
||||||
|
"final class A {",
|
||||||
|
"",
|
||||||
|
" static void staticMethodWithComment() {",
|
||||||
|
" System.out.println(42);",
|
||||||
|
" }",
|
||||||
|
"}")
|
||||||
|
.doTest(TestMode.TEXT_MATCH);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
package tech.picnic.errorprone.workshop.bugpatterns;
|
||||||
|
|
||||||
|
import com.google.errorprone.BugCheckerRefactoringTestHelper;
|
||||||
|
import com.google.errorprone.BugCheckerRefactoringTestHelper.TestMode;
|
||||||
|
import com.google.errorprone.CompilationTestHelper;
|
||||||
|
import org.junit.jupiter.api.Disabled;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
@Disabled("Enable this when implementing the BugChecker.")
|
||||||
|
final class Assignment1AssertJIsNullMethodTest {
|
||||||
|
@Test
|
||||||
|
void identification() {
|
||||||
|
CompilationTestHelper.newInstance(Assignment1AssertJIsNullMethod.class, getClass())
|
||||||
|
.addSourceLines(
|
||||||
|
"A.java",
|
||||||
|
"import static org.assertj.core.api.Assertions.assertThat;",
|
||||||
|
"",
|
||||||
|
"class A {",
|
||||||
|
" void m() {",
|
||||||
|
" assertThat(1).isEqualTo(1);",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" assertThat(1).isEqualTo(null);",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" assertThat(\"foo\").isEqualTo(null);",
|
||||||
|
" isEqualTo(null);",
|
||||||
|
" }",
|
||||||
|
"",
|
||||||
|
" private boolean isEqualTo(Object value) {",
|
||||||
|
" return value.equals(\"bar\");",
|
||||||
|
" }",
|
||||||
|
"}")
|
||||||
|
.doTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void replacement() {
|
||||||
|
BugCheckerRefactoringTestHelper.newInstance(Assignment1AssertJIsNullMethod.class, getClass())
|
||||||
|
.addInputLines(
|
||||||
|
"A.java",
|
||||||
|
"import static org.assertj.core.api.Assertions.assertThat;",
|
||||||
|
"",
|
||||||
|
"class A {",
|
||||||
|
" void m() {",
|
||||||
|
" assertThat(1).isEqualTo(null);",
|
||||||
|
" assertThat(\"foo\").isEqualTo(null);",
|
||||||
|
" }",
|
||||||
|
"}")
|
||||||
|
.addOutputLines(
|
||||||
|
"A.java",
|
||||||
|
"import static org.assertj.core.api.Assertions.assertThat;",
|
||||||
|
"",
|
||||||
|
"class A {",
|
||||||
|
" void m() {",
|
||||||
|
" assertThat(1).isNull();",
|
||||||
|
" assertThat(\"foo\").isNull();",
|
||||||
|
" }",
|
||||||
|
"}")
|
||||||
|
.doTest(TestMode.TEXT_MATCH);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,102 @@
|
|||||||
|
package tech.picnic.errorprone.workshop.bugpatterns;
|
||||||
|
|
||||||
|
import com.google.errorprone.BugCheckerRefactoringTestHelper;
|
||||||
|
import com.google.errorprone.BugCheckerRefactoringTestHelper.TestMode;
|
||||||
|
import com.google.errorprone.CompilationTestHelper;
|
||||||
|
import org.junit.jupiter.api.Disabled;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
@Disabled("Enable this when implementing the BugChecker.")
|
||||||
|
final class Assignment2DropMockitoEqTest {
|
||||||
|
@Test
|
||||||
|
void identification() {
|
||||||
|
CompilationTestHelper.newInstance(Assignment2DropMockitoEq.class, getClass())
|
||||||
|
.addSourceLines(
|
||||||
|
"A.java",
|
||||||
|
"import static org.mockito.ArgumentMatchers.eq;",
|
||||||
|
"import static org.mockito.ArgumentMatchers.notNull;",
|
||||||
|
"import static org.mockito.Mockito.doAnswer;",
|
||||||
|
"import static org.mockito.Mockito.mock;",
|
||||||
|
"",
|
||||||
|
"import java.util.function.BiConsumer;",
|
||||||
|
"import java.util.function.Consumer;",
|
||||||
|
"import org.mockito.ArgumentMatchers;",
|
||||||
|
"",
|
||||||
|
"class A {",
|
||||||
|
" void m() {",
|
||||||
|
" Runnable runnable = mock(Runnable.class);",
|
||||||
|
" doAnswer(inv -> null).when(runnable).run();",
|
||||||
|
"",
|
||||||
|
" Consumer<String> consumer = mock(Consumer.class);",
|
||||||
|
" doAnswer(inv -> null).when(consumer).accept(\"foo\");",
|
||||||
|
" doAnswer(inv -> null).when(consumer).accept(notNull());",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" doAnswer(inv -> null).when(consumer).accept(ArgumentMatchers.eq(\"foo\"));",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" doAnswer(inv -> null).when(consumer).accept(eq(toString()));",
|
||||||
|
"",
|
||||||
|
" BiConsumer<Integer, String> biConsumer = mock(BiConsumer.class);",
|
||||||
|
" doAnswer(inv -> null).when(biConsumer).accept(0, \"foo\");",
|
||||||
|
" doAnswer(inv -> null).when(biConsumer).accept(eq(0), notNull());",
|
||||||
|
" doAnswer(inv -> null).when(biConsumer).accept(notNull(), eq(\"foo\"));",
|
||||||
|
" doAnswer(inv -> null)",
|
||||||
|
" .when(biConsumer)",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" .accept(ArgumentMatchers.eq(0), ArgumentMatchers.eq(\"foo\"));",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" doAnswer(inv -> null).when(biConsumer).accept(eq(hashCode()), eq(toString()));",
|
||||||
|
" }",
|
||||||
|
"}")
|
||||||
|
.doTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void replacement() {
|
||||||
|
BugCheckerRefactoringTestHelper.newInstance(Assignment2DropMockitoEq.class, getClass())
|
||||||
|
.addInputLines(
|
||||||
|
"A.java",
|
||||||
|
"import static org.mockito.ArgumentMatchers.eq;",
|
||||||
|
"import static org.mockito.Mockito.doAnswer;",
|
||||||
|
"import static org.mockito.Mockito.mock;",
|
||||||
|
"",
|
||||||
|
"import java.util.function.BiConsumer;",
|
||||||
|
"import java.util.function.Consumer;",
|
||||||
|
"import org.mockito.ArgumentMatchers;",
|
||||||
|
"",
|
||||||
|
"class A {",
|
||||||
|
" void m() {",
|
||||||
|
" Consumer<String> consumer = mock(Consumer.class);",
|
||||||
|
" doAnswer(inv -> null).when(consumer).accept(ArgumentMatchers.eq(\"foo\"));",
|
||||||
|
" doAnswer(inv -> null).when(consumer).accept(eq(toString()));",
|
||||||
|
"",
|
||||||
|
" BiConsumer<Integer, String> biConsumer = mock(BiConsumer.class);",
|
||||||
|
" doAnswer(inv -> null)",
|
||||||
|
" .when(biConsumer)",
|
||||||
|
" .accept(ArgumentMatchers.eq(0), ArgumentMatchers.eq(\"foo\"));",
|
||||||
|
" doAnswer(inv -> null).when(biConsumer).accept(eq(hashCode()), eq(toString()));",
|
||||||
|
" }",
|
||||||
|
"}")
|
||||||
|
.addOutputLines(
|
||||||
|
"A.java",
|
||||||
|
"import static org.mockito.ArgumentMatchers.eq;",
|
||||||
|
"import static org.mockito.Mockito.doAnswer;",
|
||||||
|
"import static org.mockito.Mockito.mock;",
|
||||||
|
"",
|
||||||
|
"import java.util.function.BiConsumer;",
|
||||||
|
"import java.util.function.Consumer;",
|
||||||
|
"import org.mockito.ArgumentMatchers;",
|
||||||
|
"",
|
||||||
|
"class A {",
|
||||||
|
" void m() {",
|
||||||
|
" Consumer<String> consumer = mock(Consumer.class);",
|
||||||
|
" doAnswer(inv -> null).when(consumer).accept(\"foo\");",
|
||||||
|
" doAnswer(inv -> null).when(consumer).accept(toString());",
|
||||||
|
"",
|
||||||
|
" BiConsumer<Integer, String> biConsumer = mock(BiConsumer.class);",
|
||||||
|
" doAnswer(inv -> null).when(biConsumer).accept(0, \"foo\");",
|
||||||
|
" doAnswer(inv -> null).when(biConsumer).accept(hashCode(), toString());",
|
||||||
|
" }",
|
||||||
|
"}")
|
||||||
|
.doTest(TestMode.TEXT_MATCH);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
package tech.picnic.errorprone.workshop.bugpatterns;
|
||||||
|
|
||||||
|
import com.google.errorprone.BugCheckerRefactoringTestHelper;
|
||||||
|
import com.google.errorprone.BugCheckerRefactoringTestHelper.TestMode;
|
||||||
|
import com.google.errorprone.CompilationTestHelper;
|
||||||
|
import org.junit.jupiter.api.Disabled;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
@Disabled("Enable this when implementing the BugChecker.")
|
||||||
|
final class Assignment3DropAutowiredConstructorAnnotationTest {
|
||||||
|
@Test
|
||||||
|
void identification() {
|
||||||
|
CompilationTestHelper.newInstance(
|
||||||
|
Assignment3DropAutowiredConstructorAnnotation.class, getClass())
|
||||||
|
.addSourceLines(
|
||||||
|
"Container.java",
|
||||||
|
"import com.google.errorprone.annotations.Immutable;",
|
||||||
|
"import java.util.List;",
|
||||||
|
"import org.springframework.beans.factory.annotation.Autowired;",
|
||||||
|
"",
|
||||||
|
"interface Container {",
|
||||||
|
" @Immutable",
|
||||||
|
" class A {",
|
||||||
|
" A() {}",
|
||||||
|
" }",
|
||||||
|
"",
|
||||||
|
" class B {",
|
||||||
|
" @Autowired",
|
||||||
|
" void setProperty(Object o) {}",
|
||||||
|
" }",
|
||||||
|
"",
|
||||||
|
" class C {",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" @Autowired",
|
||||||
|
" C() {}",
|
||||||
|
" }",
|
||||||
|
"",
|
||||||
|
" class D {",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" @Autowired",
|
||||||
|
" D(String x) {}",
|
||||||
|
" }",
|
||||||
|
"",
|
||||||
|
" class E {",
|
||||||
|
" @Autowired",
|
||||||
|
" E() {}",
|
||||||
|
"",
|
||||||
|
" E(String x) {}",
|
||||||
|
" }",
|
||||||
|
"",
|
||||||
|
" class F {",
|
||||||
|
" F() {}",
|
||||||
|
"",
|
||||||
|
" @Autowired",
|
||||||
|
" F(String x) {}",
|
||||||
|
" }",
|
||||||
|
"",
|
||||||
|
" class G {",
|
||||||
|
" @Autowired private Object o;",
|
||||||
|
" }",
|
||||||
|
"",
|
||||||
|
" class H {",
|
||||||
|
" @SafeVarargs",
|
||||||
|
" H(List<String>... lists) {}",
|
||||||
|
" }",
|
||||||
|
"}")
|
||||||
|
.doTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void replacement() {
|
||||||
|
BugCheckerRefactoringTestHelper.newInstance(
|
||||||
|
Assignment3DropAutowiredConstructorAnnotation.class, getClass())
|
||||||
|
.addInputLines(
|
||||||
|
"Container.java",
|
||||||
|
"import org.springframework.beans.factory.annotation.Autowired;",
|
||||||
|
"",
|
||||||
|
"interface Container {",
|
||||||
|
" class A {",
|
||||||
|
" @Autowired",
|
||||||
|
" @Deprecated",
|
||||||
|
" A() {}",
|
||||||
|
" }",
|
||||||
|
"",
|
||||||
|
" class B {",
|
||||||
|
" @Autowired",
|
||||||
|
" B(String x) {}",
|
||||||
|
" }",
|
||||||
|
"}")
|
||||||
|
.addOutputLines(
|
||||||
|
"Container.java",
|
||||||
|
"import org.springframework.beans.factory.annotation.Autowired;",
|
||||||
|
"",
|
||||||
|
"interface Container {",
|
||||||
|
" class A {",
|
||||||
|
" @Deprecated",
|
||||||
|
" A() {}",
|
||||||
|
" }",
|
||||||
|
"",
|
||||||
|
" class B {",
|
||||||
|
" B(String x) {}",
|
||||||
|
" }",
|
||||||
|
"}")
|
||||||
|
.doTest(TestMode.TEXT_MATCH);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
package tech.picnic.errorprone.workshop.bugpatterns;
|
||||||
|
|
||||||
|
import com.google.errorprone.BugCheckerRefactoringTestHelper;
|
||||||
|
import com.google.errorprone.BugCheckerRefactoringTestHelper.TestMode;
|
||||||
|
import com.google.errorprone.CompilationTestHelper;
|
||||||
|
import org.junit.jupiter.api.Disabled;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
@Disabled("Enable this to validate part 1.")
|
||||||
|
final class Assignment4JUnitTestMethodDeclarationTest {
|
||||||
|
@Test
|
||||||
|
void identificationIllegalModifiers() {
|
||||||
|
CompilationTestHelper.newInstance(Assignment4JUnitTestMethodDeclaration.class, getClass())
|
||||||
|
.addSourceLines(
|
||||||
|
"A.java",
|
||||||
|
"import org.junit.jupiter.api.Test;",
|
||||||
|
"",
|
||||||
|
"class A {",
|
||||||
|
" @Test",
|
||||||
|
" void method1() {}",
|
||||||
|
"",
|
||||||
|
" @Test",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" public void method2() {}",
|
||||||
|
"",
|
||||||
|
" @Test",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" protected void method3() {}",
|
||||||
|
"",
|
||||||
|
" @Test",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" private void method4() {}",
|
||||||
|
"",
|
||||||
|
" public void method5() {}",
|
||||||
|
"",
|
||||||
|
" protected void method6() {}",
|
||||||
|
"",
|
||||||
|
" private void method7() {}",
|
||||||
|
"}")
|
||||||
|
.doTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void replacementIllegalModifiers() {
|
||||||
|
BugCheckerRefactoringTestHelper.newInstance(
|
||||||
|
Assignment4JUnitTestMethodDeclaration.class, getClass())
|
||||||
|
.addInputLines(
|
||||||
|
"A.java",
|
||||||
|
"import org.junit.jupiter.api.Test;",
|
||||||
|
"",
|
||||||
|
"class A {",
|
||||||
|
" @Test",
|
||||||
|
" void foo() {}",
|
||||||
|
"",
|
||||||
|
" @Test",
|
||||||
|
" public void bar() {}",
|
||||||
|
"",
|
||||||
|
" @Test",
|
||||||
|
" protected void baz() {}",
|
||||||
|
"",
|
||||||
|
" @Test",
|
||||||
|
" private void qux() {}",
|
||||||
|
"",
|
||||||
|
" public void quux() {}",
|
||||||
|
"",
|
||||||
|
" private void quuz() {}",
|
||||||
|
"}")
|
||||||
|
.addOutputLines(
|
||||||
|
"A.java",
|
||||||
|
"import org.junit.jupiter.api.Test;",
|
||||||
|
"",
|
||||||
|
"class A {",
|
||||||
|
" @Test",
|
||||||
|
" void foo() {}",
|
||||||
|
"",
|
||||||
|
" @Test",
|
||||||
|
" void bar() {}",
|
||||||
|
"",
|
||||||
|
" @Test",
|
||||||
|
" void baz() {}",
|
||||||
|
"",
|
||||||
|
" @Test",
|
||||||
|
" void qux() {}",
|
||||||
|
"",
|
||||||
|
" public void quux() {}",
|
||||||
|
"",
|
||||||
|
" private void quuz() {}",
|
||||||
|
"}")
|
||||||
|
.doTest(TestMode.TEXT_MATCH);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,223 @@
|
|||||||
|
package tech.picnic.errorprone.workshop.bugpatterns;
|
||||||
|
|
||||||
|
import com.google.errorprone.BugCheckerRefactoringTestHelper;
|
||||||
|
import com.google.errorprone.BugCheckerRefactoringTestHelper.TestMode;
|
||||||
|
import com.google.errorprone.CompilationTestHelper;
|
||||||
|
import org.junit.jupiter.api.Disabled;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
@Disabled("Enable this when implementing the BugChecker.")
|
||||||
|
final class Assignment5DeleteIdentityConversionTest {
|
||||||
|
@Test
|
||||||
|
void identification() {
|
||||||
|
CompilationTestHelper.newInstance(Assignment5DeleteIdentityConversion.class, getClass())
|
||||||
|
.addSourceLines(
|
||||||
|
"A.java",
|
||||||
|
"import static com.google.errorprone.matchers.Matchers.instanceMethod;",
|
||||||
|
"import static com.google.errorprone.matchers.Matchers.staticMethod;",
|
||||||
|
"",
|
||||||
|
"import com.google.common.collect.ImmutableBiMap;",
|
||||||
|
"import com.google.common.collect.ImmutableList;",
|
||||||
|
"import com.google.common.collect.ImmutableListMultimap;",
|
||||||
|
"import com.google.common.collect.ImmutableMap;",
|
||||||
|
"import com.google.common.collect.ImmutableMultimap;",
|
||||||
|
"import com.google.common.collect.ImmutableMultiset;",
|
||||||
|
"import com.google.common.collect.ImmutableRangeMap;",
|
||||||
|
"import com.google.common.collect.ImmutableRangeSet;",
|
||||||
|
"import com.google.common.collect.ImmutableSet;",
|
||||||
|
"import com.google.common.collect.ImmutableSetMultimap;",
|
||||||
|
"import com.google.common.collect.ImmutableTable;",
|
||||||
|
"import com.google.errorprone.matchers.Matcher;",
|
||||||
|
"import com.google.errorprone.matchers.Matchers;",
|
||||||
|
"",
|
||||||
|
"public final class A {",
|
||||||
|
" public void m() {",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" Matcher allOf1 = Matchers.allOf(instanceMethod());",
|
||||||
|
" Matcher allOf2 = Matchers.allOf(instanceMethod(), staticMethod());",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" Matcher anyOf1 = Matchers.anyOf(staticMethod());",
|
||||||
|
" Matcher anyOf2 = Matchers.anyOf(instanceMethod(), staticMethod());",
|
||||||
|
"",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" Boolean b1 = Boolean.valueOf(Boolean.FALSE);",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" Boolean b2 = Boolean.valueOf(false);",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" boolean b3 = Boolean.valueOf(Boolean.FALSE);",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" boolean b4 = Boolean.valueOf(false);",
|
||||||
|
"",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" Byte byte1 = Byte.valueOf((Byte) Byte.MIN_VALUE);",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" Byte byte2 = Byte.valueOf(Byte.MIN_VALUE);",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" byte byte3 = Byte.valueOf((Byte) Byte.MIN_VALUE);",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" byte byte4 = Byte.valueOf(Byte.MIN_VALUE);",
|
||||||
|
"",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" Character c1 = Character.valueOf((Character) 'a');",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" Character c2 = Character.valueOf('a');",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" char c3 = Character.valueOf((Character) 'a');",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" char c4 = Character.valueOf('a');",
|
||||||
|
"",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" Double d1 = Double.valueOf((Double) 0.0);",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" Double d2 = Double.valueOf(0.0);",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" double d3 = Double.valueOf((Double) 0.0);",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" double d4 = Double.valueOf(0.0);",
|
||||||
|
"",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" Float f1 = Float.valueOf((Float) 0.0F);",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" Float f2 = Float.valueOf(0.0F);",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" float f3 = Float.valueOf((Float) 0.0F);",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" float f4 = Float.valueOf(0.0F);",
|
||||||
|
"",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" Integer i1 = Integer.valueOf((Integer) 1);",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" Integer i2 = Integer.valueOf(1);",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" int i3 = Integer.valueOf((Integer) 1);",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" int i4 = Integer.valueOf(1);",
|
||||||
|
"",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" Long l1 = Long.valueOf((Long) 1L);",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" Long l2 = Long.valueOf(1L);",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" long l3 = Long.valueOf((Long) 1L);",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" long l4 = Long.valueOf(1L);",
|
||||||
|
"",
|
||||||
|
" Long l5 = Long.valueOf((Integer) 1);",
|
||||||
|
" Long l6 = Long.valueOf(1);",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" long l7 = Long.valueOf((Integer) 1);",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" long l8 = Long.valueOf(1);",
|
||||||
|
"",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" Short s1 = Short.valueOf((Short) Short.MIN_VALUE);",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" Short s2 = Short.valueOf(Short.MIN_VALUE);",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" short s3 = Short.valueOf((Short) Short.MIN_VALUE);",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" short s4 = Short.valueOf(Short.MIN_VALUE);",
|
||||||
|
"",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" String boolStr = Boolean.valueOf(Boolean.FALSE).toString();",
|
||||||
|
" int boolHash = Boolean.valueOf(false).hashCode();",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" int byteHash = Byte.valueOf((Byte) Byte.MIN_VALUE).hashCode();",
|
||||||
|
" String byteStr = Byte.valueOf(Byte.MIN_VALUE).toString();",
|
||||||
|
"",
|
||||||
|
" String str1 = String.valueOf(0);",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" String str2 = String.valueOf(\"1\");",
|
||||||
|
"",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" ImmutableBiMap<Object, Object> o1 = ImmutableBiMap.copyOf(ImmutableBiMap.of());",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" ImmutableList<Object> o2 = ImmutableList.copyOf(ImmutableList.of());",
|
||||||
|
" ImmutableListMultimap<Object, Object> o3 =",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" ImmutableListMultimap.copyOf(ImmutableListMultimap.of());",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" ImmutableMap<Object, Object> o4 = ImmutableMap.copyOf(ImmutableMap.of());",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" ImmutableMultimap<Object, Object> o5 = ImmutableMultimap.copyOf(ImmutableMultimap.of());",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" ImmutableMultiset<Object> o6 = ImmutableMultiset.copyOf(ImmutableMultiset.of());",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" ImmutableRangeMap<String, Object> o7 = ImmutableRangeMap.copyOf(ImmutableRangeMap.of());",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" ImmutableRangeSet<String> o8 = ImmutableRangeSet.copyOf(ImmutableRangeSet.of());",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" ImmutableSet<Object> o9 = ImmutableSet.copyOf(ImmutableSet.of());",
|
||||||
|
" ImmutableSetMultimap<Object, Object> o10 =",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" ImmutableSetMultimap.copyOf(ImmutableSetMultimap.of());",
|
||||||
|
" // BUG: Diagnostic contains:",
|
||||||
|
" ImmutableTable<Object, Object, Object> o11 = ImmutableTable.copyOf(ImmutableTable.of());",
|
||||||
|
" }",
|
||||||
|
"}")
|
||||||
|
.doTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void replacement() {
|
||||||
|
BugCheckerRefactoringTestHelper.newInstance(
|
||||||
|
Assignment5DeleteIdentityConversion.class, getClass())
|
||||||
|
.addInputLines(
|
||||||
|
"A.java",
|
||||||
|
"import static com.google.errorprone.matchers.Matchers.staticMethod;",
|
||||||
|
"import static org.mockito.Mockito.when;",
|
||||||
|
"",
|
||||||
|
"import com.google.common.collect.ImmutableCollection;",
|
||||||
|
"import com.google.common.collect.ImmutableList;",
|
||||||
|
"import com.google.common.collect.ImmutableSet;",
|
||||||
|
"import java.util.ArrayList;",
|
||||||
|
"import java.util.Collection;",
|
||||||
|
"",
|
||||||
|
"public final class A {",
|
||||||
|
" public void m() {",
|
||||||
|
" ImmutableSet<Object> set1 = ImmutableSet.copyOf(ImmutableSet.of());",
|
||||||
|
" ImmutableSet<Object> set2 = ImmutableSet.copyOf(ImmutableList.of());",
|
||||||
|
"",
|
||||||
|
" ImmutableCollection<Integer> list1 = ImmutableList.copyOf(ImmutableList.of(1));",
|
||||||
|
" ImmutableCollection<Integer> list2 = ImmutableList.copyOf(new ArrayList<>(ImmutableList.of(1)));",
|
||||||
|
"",
|
||||||
|
" Collection<Integer> c1 = ImmutableSet.copyOf(ImmutableSet.of(1));",
|
||||||
|
" Collection<Integer> c2 = ImmutableList.copyOf(new ArrayList<>(ImmutableList.of(1)));",
|
||||||
|
"",
|
||||||
|
" Object o1 = ImmutableSet.copyOf(ImmutableList.of());",
|
||||||
|
" Object o2 = ImmutableSet.copyOf(ImmutableSet.of());",
|
||||||
|
"",
|
||||||
|
" when(\"foo\".contains(\"f\")).thenAnswer(inv -> ImmutableSet.copyOf(ImmutableList.of(1)));",
|
||||||
|
" }",
|
||||||
|
"}")
|
||||||
|
.addOutputLines(
|
||||||
|
"A.java",
|
||||||
|
"import static com.google.errorprone.matchers.Matchers.staticMethod;",
|
||||||
|
"import static org.mockito.Mockito.when;",
|
||||||
|
"",
|
||||||
|
"import com.google.common.collect.ImmutableCollection;",
|
||||||
|
"import com.google.common.collect.ImmutableList;",
|
||||||
|
"import com.google.common.collect.ImmutableSet;",
|
||||||
|
"import java.util.ArrayList;",
|
||||||
|
"import java.util.Collection;",
|
||||||
|
"",
|
||||||
|
"public final class A {",
|
||||||
|
" public void m() {",
|
||||||
|
" ImmutableSet<Object> set1 = ImmutableSet.of();",
|
||||||
|
" ImmutableSet<Object> set2 = ImmutableSet.copyOf(ImmutableList.of());",
|
||||||
|
"",
|
||||||
|
" ImmutableCollection<Integer> list1 = ImmutableList.of(1);",
|
||||||
|
" ImmutableCollection<Integer> list2 = ImmutableList.copyOf(new ArrayList<>(ImmutableList.of(1)));",
|
||||||
|
"",
|
||||||
|
" Collection<Integer> c1 = ImmutableSet.of(1);",
|
||||||
|
" Collection<Integer> c2 = ImmutableList.copyOf(new ArrayList<>(ImmutableList.of(1)));",
|
||||||
|
"",
|
||||||
|
" Object o1 = ImmutableSet.copyOf(ImmutableList.of());",
|
||||||
|
" Object o2 = ImmutableSet.of();",
|
||||||
|
"",
|
||||||
|
" when(\"foo\".contains(\"f\")).thenAnswer(inv -> ImmutableSet.copyOf(ImmutableList.of(1)));",
|
||||||
|
" }",
|
||||||
|
"}")
|
||||||
|
.doTest(TestMode.TEXT_MATCH);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package tech.picnic.errorprone.workshop.refasterrules;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Disabled;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import tech.picnic.errorprone.refaster.test.RefasterRuleCollection;
|
||||||
|
|
||||||
|
final class WorkshopRefasterRulesTest {
|
||||||
|
@Test
|
||||||
|
void validateExampleRuleCollection() {
|
||||||
|
RefasterRuleCollection.validate(WorkshopAssignment0Rules.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Disabled("Needs to be implemented in `WorkshopAssignment1Rules.java`.")
|
||||||
|
@Test
|
||||||
|
void validateFirstWorkshopAssignment() {
|
||||||
|
RefasterRuleCollection.validate(WorkshopAssignment1Rules.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Disabled("Needs to be implemented in `WorkshopAssignment2Rules.java`.")
|
||||||
|
@Test
|
||||||
|
void validateSecondWorkshopAssignment() {
|
||||||
|
RefasterRuleCollection.validate(WorkshopAssignment2Rules.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Disabled("Needs to be implemented in `WorkshopAssignment3Rules.java`.")
|
||||||
|
@Test
|
||||||
|
void validateThirdWorkshopAssignment() {
|
||||||
|
RefasterRuleCollection.validate(WorkshopAssignment3Rules.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Disabled("Needs to be implemented in `WorkshopAssignment4Rules.java`.")
|
||||||
|
@Test
|
||||||
|
void validateFourthWorkshopAssignment() {
|
||||||
|
RefasterRuleCollection.validate(WorkshopAssignment4Rules.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Disabled("Needs to be implemented in `WorkshopAssignment5Rules.java`.")
|
||||||
|
@Test
|
||||||
|
void validateFifthWorkshopAssignment() {
|
||||||
|
RefasterRuleCollection.validate(WorkshopAssignment5Rules.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package tech.picnic.errorprone.workshop.refasterrules;
|
||||||
|
|
||||||
|
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
|
||||||
|
|
||||||
|
final class WorkshopAssignment0RulesTest implements RefasterRuleCollectionTestCase {
|
||||||
|
boolean testExampleStringIsEmpty() {
|
||||||
|
boolean b = "foo".length() == 0;
|
||||||
|
return "bar".length() == 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package tech.picnic.errorprone.workshop.refasterrules;
|
||||||
|
|
||||||
|
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
|
||||||
|
|
||||||
|
final class WorkshopAssignment0RulesTest implements RefasterRuleCollectionTestCase {
|
||||||
|
boolean testExampleStringIsEmpty() {
|
||||||
|
boolean b = "foo".isEmpty();
|
||||||
|
return "bar".isEmpty();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package tech.picnic.errorprone.workshop.refasterrules;
|
||||||
|
|
||||||
|
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
|
||||||
|
|
||||||
|
final class WorkshopAssignment1RulesTest implements RefasterRuleCollectionTestCase {
|
||||||
|
String testNewStringCharArray() {
|
||||||
|
String.copyValueOf(new char[] {});
|
||||||
|
String.copyValueOf(new char[] {'f', 'o', 'o'});
|
||||||
|
return String.copyValueOf(new char[] {'b', 'a', 'r'});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package tech.picnic.errorprone.workshop.refasterrules;
|
||||||
|
|
||||||
|
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
|
||||||
|
|
||||||
|
final class WorkshopAssignment1RulesTest implements RefasterRuleCollectionTestCase {
|
||||||
|
String testNewStringCharArray() {
|
||||||
|
new String(new char[] {});
|
||||||
|
new String(new char[] {'f', 'o', 'o'});
|
||||||
|
return new String(new char[] {'b', 'a', 'r'});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package tech.picnic.errorprone.workshop.refasterrules;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
|
||||||
|
|
||||||
|
final class WorkshopAssignment2RulesTest implements RefasterRuleCollectionTestCase {
|
||||||
|
@Override
|
||||||
|
public ImmutableSet<Object> elidedTypesAndStaticImports() {
|
||||||
|
return ImmutableSet.of(Collections.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Object> testImmutableListOfOne() {
|
||||||
|
Collections.singletonList(1);
|
||||||
|
Collections.singletonList("foo");
|
||||||
|
List.of(1);
|
||||||
|
return List.of("bar");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package tech.picnic.errorprone.workshop.refasterrules;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
|
||||||
|
|
||||||
|
final class WorkshopAssignment2RulesTest implements RefasterRuleCollectionTestCase {
|
||||||
|
@Override
|
||||||
|
public ImmutableSet<Object> elidedTypesAndStaticImports() {
|
||||||
|
return ImmutableSet.of(Collections.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Object> testImmutableListOfOne() {
|
||||||
|
ImmutableList.of(1);
|
||||||
|
ImmutableList.of("foo");
|
||||||
|
ImmutableList.of(1);
|
||||||
|
return ImmutableList.of("bar");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package tech.picnic.errorprone.workshop.refasterrules;
|
||||||
|
|
||||||
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
|
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
|
||||||
|
|
||||||
|
final class WorkshopAssignment3RulesTest implements RefasterRuleCollectionTestCase {
|
||||||
|
void testCheckArgumentWithoutMessage() {
|
||||||
|
if (!"foo".isEmpty()) {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
if (!ThreadLocalRandom.current().nextBoolean()) {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void testCheckArgumentWithMessage() {
|
||||||
|
if (!"foo".isEmpty()) {
|
||||||
|
throw new IllegalArgumentException("The string is not empty");
|
||||||
|
}
|
||||||
|
if (!ThreadLocalRandom.current().nextBoolean()) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"The rule should be able rewrite all kinds of messages ;).");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package tech.picnic.errorprone.workshop.refasterrules;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
|
|
||||||
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
|
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
|
||||||
|
|
||||||
|
final class WorkshopAssignment3RulesTest implements RefasterRuleCollectionTestCase {
|
||||||
|
void testCheckArgumentWithoutMessage() {
|
||||||
|
checkArgument("foo".isEmpty());
|
||||||
|
checkArgument(ThreadLocalRandom.current().nextBoolean());
|
||||||
|
}
|
||||||
|
|
||||||
|
void testCheckArgumentWithMessage() {
|
||||||
|
checkArgument("foo".isEmpty(), "The string is not empty");
|
||||||
|
checkArgument(
|
||||||
|
ThreadLocalRandom.current().nextBoolean(),
|
||||||
|
"The rule should be able rewrite all kinds of messages ;).");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package tech.picnic.errorprone.workshop.refasterrules;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import java.math.RoundingMode;
|
||||||
|
import java.util.Objects;
|
||||||
|
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
|
||||||
|
|
||||||
|
final class WorkshopAssignment4RulesTest implements RefasterRuleCollectionTestCase {
|
||||||
|
@Override
|
||||||
|
public ImmutableSet<Object> elidedTypesAndStaticImports() {
|
||||||
|
return ImmutableSet.of(Objects.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImmutableSet<Boolean> testPrimitiveOrReferenceEqualityEnum() {
|
||||||
|
// Don't pay attention to the `ImmutableSet#of` here, it's just syntactical sugar for the
|
||||||
|
// testing framework.
|
||||||
|
return ImmutableSet.of(
|
||||||
|
"foo".equals("bar"),
|
||||||
|
Integer.valueOf(1).equals(2),
|
||||||
|
RoundingMode.UP.equals(RoundingMode.DOWN),
|
||||||
|
Objects.equals(RoundingMode.UP, RoundingMode.DOWN),
|
||||||
|
!RoundingMode.UP.equals(RoundingMode.DOWN),
|
||||||
|
!Objects.equals(RoundingMode.UP, RoundingMode.DOWN));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package tech.picnic.errorprone.workshop.refasterrules;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import java.math.RoundingMode;
|
||||||
|
import java.util.Objects;
|
||||||
|
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
|
||||||
|
|
||||||
|
final class WorkshopAssignment4RulesTest implements RefasterRuleCollectionTestCase {
|
||||||
|
@Override
|
||||||
|
public ImmutableSet<Object> elidedTypesAndStaticImports() {
|
||||||
|
return ImmutableSet.of(Objects.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImmutableSet<Boolean> testPrimitiveOrReferenceEqualityEnum() {
|
||||||
|
// Don't pay attention to the `ImmutableSet#of` here, it's just syntactical sugar for the
|
||||||
|
// testing framework.
|
||||||
|
return ImmutableSet.of(
|
||||||
|
"foo".equals("bar"),
|
||||||
|
Integer.valueOf(1).equals(2),
|
||||||
|
RoundingMode.UP == RoundingMode.DOWN,
|
||||||
|
RoundingMode.UP == RoundingMode.DOWN,
|
||||||
|
RoundingMode.UP != RoundingMode.DOWN,
|
||||||
|
RoundingMode.UP != RoundingMode.DOWN);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package tech.picnic.errorprone.workshop.refasterrules;
|
||||||
|
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
|
||||||
|
|
||||||
|
final class WorkshopAssignment5RulesTest implements RefasterRuleCollectionTestCase {
|
||||||
|
boolean testStreamDoAllMatch() {
|
||||||
|
boolean example = Stream.of("foo").noneMatch(s -> !s.isBlank());
|
||||||
|
return Stream.of("bar").noneMatch(b -> !b.startsWith("b"));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package tech.picnic.errorprone.workshop.refasterrules;
|
||||||
|
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
import tech.picnic.errorprone.refaster.test.RefasterRuleCollectionTestCase;
|
||||||
|
|
||||||
|
final class WorkshopAssignment5RulesTest implements RefasterRuleCollectionTestCase {
|
||||||
|
boolean testStreamDoAllMatch() {
|
||||||
|
boolean example = Stream.of("foo").allMatch(s -> s.isBlank());
|
||||||
|
return Stream.of("bar").allMatch(b -> b.startsWith("b"));
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user