com.android.build.gradle.internal.LintGradleClient Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gradle-core Show documentation
Show all versions of gradle-core Show documentation
Core library to build Android Gradle plugin.
/*
* 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;
import static com.android.builder.model.AndroidProject.FD_INTERMEDIATES;
import static java.io.File.separator;
import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
import com.android.builder.model.AndroidProject;
import com.android.builder.model.Variant;
import com.android.sdklib.BuildToolInfo;
import com.android.tools.lint.LintCliClient;
import com.android.tools.lint.LintCliFlags;
import com.android.tools.lint.Warning;
import com.android.tools.lint.checks.UnusedResourceDetector;
import com.android.tools.lint.client.api.IssueRegistry;
import com.android.tools.lint.client.api.LintRequest;
import com.android.tools.lint.detector.api.Issue;
import com.android.tools.lint.detector.api.Project;
import com.android.utils.Pair;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
public class LintGradleClient extends LintCliClient {
private final AndroidProject mModelProject;
/**
* Variant to run the client on.
*/
@NonNull private Variant mVariant;
private final org.gradle.api.Project mGradleProject;
private List mCustomRules = Lists.newArrayList();
private File mSdkHome;
private final BuildToolInfo mBuildToolInfo;
public LintGradleClient(
@NonNull IssueRegistry registry,
@NonNull LintCliFlags flags,
@NonNull org.gradle.api.Project gradleProject,
@NonNull AndroidProject modelProject,
@Nullable File sdkHome,
@NonNull Variant variant,
@Nullable BuildToolInfo buildToolInfo) {
super(flags, CLIENT_GRADLE);
mGradleProject = gradleProject;
mModelProject = modelProject;
mSdkHome = sdkHome;
mRegistry = registry;
mBuildToolInfo = buildToolInfo;
mVariant = variant;
}
public void setCustomRules(List customRules) {
mCustomRules = customRules;
}
@NonNull
@Override
public List findRuleJars(@NonNull Project project) {
return mCustomRules;
}
@NonNull
@Override
protected Project createProject(@NonNull File dir, @NonNull File referenceDir) {
// Should not be called by lint since we supply an explicit set of projects
// to the LintRequest
throw new IllegalStateException();
}
@Override
public File getSdkHome() {
if (mSdkHome != null) {
return mSdkHome;
}
return super.getSdkHome();
}
@Override
@Nullable
public File getCacheDir(boolean create) {
File dir = new File(mGradleProject.getRootProject().getBuildDir(),
FD_INTERMEDIATES + separator + "lint-cache"); //$NON-NLS-1$
if (dir.exists() || create && dir.mkdirs()) {
return dir;
}
return super.getCacheDir(create);
}
@Override
@NonNull
protected LintRequest createLintRequest(@NonNull List files) {
LintRequest lintRequest = new LintRequest(this, files);
if (mVariant == null) {
lintRequest.setProjects(Lists.newArrayList());
} else {
Pair> result = LintGradleProject.create(
this, mModelProject, mVariant, mGradleProject);
lintRequest.setProjects(Collections.singletonList(result.getFirst()));
setCustomRules(result.getSecond());
}
return lintRequest;
}
/** Run lint with the given registry and return the resulting warnings */
@NonNull
public List run(@NonNull IssueRegistry registry) throws IOException {
run(registry, Collections.emptyList());
return mWarnings;
}
/**
* Given a list of results from separate variants, merge them into a single
* list of warnings, and mark their
* @param warningMap a map from variant to corresponding warnings
* @param project the project model
* @return a merged list of issues
*/
@NonNull
public static List merge(
@NonNull Map> warningMap,
@NonNull AndroidProject project) {
// Easy merge?
if (warningMap.size() == 1) {
return warningMap.values().iterator().next();
}
int maxCount = 0;
for (List warnings : warningMap.values()) {
int size = warnings.size();
maxCount = Math.max(size, maxCount);
}
if (maxCount == 0) {
return Collections.emptyList();
}
int totalVariantCount = project.getVariants().size();
List merged = Lists.newArrayListWithExpectedSize(2 * maxCount);
// Map fro issue to message to line number to file name to canonical warning
Map>>> map =
Maps.newHashMapWithExpectedSize(2 * maxCount);
for (Map.Entry> entry : warningMap.entrySet()) {
Variant variant = entry.getKey();
List warnings = entry.getValue();
for (Warning warning : warnings) {
Map>> messageMap = map.get(warning.issue);
if (messageMap == null) {
messageMap = Maps.newHashMap();
map.put(warning.issue, messageMap);
}
Map> lineMap = messageMap.get(warning.message);
if (lineMap == null) {
lineMap = Maps.newHashMap();
messageMap.put(warning.message, lineMap);
}
Map fileMap = lineMap.get(warning.line);
if (fileMap == null) {
fileMap = Maps.newHashMap();
lineMap.put(warning.line, fileMap);
}
String fileName = warning.file != null ? warning.file.getName() : "";
Warning canonical = fileMap.get(fileName);
if (canonical == null) {
canonical = warning;
fileMap.put(fileName, canonical);
canonical.variants = Sets.newHashSet();
canonical.gradleProject = project;
merged.add(canonical);
}
canonical.variants.add(variant);
}
}
// Clear out variants on any nodes that define all
for (Warning warning : merged) {
if (warning.variants != null && warning.variants.size() == totalVariantCount) {
// If this error is present in all variants, just clear it out
warning.variants = null;
}
}
Collections.sort(merged);
return merged;
}
@Override
protected void addProgressPrinter() {
// No progress printing from the Gradle lint task; gradle tasks
// do not really do that, even for long-running jobs.
}
@Nullable
@Override
public BuildToolInfo getBuildTools(@NonNull Project project) {
return mBuildToolInfo;
}
}