blob: 46d7e5cf62658ba6e9ed7e8694f667329cdea997 [file] [log] [blame]
/*
* 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.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.Reporter
import com.android.tools.lint.TextReporter
import com.android.tools.lint.XmlReporter
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 {
public static final String STDOUT = "stdout"
@Input
private Set<String> disable = Sets.newHashSet()
@Input
private Set<String> enable = Sets.newHashSet()
@Input
private Set<String> check = Sets.newHashSet()
@Input
private boolean abortOnError
@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
@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
public LintOptionsImpl() {
}
public LintOptionsImpl(
@Nullable Set<String> disable,
@Nullable Set<String> enable,
@Nullable Set<String> 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) {
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
}
@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()
)
}
/**
* Returns the set of issue id's to suppress. Callers are allowed to modify this collection.
*/
@NonNull
public Set<String> 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<String> 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<String> 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<String> 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<String> getCheck() {
return check
}
/**
* Sets the <b>exact</b> set of issues to check.
* @param ids the set of issue id's to check
*/
public void setCheck(@Nullable Set<String> 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
}
/**
* 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 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)
if (report) {
if (textReport) {
File output = textOutput
if (output == null) {
output = new File(STDOUT)
} else if (!output.isAbsolute() && !isStdOut(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 {
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 (xmlReport) {
File output = xmlOutput
if (output == null) {
output = createOutputPath(project, variantName, DOT_XML)
} 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)
}
}
if (htmlReport) {
File output = htmlOutput
if (output == null) {
output = createOutputPath(project, variantName, ".html")
} 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)
}
}
Map<String, String> map = new HashMap<String, String>() {{
put("", "file://")
}}
for (Reporter reporter : flags.getReporters()) {
reporter.setUrlMap(map)
}
}
}
private static boolean isStdOut(@NonNull File output) {
return STDOUT.equals(output.getPath())
}
@NonNull
private static File validateOutputFile(@NonNull File output) {
if (isStdOut(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) {
StringBuilder base = new StringBuilder()
base.append("lint-results")
if (variantName != null) {
base.append("-")
base.append(variantName)
}
base.append(extension)
return new File(project.buildDir, base.toString())
}
// -- DSL Methods. TODO remove once the instantiator does what I expect it to do.
public void check(String id) {
check.add(id)
}
public void check(String... ids) {
check.addAll(ids)
}
public void enable(String id) {
enable.add(id)
}
public void enable(String... ids) {
enable.addAll(ids)
}
public void disable(String id) {
disable.add(id)
}
public void disable(String... ids) {
disable.addAll(ids)
}
// For textOutput 'stdout' (normally a file)
void textOutput(String textOutput) {
this.textOutput = new File(textOutput)
}
// For textOutput file()
void textOutput(File textOutput) {
this.textOutput = textOutput;
}
}