![JAR search and dependency download from the Maven repository](/logo.png)
com.android.build.gradle.internal.dsl.LintOptions.groovy Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gradle Show documentation
Show all versions of gradle Show documentation
Gradle plug-in to build Android applications.
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.build.gradle.internal.dsl
import com.android.tools.lint.checks.BuiltinIssueRegistry
import static com.android.builder.model.AndroidProject.FD_OUTPUTS
import com.android.annotations.NonNull
import com.android.annotations.Nullable
import com.android.tools.lint.HtmlReporter
import com.android.tools.lint.LintCliClient
import com.android.tools.lint.LintCliFlags
import com.android.tools.lint.TextReporter
import com.android.tools.lint.XmlReporter
import com.android.tools.lint.detector.api.Severity
import com.google.common.collect.Maps
import com.google.common.collect.Sets
import org.gradle.api.GradleException
import org.gradle.api.Project
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.InputFile
import org.gradle.api.tasks.OutputFile
import static com.android.SdkConstants.DOT_XML
/**
* DSL object for configuring lint options.
*/
public class LintOptions implements com.android.builder.model.LintOptions, Serializable {
public static final String STDOUT = "stdout"
public static final String STDERR = "stderr"
private static final long serialVersionUID = 1L;
@Input
private Set disable = Sets.newHashSet()
@Input
private Set enable = Sets.newHashSet()
@Input
private Set check = Sets.newHashSet()
@Input
private boolean abortOnError = true
@Input
private boolean absolutePaths = true
@Input
private boolean noLines
@Input
private boolean quiet
@Input
private boolean checkAllWarnings
@Input
private boolean ignoreWarnings
@Input
private boolean warningsAsErrors
@Input
private boolean showAll
@Input
private boolean checkReleaseBuilds = true;
@Input
private boolean explainIssues = true;
@InputFile
private File lintConfig
@Input
private boolean textReport
@OutputFile
private File textOutput
@Input
private boolean htmlReport = true
@OutputFile
private File htmlOutput
@Input
private boolean xmlReport = true
@OutputFile
private File xmlOutput
private Map severities = Maps.newHashMap();
public LintOptions() {
}
public LintOptions(
@Nullable Set disable,
@Nullable Set enable,
@Nullable Set check,
@Nullable File lintConfig,
boolean textReport,
@Nullable File textOutput,
boolean htmlReport,
@Nullable File htmlOutput,
boolean xmlReport,
@Nullable File xmlOutput,
boolean abortOnError,
boolean absolutePaths,
boolean noLines,
boolean quiet,
boolean checkAllWarnings,
boolean ignoreWarnings,
boolean warningsAsErrors,
boolean showAll,
boolean explainIssues,
boolean checkReleaseBuilds,
@Nullable Map severityOverrides) {
this.disable = disable
this.enable = enable
this.check = check
this.lintConfig = lintConfig
this.textReport = textReport
this.textOutput = textOutput
this.htmlReport = htmlReport
this.htmlOutput = htmlOutput
this.xmlReport = xmlReport
this.xmlOutput = xmlOutput
this.abortOnError = abortOnError
this.absolutePaths = absolutePaths
this.noLines = noLines
this.quiet = quiet
this.checkAllWarnings = checkAllWarnings
this.ignoreWarnings = ignoreWarnings
this.warningsAsErrors = warningsAsErrors
this.showAll = showAll
this.explainIssues = explainIssues
this.checkReleaseBuilds = checkReleaseBuilds
if (severityOverrides != null) {
for (Map.Entry entry : severityOverrides.entrySet()) {
severities.put(entry.key, convert(entry.value))
}
}
}
@NonNull
static com.android.builder.model.LintOptions create(@NonNull com.android.builder.model.LintOptions source) {
return new LintOptions(
source.getDisable(),
source.getEnable(),
source.getCheck(),
source.getLintConfig(),
source.getTextReport(),
source.getTextOutput(),
source.getHtmlReport(),
source.getHtmlOutput(),
source.getXmlReport(),
source.getXmlOutput(),
source.isAbortOnError(),
source.isAbsolutePaths(),
source.isNoLines(),
source.isQuiet(),
source.isCheckAllWarnings(),
source.isIgnoreWarnings(),
source.isWarningsAsErrors(),
source.isShowAll(),
source.isExplainIssues(),
source.isCheckReleaseBuilds(),
source.getSeverityOverrides()
)
}
/**
* Returns the set of issue id's to suppress. Callers are allowed to modify this collection.
*/
@NonNull
public Set getDisable() {
return disable
}
/**
* Sets the set of issue id's to suppress. Callers are allowed to modify this collection.
* Note that these ids add to rather than replace the given set of ids.
*/
public void setDisable(@Nullable Set ids) {
disable.addAll(ids)
}
/**
* Returns the set of issue id's to enable. Callers are allowed to modify this collection.
* To enable a given issue, add the issue ID to the returned set.
*/
@NonNull
public Set getEnable() {
return enable
}
/**
* Sets the set of issue id's to enable. Callers are allowed to modify this collection.
* Note that these ids add to rather than replace the given set of ids.
*/
public void setEnable(@Nullable Set ids) {
enable.addAll(ids)
}
/**
* Returns the exact set of issues to check, or null to run the issues that are enabled
* by default plus any issues enabled via {@link #getEnable} and without issues disabled
* via {@link #getDisable}. If non-null, callers are allowed to modify this collection.
*/
@Nullable
public Set getCheck() {
return check
}
/**
* Sets the exact set of issues to check.
* @param ids the set of issue id's to check
*/
public void setCheck(@Nullable Set ids) {
check.addAll(ids)
}
/** Whether lint should set the exit code of the process if errors are found */
public boolean isAbortOnError() {
return this.abortOnError
}
/** Sets whether lint should set the exit code of the process if errors are found */
public void setAbortOnError(boolean abortOnError) {
this.abortOnError = abortOnError
}
/**
* Whether lint should display full paths in the error output. By default the paths
* are relative to the path lint was invoked from.
*/
public boolean isAbsolutePaths() {
return absolutePaths
}
/**
* Sets whether lint should display full paths in the error output. By default the paths
* are relative to the path lint was invoked from.
*/
public void setAbsolutePaths(boolean absolutePaths) {
this.absolutePaths = absolutePaths
}
/**
* Whether lint should include the source lines in the output where errors occurred
* (true by default)
*/
public boolean isNoLines() {
return this.noLines
}
/**
* Sets whether lint should include the source lines in the output where errors occurred
* (true by default)
*/
public void setNoLines(boolean noLines) {
this.noLines = noLines
}
/**
* Returns whether lint should be quiet (for example, not write informational messages
* such as paths to report files written)
*/
public boolean isQuiet() {
return quiet
}
/**
* Sets whether lint should be quiet (for example, not write informational messages
* such as paths to report files written)
*/
public void setQuiet(boolean quiet) {
this.quiet = quiet
}
/** Returns whether lint should check all warnings, including those off by default */
public boolean isCheckAllWarnings() {
return checkAllWarnings
}
/** Sets whether lint should check all warnings, including those off by default */
public void setCheckAllWarnings(boolean warnAll) {
this.checkAllWarnings = warnAll
}
/** Returns whether lint will only check for errors (ignoring warnings) */
public boolean isIgnoreWarnings() {
return ignoreWarnings
}
/** Sets whether lint will only check for errors (ignoring warnings) */
public void setIgnoreWarnings(boolean noWarnings) {
this.ignoreWarnings = noWarnings
}
/** Returns whether lint should treat all warnings as errors */
public boolean isWarningsAsErrors() {
return warningsAsErrors
}
/** Sets whether lint should treat all warnings as errors */
public void setWarningsAsErrors(boolean allErrors) {
this.warningsAsErrors = allErrors
}
/** Returns whether lint should include explanations for issue errors. (Note that
* HTML and XML reports intentionally do this unconditionally, ignoring this setting.) */
public boolean isExplainIssues() {
return explainIssues
}
public void setExplainIssues(boolean explainIssues) {
this.explainIssues = explainIssues
}
/**
* Returns whether lint should include all output (e.g. include all alternate
* locations, not truncating long messages, etc.)
*/
public boolean isShowAll() {
return showAll
}
/**
* Sets whether lint should include all output (e.g. include all alternate
* locations, not truncating long messages, etc.)
*/
public void setShowAll(boolean showAll) {
this.showAll = showAll
}
/**
* Returns whether lint should check for fatal errors during release builds. Default is true.
* If issues with severity "fatal" are found, the release build is aborted.
*/
@Override
public boolean isCheckReleaseBuilds() {
return checkReleaseBuilds;
}
public void setCheckReleaseBuilds(boolean checkReleaseBuilds) {
this.checkReleaseBuilds = checkReleaseBuilds
}
/**
* Returns the default configuration file to use as a fallback
*/
public File getLintConfig() {
return lintConfig
}
/** Whether we should write an text report. Default false. The location can be
* controlled by {@link #getTextOutput()}. */
@Override
boolean getTextReport() {
return textReport
}
void setTextReport(boolean textReport) {
this.textReport = textReport
}
void setHtmlReport(boolean htmlReport) {
this.htmlReport = htmlReport
}
void setHtmlOutput(@NonNull File htmlOutput) {
this.htmlOutput = htmlOutput
}
void setXmlReport(boolean xmlReport) {
this.xmlReport = xmlReport
}
void setXmlOutput(@NonNull File xmlOutput) {
this.xmlOutput = xmlOutput
}
/**
* The optional path to where a text report should be written. The special value
* "stdout" can be used to point to standard output.
*/
@Override
File getTextOutput() {
return textOutput
}
/** Whether we should write an HTML report. Default true. The location can be
* controlled by {@link #getHtmlOutput()}. */
@Override
boolean getHtmlReport() {
return htmlReport
}
/** The optional path to where an HTML report should be written */
@Override
File getHtmlOutput() {
return htmlOutput
}
/** Whether we should write an XML report. Default true. The location can be
* controlled by {@link #getXmlOutput()}. */
@Override
boolean getXmlReport() {
return xmlReport
}
/** The optional path to where an XML report should be written */
@Override
File getXmlOutput() {
return xmlOutput
}
/**
* Sets the default config file to use as a fallback. This corresponds to a {@code lint.xml}
* file with severities etc to use when a project does not have more specific information.
*/
public void setLintConfig(@NonNull File lintConfig) {
this.lintConfig = lintConfig
}
public void syncTo(
@NonNull LintCliClient client,
@NonNull LintCliFlags flags,
@Nullable String variantName,
@Nullable Project project,
boolean report) {
if (disable != null) {
flags.getSuppressedIds().addAll(disable)
}
if (enable != null) {
flags.getEnabledIds().addAll(enable)
}
if (check != null && !check.isEmpty()) {
flags.setExactCheckedIds(check)
}
flags.setSetExitCode(this.abortOnError)
flags.setFullPath(absolutePaths)
flags.setShowSourceLines(!noLines)
flags.setQuiet(quiet)
flags.setCheckAllWarnings(checkAllWarnings)
flags.setIgnoreWarnings(ignoreWarnings)
flags.setWarningsAsErrors(warningsAsErrors)
flags.setShowEverything(showAll)
flags.setDefaultConfiguration(lintConfig)
flags.setSeverityOverrides(severities)
flags.setExplainIssues(explainIssues)
if (report || flags.isFatalOnly() && this.abortOnError) {
if (textReport || flags.isFatalOnly()) {
File output = textOutput
if (output == null) {
output = new File(flags.isFatalOnly() ? STDERR: STDOUT)
} else if (!output.isAbsolute() && !isStdOut(output) && !isStdErr(output)) {
output = project.file(output.getPath())
}
output = validateOutputFile(output)
Writer writer
File file = null
boolean closeWriter
if (isStdOut(output)) {
writer = new PrintWriter(System.out, true)
closeWriter = false
} else if (isStdErr(output)) {
writer = new PrintWriter(System.err, true)
closeWriter = false
} else {
file = output
try {
writer = new BufferedWriter(new FileWriter(output))
} catch (IOException e) {
throw new GradleException("Text invalid argument.", e)
}
closeWriter = true
}
flags.getReporters().add(new TextReporter(client, flags, file, writer,
closeWriter))
}
if (htmlReport) {
File output = htmlOutput
if (output == null || flags.isFatalOnly()) {
output = createOutputPath(project, variantName, ".html", flags.isFatalOnly())
} else if (!output.isAbsolute()) {
output = project.file(output.getPath())
}
output = validateOutputFile(output)
try {
flags.getReporters().add(new HtmlReporter(client, output))
} catch (IOException e) {
throw new GradleException("HTML invalid argument.", e)
}
}
if (xmlReport) {
File output = xmlOutput
if (output == null || flags.isFatalOnly()) {
output = createOutputPath(project, variantName, DOT_XML, flags.isFatalOnly())
} else if (!output.isAbsolute()) {
output = project.file(output.getPath())
}
output = validateOutputFile(output)
try {
flags.getReporters().add(new XmlReporter(client, output))
} catch (IOException e) {
throw new GradleException("XML invalid argument.", e)
}
}
}
}
private static boolean isStdOut(@NonNull File output) {
return STDOUT.equals(output.getPath())
}
private static boolean isStdErr(@NonNull File output) {
return STDERR.equals(output.getPath())
}
@NonNull
private static File validateOutputFile(@NonNull File output) {
if (isStdOut(output) || isStdErr(output)) {
return output
}
File parent = output.parentFile
if (!parent.exists()) {
parent.mkdirs()
}
output = output.getAbsoluteFile()
if (output.exists()) {
boolean delete = output.delete()
if (!delete) {
throw new GradleException("Could not delete old " + output)
}
}
if (output.getParentFile() != null && !output.getParentFile().canWrite()) {
throw new GradleException("Cannot write output file " + output)
}
return output
}
private static File createOutputPath(
@NonNull Project project,
@NonNull String variantName,
@NonNull String extension,
boolean fatalOnly) {
StringBuilder base = new StringBuilder()
base.append(FD_OUTPUTS)
base.append(File.separator)
base.append("lint-results")
if (variantName != null) {
base.append("-")
base.append(variantName)
}
if (fatalOnly) {
base.append("-fatal")
}
base.append(extension)
return new File(project.buildDir, base.toString())
}
/**
* An optional map of severity overrides. The map maps from issue id's to the corresponding
* severity to use, which must be "fatal", "error", "warning", or "ignore".
*
* @return a map of severity overrides, or null. The severities are one of the constants
* {@link #SEVERITY_FATAL}, {@link #SEVERITY_ERROR}, {@link #SEVERITY_WARNING},
* {@link #SEVERITY_INFORMATIONAL}, {@link #SEVERITY_IGNORE}
*/
@Override
@Nullable
public Map getSeverityOverrides() {
if (severities == null || severities.isEmpty()) {
return null
}
Map map =
Maps.newHashMapWithExpectedSize(severities.size())
for (Map.Entry entry : severities.entrySet()) {
map.put(entry.key, convert(entry.value))
}
return map
}
// -- DSL Methods.
/**
* Adds the id to the set of issues to check.
*/
public void check(String id) {
check.add(id)
}
/**
* Adds the ids to the set of issues to check.
*/
public void check(String... ids) {
for (String id : ids) {
check(id);
}
}
/**
* Adds the id to the set of issues to enable.
*/
public void enable(String id) {
enable.add(id)
def issue = new BuiltinIssueRegistry().getIssue(id)
severities.put(id, issue != null ? issue.defaultSeverity : Severity.WARNING)
}
/**
* Adds the ids to the set of issues to enable.
*/
public void enable(String... ids) {
for (String id : ids) {
enable(id);
}
}
/**
* Adds the id to the set of issues to enable.
*/
public void disable(String id) {
disable.add(id)
severities.put(id, Severity.IGNORE)
}
/**
* Adds the ids to the set of issues to enable.
*/
public void disable(String... ids) {
for (String id : ids) {
disable(id);
}
}
// For textOutput 'stdout' or 'stderr' (normally a file)
void textOutput(String textOutput) {
this.textOutput = new File(textOutput)
}
// For textOutput file()
void textOutput(File textOutput) {
this.textOutput = textOutput;
}
/**
* Adds a severity override for the given issues.
*/
public void fatal(String id) {
severities.put(id, Severity.FATAL)
}
/**
* Adds a severity override for the given issues.
*/
public void fatal(String... ids) {
for (String id : ids) {
fatal(id);
}
}
/**
* Adds a severity override for the given issues.
*/
public void error(String id) {
severities.put(id, Severity.ERROR)
}
/**
* Adds a severity override for the given issues.
*/
public void error(String... ids) {
for (String id : ids) {
error(id);
}
}
/**
* Adds a severity override for the given issues.
*/
public void warning(String id) {
severities.put(id, Severity.WARNING)
}
/**
* Adds a severity override for the given issues.
*/
public void warning(String... ids) {
for (String id : ids) {
warning(id);
}
}
/**
* Adds a severity override for the given issues.
*/
public void ignore(String id) {
severities.put(id, Severity.IGNORE)
}
/**
* Adds a severity override for the given issues.
*/
public void ignore(String... ids) {
for (String id : ids) {
ignore(id);
}
}
// Without these qualifiers, Groovy compilation will fail with "Apparent variable
// 'SEVERITY_FATAL' was found in a static scope but doesn't refer to a local variable,
// static field or class"
@SuppressWarnings("UnnecessaryQualifiedReference")
private static int convert(Severity s) {
switch (s) {
case Severity.FATAL:
return com.android.builder.model.LintOptions.SEVERITY_FATAL
case Severity.ERROR:
return com.android.builder.model.LintOptions.SEVERITY_ERROR
case Severity.WARNING:
return com.android.builder.model.LintOptions.SEVERITY_WARNING
case Severity.INFORMATIONAL:
return com.android.builder.model.LintOptions.SEVERITY_INFORMATIONAL
case Severity.IGNORE:
default:
return com.android.builder.model.LintOptions.SEVERITY_IGNORE
}
}
@SuppressWarnings("UnnecessaryQualifiedReference")
private static Severity convert(int s) {
switch (s) {
case com.android.builder.model.LintOptions.SEVERITY_FATAL:
return Severity.FATAL
case com.android.builder.model.LintOptions.SEVERITY_ERROR:
return Severity.ERROR
case com.android.builder.model.LintOptions.SEVERITY_WARNING:
return Severity.WARNING
case com.android.builder.model.LintOptions.SEVERITY_INFORMATIONAL:
return Severity.INFORMATIONAL
case com.android.builder.model.LintOptions.SEVERITY_IGNORE:
default:
return Severity.IGNORE
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy