diff options
Diffstat (limited to 'gradle/src/main/groovy/com/android/build/gradle/internal/LintGradleProject.java')
-rw-r--r-- | gradle/src/main/groovy/com/android/build/gradle/internal/LintGradleProject.java | 411 |
1 files changed, 381 insertions, 30 deletions
diff --git a/gradle/src/main/groovy/com/android/build/gradle/internal/LintGradleProject.java b/gradle/src/main/groovy/com/android/build/gradle/internal/LintGradleProject.java index 6724268..fb50f00 100644 --- a/gradle/src/main/groovy/com/android/build/gradle/internal/LintGradleProject.java +++ b/gradle/src/main/groovy/com/android/build/gradle/internal/LintGradleProject.java @@ -1,32 +1,86 @@ package com.android.build.gradle.internal; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; + import com.android.annotations.NonNull; -import com.android.build.gradle.BasePlugin; -import com.android.build.gradle.LibraryPlugin; -import com.android.build.gradle.internal.model.ModelBuilder; +import com.android.annotations.Nullable; import com.android.builder.model.AndroidLibrary; import com.android.builder.model.AndroidProject; +import com.android.builder.model.BuildTypeContainer; +import com.android.builder.model.Dependencies; +import com.android.builder.model.ProductFlavor; +import com.android.builder.model.ProductFlavorContainer; +import com.android.builder.model.SourceProvider; import com.android.builder.model.Variant; -import com.android.tools.lint.client.api.LintClient; +import com.android.sdklib.AndroidTargetHash; +import com.android.sdklib.AndroidVersion; import com.android.tools.lint.detector.api.Project; +import com.android.utils.Pair; import java.io.File; +import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; +import java.util.List; +import java.util.Set; -public class LintGradleProject extends Project { - private AndroidProject mProject; +import static java.io.File.separatorChar; - LintGradleProject( - @NonNull LintClient client, +/** + * An implementation of Lint's {@link Project} class wrapping a Gradle model (project or + * library) + */ +public class LintGradleProject extends Project { + private LintGradleProject( + @NonNull LintGradleClient client, @NonNull File dir, @NonNull File referenceDir) { super(client, dir, referenceDir); - mGradleProject = true; mMergeManifests = true; - mDirectLibraries = Collections.emptyList(); + mDirectLibraries = Lists.newArrayList(); + } + + /** + * Creates a {@link com.android.build.gradle.internal.LintGradleProject} from + * the given {@link com.android.builder.model.AndroidProject} definition for + * a given {@link com.android.builder.model.Variant}, and returns it along with + * a set of lint custom rule jars applicable for the given model project. + * + * @param client the client + * @param project the model project + * @param variant the variant + * @param gradleProject the gradle project + * @return a pair of new project and list of custom rule jars + */ + @NonNull + public static Pair<LintGradleProject, List<File>> create( + @NonNull LintGradleClient client, + @NonNull AndroidProject project, + @NonNull Variant variant, + @NonNull org.gradle.api.Project gradleProject) { + File dir = gradleProject.getRootDir(); + AppGradleProject lintProject = new AppGradleProject(client, dir, + dir, project, variant); + + List<File> customRules = Lists.newArrayList(); + File appLintJar = new File(gradleProject.getBuildDir(), + "lint" + separatorChar + "lint.jar"); + if (appLintJar.exists()) { + customRules.add(appLintJar); + } + + Set<AndroidLibrary> libraries = Sets.newHashSet(); + Dependencies dependencies = variant.getMainArtifact().getDependencies(); + for (AndroidLibrary library : dependencies.getLibraries()) { + lintProject.addDirectLibrary(createLibrary(client, library, libraries, customRules)); + } + + return Pair.<LintGradleProject,List<File>>of(lintProject, customRules); } + @Override protected void initialize() { // Deliberately not calling super; that code is for ADT compatibility @@ -37,33 +91,330 @@ public class LintGradleProject extends Project { return true; } - @Override - public boolean isLibrary() { - LintGradleClient client = (LintGradleClient) mClient; - BasePlugin plugin = client.getPlugin(); - return plugin instanceof LibraryPlugin; + void addDirectLibrary(@NonNull Project project) { + mDirectLibraries.add(project); } - @Override - public AndroidProject getGradleProjectModel() { - if (mProject == null) { - LintGradleClient client = (LintGradleClient) mClient; - BasePlugin plugin = client.getPlugin(); - String modelName = AndroidProject.class.getName(); - ModelBuilder builder = new ModelBuilder(); - mProject = (AndroidProject) builder.buildAll(modelName, plugin.getProject()); + @NonNull + private static LibraryProject createLibrary(@NonNull LintGradleClient client, + @NonNull AndroidLibrary library, + @NonNull Set<AndroidLibrary> seen, List<File> customRules) { + seen.add(library); + File dir = library.getFolder(); + LibraryProject project = new LibraryProject(client, dir, dir, library); + + File ruleJar = library.getLintJar(); + if (ruleJar.exists()) { + customRules.add(ruleJar); + } + + for (AndroidLibrary dependent : library.getLibraryDependencies()) { + if (!seen.contains(dependent)) { + project.addDirectLibrary(createLibrary(client, dependent, seen, customRules)); + } } - return mProject; + return project; } - @Override - public AndroidLibrary getGradleLibraryModel() { - return null; + private static class AppGradleProject extends LintGradleProject { + private AndroidProject mProject; + private Variant mVariant; + private List<SourceProvider> mProviders; + + private AppGradleProject( + @NonNull LintGradleClient client, + @NonNull File dir, + @NonNull File referenceDir, + @NonNull AndroidProject project, + @NonNull Variant variant) { + super(client, dir, referenceDir); + + mProject = project; + mVariant = variant; + } + + @Override + public boolean isLibrary() { + return mProject.isLibrary(); + } + + @Override + public AndroidProject getGradleProjectModel() { + return mProject; + } + + @Override + public Variant getCurrentVariant() { + return mVariant; + } + + private List<SourceProvider> getSourceProviders() { + if (mProviders == null) { + List<SourceProvider> providers = Lists.newArrayList(); + + SourceProvider defaultProvider = mProject.getDefaultConfig().getSourceProvider(); + if (defaultProvider != null) { + providers.add(defaultProvider); + } + + SourceProvider sourceProvider = mVariant.getMainArtifact().getVariantSourceProvider(); + if (sourceProvider != null) { + providers.add(sourceProvider); + } + + sourceProvider = mVariant.getMainArtifact().getMultiFlavorSourceProvider(); + if (sourceProvider != null) { + providers.add(sourceProvider); + } + + for (String flavorName : mVariant.getProductFlavors()) { + for (ProductFlavorContainer flavor : mProject.getProductFlavors()) { + if (flavorName.equals(flavor.getProductFlavor().getName())) { + SourceProvider provider = flavor.getSourceProvider(); + if (provider != null) { + providers.add(provider); + } + break; + } + } + } + + String buildTypeName = mVariant.getBuildType(); + for (BuildTypeContainer buildType : mProject.getBuildTypes()) { + if (buildTypeName.equals(buildType.getBuildType().getName())) { + SourceProvider provider = buildType.getSourceProvider(); + if (provider != null) { + providers.add(provider); + } + break; + } + } + mProviders = providers; + } + + return mProviders; + } + + @NonNull + @Override + public List<File> getManifestFiles() { + if (mManifestFiles == null) { + mManifestFiles = Lists.newArrayList(); + for (SourceProvider provider : getSourceProviders()) { + File manifestFile = provider.getManifestFile(); + if (manifestFile.exists()) { // model returns path whether or not it exists + mManifestFiles.add(manifestFile); + } + } + } + + return mManifestFiles; + } + + @Override + public List<File> getProguardFiles() { + if (mProguardFiles == null) { + ProductFlavor flavor = mProject.getDefaultConfig().getProductFlavor(); + mProguardFiles = Lists.newArrayList(); + mProguardFiles.addAll(flavor.getProguardFiles()); + // TODO: This is currently broken: + //mProguardFiles.addAll(flavor.getConsumerProguardFiles()); + // It will throw + //org.gradle.tooling.model.UnsupportedMethodException: Unsupported method: BaseConfig.getConsumerProguardFiles(). + // The version of Gradle you connect to does not support that method. + // To resolve the problem you can change/upgrade the target version of Gradle you connect to. + // Alternatively, you can ignore this exception and read other information from the model. + //at org.gradle.tooling.model.internal.Exceptions.unsupportedMethod(Exceptions.java:33) + //at org.gradle.tooling.internal.adapter.ProtocolToModelAdapter$InvocationHandlerImpl.invoke(ProtocolToModelAdapter.java:239) + //at com.sun.proxy.$Proxy129.getConsumerProguardFiles(Unknown Source) + } + + return mProguardFiles; + } + + @NonNull + @Override + public List<File> getResourceFolders() { + if (mResourceFolders == null) { + mResourceFolders = Lists.newArrayList(); + for (SourceProvider provider : getSourceProviders()) { + Collection<File> resDirs = provider.getResDirectories(); + for (File res : resDirs) { + if (res.exists()) { // model returns path whether or not it exists + mResourceFolders.add(res); + } + } + } + } + + return mResourceFolders; + } + + @NonNull + @Override + public List<File> getJavaSourceFolders() { + if (mJavaSourceFolders == null) { + mJavaSourceFolders = Lists.newArrayList(); + for (SourceProvider provider : getSourceProviders()) { + Collection<File> resDirs = provider.getJavaDirectories(); + for (File res : resDirs) { + if (res.exists()) { // model returns path whether or not it exists + mJavaSourceFolders.add(res); + } + } + } + } + + return mJavaSourceFolders; + } + + @NonNull + @Override + public List<File> getJavaClassFolders() { + if (mJavaClassFolders == null) { + mJavaClassFolders = new ArrayList<File>(1); + File outputClassFolder = mVariant.getMainArtifact().getClassesFolder(); + if (outputClassFolder != null && outputClassFolder.exists()) { + mJavaClassFolders.add(outputClassFolder); + } + } + + return mJavaClassFolders; + } + + @Override + public List<File> getJavaLibraries() { + if (mJavaLibraries == null) { + Collection<File> jars = mVariant.getMainArtifact().getDependencies().getJars(); + mJavaLibraries = Lists.newArrayListWithExpectedSize(jars.size()); + for (File jar : jars) { + if (jar.exists()) { + mJavaLibraries.add(jar); + } + } + } + return mJavaLibraries; + } + + @Nullable + @Override + public String getPackage() { + // TODO: Merge with manifest + return mProject.getDefaultConfig().getProductFlavor().getPackageName(); + } + + @Override + public int getMinSdk() { + // TODO: Merge with manifest + return mProject.getDefaultConfig().getProductFlavor().getMinSdkVersion(); + } + + @Override + public int getTargetSdk() { + // TODO: Merge with manifest + return mProject.getDefaultConfig().getProductFlavor().getTargetSdkVersion(); + } + + @Override + public int getBuildSdk() { + String compileTarget = mProject.getCompileTarget(); + if (compileTarget != null) { + AndroidVersion version = AndroidTargetHash.getPlatformVersion(compileTarget); + if (version != null) { + return version.getApiLevel(); + } + } + + return super.getBuildSdk(); + } } - @Override - public Variant getCurrentVariant() { - return null; + private static class LibraryProject extends LintGradleProject { + private AndroidLibrary mLibrary; + + private LibraryProject( + @NonNull LintGradleClient client, + @NonNull File dir, + @NonNull File referenceDir, + @NonNull AndroidLibrary library) { + super(client, dir, referenceDir); + mLibrary = library; + + // TODO: Make sure we don't use this project for any source library projects! + mReportIssues = false; + } + + @Override + public boolean isLibrary() { + return true; + } + + @Override + public AndroidLibrary getGradleLibraryModel() { + return mLibrary; + } + + @Override + public Variant getCurrentVariant() { + return null; + } + + @NonNull + @Override + public List<File> getManifestFiles() { + if (mManifestFiles == null) { + File manifest = mLibrary.getManifest(); + if (manifest.exists()) { + mManifestFiles = Collections.singletonList(manifest); + } else { + mManifestFiles = Collections.emptyList(); + } + } + + return mManifestFiles; + } + + @NonNull + @Override + public List<File> getResourceFolders() { + if (mResourceFolders == null) { + File folder = mLibrary.getResFolder(); + if (folder.exists()) { + mResourceFolders = Collections.singletonList(folder); + } else { + mResourceFolders = Collections.emptyList(); + } + } + + return mResourceFolders; + } + + @NonNull + @Override + public List<File> getJavaSourceFolders() { + return Collections.emptyList(); + } + + @NonNull + @Override + public List<File> getJavaClassFolders() { + return Collections.emptyList(); + } + + @NonNull + @Override + public List<File> getJavaLibraries() { + if (mJavaLibraries == null) { + File jarFile = mLibrary.getJarFile(); + if (jarFile.exists()) { + mJavaLibraries = Collections.singletonList(jarFile); + } else { + mJavaLibraries = Collections.emptyList(); + } + } + + return mJavaLibraries; + } } } |