
com.android.build.gradle.internal.dsl.LintOptionsImpl.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.builder.model.LintOptions
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
public class LintOptionsImpl implements 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 = true
@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 LintOptionsImpl() {
}
public LintOptionsImpl(
@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 LintOptions create(@NonNull LintOptions source) {
return new LintOptionsImpl(
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 {@link com.android.tools.lint.detector.api.Issue#getId()} 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 show progress dots for each analyzed
* file)
*/
public boolean isQuiet() {
return quiet
}
/**
* Sets whether lint should be quiet (for example, not show progress dots for each analyzed
* file)
*/
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
}
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
}
@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
}
@Override
boolean getTextReport() {
return textReport
}
void setTextReport(boolean textReport) {
this.textReport = textReport
}
void setTextOutput(@NonNull File textOutput) {
this.textOutput = textOutput
}
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
}
@Override
File getTextOutput() {
return textOutput
}
@Override
boolean getHtmlReport() {
return htmlReport
}
@Override
File getHtmlOutput() {
return htmlOutput
}
@Override
boolean getXmlReport() {
return xmlReport
}
@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())
}
@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.
public void check(String id) {
check.add(id)
}
public void check(String... ids) {
for (String id : ids) {
check(id);
}
}
public void enable(String id) {
enable.add(id)
def issue = new BuiltinIssueRegistry().getIssue(id)
severities.put(id, issue != null ? issue.defaultSeverity : Severity.WARNING)
}
public void enable(String... ids) {
for (String id : ids) {
enable(id);
}
}
public void disable(String id) {
disable.add(id)
severities.put(id, Severity.IGNORE)
}
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;
}
public void fatal(String id) {
severities.put(id, Severity.FATAL)
}
public void fatal(String... ids) {
for (String id : ids) {
fatal(id);
}
}
public void error(String id) {
severities.put(id, Severity.ERROR)
}
public void error(String... ids) {
for (String id : ids) {
error(id);
}
}
public void warning(String id) {
severities.put(id, Severity.WARNING)
}
public void warning(String... ids) {
for (String id : ids) {
warning(id);
}
}
public void ignore(String id) {
severities.put(id, Severity.IGNORE)
}
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 LintOptions.SEVERITY_FATAL
case Severity.ERROR:
return LintOptions.SEVERITY_ERROR
case Severity.WARNING:
return LintOptions.SEVERITY_WARNING
case Severity.INFORMATIONAL:
return LintOptions.SEVERITY_INFORMATIONAL
case Severity.IGNORE:
default:
return LintOptions.SEVERITY_IGNORE
}
}
@SuppressWarnings("UnnecessaryQualifiedReference")
private static Severity convert(int s) {
switch (s) {
case LintOptions.SEVERITY_FATAL:
return Severity.FATAL
case LintOptions.SEVERITY_ERROR:
return Severity.ERROR
case LintOptions.SEVERITY_WARNING:
return Severity.WARNING
case LintOptions.SEVERITY_INFORMATIONAL:
return Severity.INFORMATIONAL
case LintOptions.SEVERITY_IGNORE:
default:
return Severity.IGNORE
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy