diff options
Diffstat (limited to 'gradle/src/main/groovy/com/android/build/gradle/internal/LintGradleClient.java')
-rw-r--r-- | gradle/src/main/groovy/com/android/build/gradle/internal/LintGradleClient.java | 119 |
1 files changed, 116 insertions, 3 deletions
diff --git a/gradle/src/main/groovy/com/android/build/gradle/internal/LintGradleClient.java b/gradle/src/main/groovy/com/android/build/gradle/internal/LintGradleClient.java index 6ebb37f..3bf7b8d 100644 --- a/gradle/src/main/groovy/com/android/build/gradle/internal/LintGradleClient.java +++ b/gradle/src/main/groovy/com/android/build/gradle/internal/LintGradleClient.java @@ -17,24 +17,45 @@ package com.android.build.gradle.internal; import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; import com.android.annotations.NonNull; import com.android.annotations.Nullable; import com.android.build.gradle.BasePlugin; +import com.android.builder.model.AndroidProject; +import com.android.builder.model.Variant; import com.android.tools.lint.LintCliClient; import com.android.tools.lint.LintCliFlags; +import com.android.tools.lint.Warning; +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 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; + private final String mVariantName; + private final BasePlugin mPlugin; private List<File> mCustomRules = Lists.newArrayList(); - private BasePlugin mPlugin; - public LintGradleClient(@NonNull LintCliFlags flags, @NonNull BasePlugin plugin) { + public LintGradleClient( + @NonNull IssueRegistry registry, + @NonNull LintCliFlags flags, + @NonNull BasePlugin plugin, + @NonNull AndroidProject modelProject, + @Nullable String variantName) { super(flags); mPlugin = plugin; + mModelProject = modelProject; + mVariantName = variantName; + mRegistry = registry; } @NonNull @@ -53,7 +74,9 @@ public class LintGradleClient extends LintCliClient { @Override protected Project createProject(@NonNull File dir, @NonNull File referenceDir) { - return new LintGradleProject(this, dir, referenceDir); + // Should not be called by lint since we supply an explicit set of projects + // to the LintRequest + throw new IllegalStateException(); } @Override @@ -64,4 +87,94 @@ public class LintGradleClient extends LintCliClient { } return super.getSdkHome(); } + + @Override + @NonNull + protected LintRequest createLintRequest(@NonNull List<File> files) { + return new LintGradleRequest(this, mModelProject, mPlugin, mVariantName, files); + } + + /** Run lint with the given registry and return the resulting warnings */ + @NonNull + public List<Warning> run(@NonNull IssueRegistry registry) throws IOException { + run(registry, Collections.<File>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<Warning> merge( + @NonNull Map<Variant,List<Warning>> warningMap, + @NonNull AndroidProject project) { + // Easy merge? + if (warningMap.size() == 1) { + return warningMap.values().iterator().next(); + } + int maxCount = 0; + for (List<Warning> warnings : warningMap.values()) { + int size = warnings.size(); + maxCount = Math.max(size, maxCount); + } + if (maxCount == 0) { + return Collections.emptyList(); + } + + int totalVariantCount = project.getVariants().size(); + + List<Warning> merged = Lists.newArrayListWithExpectedSize(2 * maxCount); + + // Map fro issue to message to line number to file name to canonical warning + Map<Issue,Map<String, Map<Integer, Map<String, Warning>>>> map = + Maps.newHashMapWithExpectedSize(2 * maxCount); + + for (Map.Entry<Variant,List<Warning>> entry : warningMap.entrySet()) { + Variant variant = entry.getKey(); + List<Warning> warnings = entry.getValue(); + for (Warning warning : warnings) { + Map<String,Map<Integer,Map<String,Warning>>> messageMap = map.get(warning.issue); + if (messageMap == null) { + messageMap = Maps.newHashMap(); + map.put(warning.issue, messageMap); + } + Map<Integer, Map<String, Warning>> lineMap = messageMap.get(warning.message); + if (lineMap == null) { + lineMap = Maps.newHashMap(); + messageMap.put(warning.message, lineMap); + } + Map<String, Warning> fileMap = lineMap.get(warning.line); + if (fileMap == null) { + fileMap = Maps.newHashMap(); + lineMap.put(warning.line, fileMap); + } + String fileName = warning.file != null ? warning.file.getName() : "<unknown>"; + 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 don't 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; + } } |