blob: a8da4d9fe58a0f719e8071b0ff35e2f60b522fb6 [file] [log] [blame]
/*
* Copyright 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.build
import org.gradle.api.DefaultTask
import org.gradle.api.GradleException
import org.gradle.api.Project
import org.gradle.api.tasks.Internal
import org.gradle.api.tasks.TaskAction
import org.gradle.api.tasks.options.Option
import org.jetbrains.kotlin.konan.file.File
// first level line filter - we ignore lines that don't contain the following for speed
const val ROOT_MATCH = "noinspection"
// Map of invalid pattern to correct replacement
// These could be regex for fancy whitespace matching, but don't seem to need in practice
val MATCHERS = mapOf(
"//noinspection deprecation" to "@SuppressWarnings(\"deprecation\")",
"//noinspection unchecked" to "@SuppressWarnings(\"unchecked\")"
)
open class CheckInvalidSuppressTask : DefaultTask() {
@Option(option = "files", description = "List of files to check")
@Internal
lateinit var filenamesOption: String
@Option(
option = "format",
description = "Use --format to auto-correct invalid suppressions"
)
@Internal
var autocorrectOption = false
// Check a line for any invalid suppressions, and return it if found
fun getInvalidSuppression(line: String): String {
MATCHERS.keys.forEach { bad ->
if (line.trimStart().startsWith(bad)) {
return bad
}
}
return ""
}
// Get report for line with invalid suppression
fun getReportForLine(filename: String, i: Int, lines: List<String>, good: String): String {
var context = ""
for (index in 0..2) {
if (index + i >= lines.size) break
context += lines[index + i] + "\n"
}
return "\n%s:%d:\nError: unsupported comment suppression\n%sInstead, use: %s\n"
.format(
filename, i, context, good
)
}
@TaskAction
fun checkForInvalidSuppression() {
val filenames = filenamesOption.split(" ")
var report = ""
for (filename in filenames) {
// suppress comments ignored in kotlin, but may as well block there too
if (!filename.endsWith(".java") && !filename.endsWith(".kt"))
continue
// check file exists
if (!File(filename).exists)
continue
val lines = File(filename).readStrings()
for ((i, line) in lines.withIndex()) {
if (line.contains(ROOT_MATCH)) {
val bad = getInvalidSuppression(line)
if (bad != "") {
if (autocorrectOption) {
if (line.trimStart() == bad) {
lines[i] = line.replaceFirst(bad, MATCHERS[bad]!!)
} else {
lines[i] = line.replaceFirst(bad, MATCHERS[bad]!! + " // ")
}
File(filename).writeLines(lines)
} else {
report += getReportForLine(filename, i, lines, MATCHERS[bad]!!)
}
}
}
}
}
if (report != "") {
throw GradleException(
"Invalid, IDEA-specific warning suppression found. These cause " +
"warnings during compilation." + "\n" + report
)
}
}
}
fun Project.configureCheckInvalidSuppress() {
tasks.register("checkInvalidSuppress", CheckInvalidSuppressTask::class.java) { task ->
task.description = "Task used to find IDEA-specific warning suppressions that do not " +
"work for command line builds."
task.group = "Verification"
}
}