Lint: Remove SdkWrapper and AnroidModelFacade (was needed in Android Studio 1.5)

This commit is contained in:
Yan Zhulanow
2016-10-14 16:49:51 +03:00
committed by Yan Zhulanow
parent 7404b91cb3
commit fee54d9b86
9 changed files with 149 additions and 292 deletions
@@ -37,9 +37,12 @@ import com.android.ide.common.repository.ResourceVisibilityLookup;
import com.android.ide.common.res2.AbstractResourceRepository; import com.android.ide.common.res2.AbstractResourceRepository;
import com.android.ide.common.res2.ResourceItem; import com.android.ide.common.res2.ResourceItem;
import com.android.prefs.AndroidLocation; import com.android.prefs.AndroidLocation;
import com.android.repository.api.ProgressIndicator;
import com.android.repository.api.ProgressIndicatorAdapter;
import com.android.sdklib.BuildToolInfo; import com.android.sdklib.BuildToolInfo;
import com.android.sdklib.IAndroidTarget; import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.SdkVersionInfo; import com.android.sdklib.SdkVersionInfo;
import com.android.sdklib.repositoryv2.AndroidSdkHandler;
import com.android.tools.klint.detector.api.Context; import com.android.tools.klint.detector.api.Context;
import com.android.tools.klint.detector.api.Detector; import com.android.tools.klint.detector.api.Detector;
import com.android.tools.klint.detector.api.Issue; import com.android.tools.klint.detector.api.Issue;
@@ -741,9 +744,12 @@ public abstract class LintClient {
@NonNull @NonNull
public IAndroidTarget[] getTargets() { public IAndroidTarget[] getTargets() {
if (mTargets == null) { if (mTargets == null) {
SdkWrapper localSdk = getSdk(); AndroidSdkHandler sdkHandler = getSdk();
if (localSdk != null) { if (sdkHandler != null) {
mTargets = localSdk.getTargets(); ProgressIndicator logger = getRepositoryLogger();
Collection<IAndroidTarget> targets = sdkHandler.getAndroidTargetManager(logger)
.getTargets(logger);
mTargets = targets.toArray(new IAndroidTarget[targets.size()]);
} else { } else {
mTargets = new IAndroidTarget[0]; mTargets = new IAndroidTarget[0];
} }
@@ -752,7 +758,7 @@ public abstract class LintClient {
return mTargets; return mTargets;
} }
protected SdkWrapper mSdk; protected AndroidSdkHandler mSdk;
/** /**
* Returns the SDK installation (used to look up platforms etc) * Returns the SDK installation (used to look up platforms etc)
@@ -760,13 +766,13 @@ public abstract class LintClient {
* @return the SDK if known * @return the SDK if known
*/ */
@Nullable @Nullable
public SdkWrapper getSdk() { public AndroidSdkHandler getSdk() {
if (mSdk == null) { if (mSdk == null) {
File sdkHome = getSdkHome(); File sdkHome = getSdkHome();
if (sdkHome != null) { if (sdkHome != null) {
mSdk = SdkWrapper.createLocalSdk(sdkHome); mSdk = AndroidSdkHandler.getInstance(sdkHome);
} }
} }
return mSdk; return mSdk;
} }
@@ -1217,4 +1223,33 @@ public abstract class LintClient {
public static boolean isGradle() { public static boolean isGradle() {
return CLIENT_GRADLE.equals(sClientName); return CLIENT_GRADLE.equals(sClientName);
} }
@NonNull
public ProgressIndicator getRepositoryLogger() {
return new LintClient.RepoLogger();
}
private static final class RepoLogger extends ProgressIndicatorAdapter {
// Intentionally not logging these: the SDK manager is
// logging events such as package.xml parsing
// Parsing /path/to/sdk//build-tools/19.1.0/package.xml
// Parsing /path/to/sdk//build-tools/20.0.0/package.xml
// Parsing /path/to/sdk//build-tools/21.0.0/package.xml
// which we don't want to spam on the console.
// It's also warning about packages that it's encountering
// multiple times etc; that's not something we should include
// in lint command line output.
@Override
public void logError(@NonNull String s, @Nullable Throwable e) {
}
@Override
public void logInfo(@NonNull String s) {
}
@Override
public void logWarning(@NonNull String s, @Nullable Throwable e) {
}
}
} }
@@ -42,6 +42,7 @@ import com.android.ide.common.res2.ResourceItem;
import com.android.resources.ResourceFolderType; import com.android.resources.ResourceFolderType;
import com.android.sdklib.BuildToolInfo; import com.android.sdklib.BuildToolInfo;
import com.android.sdklib.IAndroidTarget; import com.android.sdklib.IAndroidTarget;
import com.android.sdklib.repositoryv2.AndroidSdkHandler;
import com.android.tools.klint.client.api.LintListener.EventType; import com.android.tools.klint.client.api.LintListener.EventType;
import com.android.tools.klint.detector.api.ClassContext; import com.android.tools.klint.detector.api.ClassContext;
import com.android.tools.klint.detector.api.Context; import com.android.tools.klint.detector.api.Context;
@@ -2129,7 +2130,7 @@ public class LintDriver {
@Nullable @Nullable
@Override @Override
public SdkWrapper getSdk() { public AndroidSdkHandler getSdk() {
return mDelegate.getSdk(); return mDelegate.getSdk();
} }
@@ -1,104 +0,0 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* 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.tools.klint.client.api
import com.android.sdklib.IAndroidTarget
import java.io.File
class SdkWrapper(val sdk: Any) {
companion object {
val PROGRESS_INDICATOR_CLASS_NAME = "com.android.repository.api.ConsoleProgressIndicator"
@JvmStatic
fun createLocalSdk(file: File): SdkWrapper? {
try {
val clazz = Class.forName("com.android.sdklib.repository.local.LocalSdk")
return SdkWrapper(clazz.getConstructor(File::class.java).newInstance(file))
}
catch (t: Throwable) {
try {
val clazz = Class.forName("com.android.sdklib.repositoryv2.AndroidSdkHandler")
return SdkWrapper(clazz.getMethod("getInstance", File::class.java).invoke(null, file))
}
catch (t2: Throwable) {
return null
}
}
}
}
fun getTargets(): Array<IAndroidTarget>? {
try {
@Suppress("UNCHECKED_CAST")
return sdk.javaClass.getMethod("getTargets").invoke(sdk) as? Array<IAndroidTarget>
} catch (t: Throwable) {
@Suppress("UNCHECKED_CAST")
try {
val targets = sdk.javaClass
.getMethod("getAndroidTargetManager", Class.forName(PROGRESS_INDICATOR_CLASS_NAME))
.invoke(sdk, createProgressIndicator()) as? Collection<IAndroidTarget> ?: return null
return targets.toTypedArray()
}
catch (t2: Throwable) {
return null
}
}
}
fun getPlatformVersion(): String? {
try {
val pkgPlatformTools = Class.forName("com.android.sdklib.repository.descriptors.PkgType")
.getField("PKG_PLATFORM_TOOLS").get(null)
val pkgInfo = sdk.javaClass.declaredMethods
.first { it.name == "getPkgInfo" && it.parameterTypes.size == 1 }
.invoke(sdk, pkgPlatformTools)
if (pkgInfo != null) {
val desc = pkgInfo.javaClass.getMethod("getDesc").invoke(pkgInfo)
val version = desc.javaClass.getMethod("getFullRevision").invoke(desc)
if (version != null) {
return version.javaClass.getMethod("toShortString").invoke(version) as? String
}
}
else {
return null
}
} catch (t: Throwable) {
try {
val pkgPlatformTools = Class.forName("com.android.SdkConstants")
.getField("FD_PLATFORM_TOOLS").get(null)
val pkgInfo = sdk.javaClass.declaredMethods
.first { it.name == "getLocalPackage" && it.parameterTypes.size == 2 }
.invoke(sdk, pkgPlatformTools, createProgressIndicator())
if (pkgInfo != null) {
val version = pkgInfo.javaClass.getMethod("getVersion").invoke(pkgInfo)
return version.javaClass.getMethod("toShortString").invoke(version) as? String
}
else {
return null
}
}
catch (ignore: Throwable) {}
}
return null
}
private fun createProgressIndicator(): Any {
return Class.forName(PROGRESS_INDICATOR_CLASS_NAME).newInstance()
}
}
@@ -48,6 +48,7 @@ import com.android.builder.model.AndroidProject;
import com.android.builder.model.ProductFlavor; import com.android.builder.model.ProductFlavor;
import com.android.builder.model.ProductFlavorContainer; import com.android.builder.model.ProductFlavorContainer;
import com.android.builder.model.Variant; import com.android.builder.model.Variant;
import com.android.ide.common.repository.GradleVersion;
import com.android.ide.common.repository.ResourceVisibilityLookup; import com.android.ide.common.repository.ResourceVisibilityLookup;
import com.android.resources.Density; import com.android.resources.Density;
import com.android.resources.ResourceFolderType; import com.android.resources.ResourceFolderType;
@@ -136,6 +137,7 @@ public class Project {
protected Boolean mGradleProject; protected Boolean mGradleProject;
protected Boolean mSupportLib; protected Boolean mSupportLib;
protected Boolean mAppCompat; protected Boolean mAppCompat;
protected GradleVersion mGradleVersion;
private Map<String, String> mSuperClassMap; private Map<String, String> mSuperClassMap;
private ResourceVisibilityLookup mResourceVisibility; private ResourceVisibilityLookup mResourceVisibility;
private BuildToolInfo mBuildTools; private BuildToolInfo mBuildTools;
@@ -190,6 +192,24 @@ public class Project {
public AndroidProject getGradleProjectModel() { public AndroidProject getGradleProjectModel() {
return null; return null;
} }
/**
* If this is a Gradle project with a valid Gradle model, return the version
* of the model/plugin.
*
* @return the Gradle plugin version, or null if invalid or not a Gradle project
*/
@Nullable
public GradleVersion getGradleModelVersion() {
if (mGradleVersion == null && isGradleProject()) {
AndroidProject gradleProjectModel = getGradleProjectModel();
if (gradleProjectModel != null) {
mGradleVersion = GradleVersion.tryParse(gradleProjectModel.getModelVersion());
}
}
return mGradleVersion;
}
/** /**
* Returns the project model for this project if it corresponds to * Returns the project model for this project if it corresponds to
@@ -63,10 +63,8 @@ import com.android.resources.ResourceType;
import com.android.sdklib.AndroidVersion; import com.android.sdklib.AndroidVersion;
import com.android.sdklib.BuildToolInfo; import com.android.sdklib.BuildToolInfo;
import com.android.sdklib.SdkVersionInfo; import com.android.sdklib.SdkVersionInfo;
import com.android.tools.klint.client.api.IssueRegistry; import com.android.sdklib.repositoryv2.AndroidSdkHandler;
import com.android.tools.klint.client.api.JavaEvaluator; import com.android.tools.klint.client.api.*;
import com.android.tools.klint.client.api.LintDriver;
import com.android.tools.klint.client.api.UastLintUtils;
import com.android.tools.klint.detector.api.Category; import com.android.tools.klint.detector.api.Category;
import com.android.tools.klint.detector.api.ClassContext; import com.android.tools.klint.detector.api.ClassContext;
import com.android.tools.klint.detector.api.Context; import com.android.tools.klint.detector.api.Context;
@@ -339,68 +337,67 @@ public class ApiDetector extends ResourceXmlDetector
@Override @Override
public void beforeCheckProject(@NonNull Context context) { public void beforeCheckProject(@NonNull Context context) {
if (mApiDatabase == null) { if (mApiDatabase == null) {
//TODO mApiDatabase = ApiLookup.get(context.getClient());
//mApiDatabase = ApiLookup.get(context.getClient()); // We can't look up the minimum API required by the project here:
//// We can't look up the minimum API required by the project here: // The manifest file hasn't been processed yet in the -before- project hook.
//// The manifest file hasn't been processed yet in the -before- project hook. // For now it's initialized lazily in getMinSdk(Context), but the
//// For now it's initialized lazily in getMinSdk(Context), but the // lint infrastructure should be fixed to parse manifest file up front.
//// lint infrastructure should be fixed to parse manifest file up front.
// if (mApiDatabase == null && !mWarnedMissingDb) {
//if (mApiDatabase == null && !mWarnedMissingDb) { mWarnedMissingDb = true;
// mWarnedMissingDb = true; context.report(IssueRegistry.LINT_ERROR, Location.create(context.file),
// context.report(IssueRegistry.LINT_ERROR, Location.create(context.file), "Can't find API database; API check not performed");
// "Can't find API database; API check not performed"); } else {
//} else { // See if you don't have at least version 23.0.1 of platform tools installed
// // See if you don't have at least version 23.0.1 of platform tools installed AndroidSdkHandler sdk = context.getClient().getSdk();
// AndroidSdkHandler sdk = context.getClient().getSdk(); if (sdk == null) {
// if (sdk == null) { return;
// return; }
// } LocalPackage pkgInfo = sdk.getLocalPackage(SdkConstants.FD_PLATFORM_TOOLS,
// LocalPackage pkgInfo = sdk.getLocalPackage(SdkConstants.FD_PLATFORM_TOOLS, context.getClient().getRepositoryLogger());
// context.getClient().getRepositoryLogger()); if (pkgInfo == null) {
// if (pkgInfo == null) { return;
// return; }
// } Revision revision = pkgInfo.getVersion();
// Revision revision = pkgInfo.getVersion();
// // The platform tools must be at at least the same revision
// // The platform tools must be at at least the same revision // as the compileSdkVersion!
// // as the compileSdkVersion! // And as a special case, for 23, they must be at 23.0.1
// // And as a special case, for 23, they must be at 23.0.1 // because 23.0.0 accidentally shipped without Android M APIs.
// // because 23.0.0 accidentally shipped without Android M APIs. int compileSdkVersion = context.getProject().getBuildSdk();
// int compileSdkVersion = context.getProject().getBuildSdk(); if (compileSdkVersion == 23) {
// if (compileSdkVersion == 23) { if (revision.getMajor() > 23 || revision.getMajor() == 23
// if (revision.getMajor() > 23 || revision.getMajor() == 23 && (revision.getMinor() > 0 || revision.getMicro() > 0)) {
// && (revision.getMinor() > 0 || revision.getMicro() > 0)) { return;
// return; }
// } } else if (compileSdkVersion <= revision.getMajor()) {
// } else if (compileSdkVersion <= revision.getMajor()) { return;
// return; }
// }
// // Pick a location: when incrementally linting in the IDE, tie
// // Pick a location: when incrementally linting in the IDE, tie // it to the current file
// // it to the current file List<File> currentFiles = context.getProject().getSubset();
// List<File> currentFiles = context.getProject().getSubset(); Location location;
// Location location; if (currentFiles != null && currentFiles.size() == 1) {
// if (currentFiles != null && currentFiles.size() == 1) { File file = currentFiles.get(0);
// File file = currentFiles.get(0); String contents = context.getClient().readFile(file);
// String contents = context.getClient().readFile(file); int firstLineEnd = contents.indexOf('\n');
// int firstLineEnd = contents.indexOf('\n'); if (firstLineEnd == -1) {
// if (firstLineEnd == -1) { firstLineEnd = contents.length();
// firstLineEnd = contents.length(); }
// } location = Location.create(file,
// location = Location.create(file, new DefaultPosition(0, 0, 0), new
// new DefaultPosition(0, 0, 0), new DefaultPosition(0, firstLineEnd, firstLineEnd));
// DefaultPosition(0, firstLineEnd, firstLineEnd)); } else {
// } else { location = Location.create(context.file);
// location = Location.create(context.file); }
// } context.report(UNSUPPORTED,
// context.report(UNSUPPORTED, location,
// location, String.format("The SDK platform-tools version (%1$s) is too old "
// String.format("The SDK platform-tools version (%1$s) is too old " + " to check APIs compiled with API %2$d; please update",
// + " to check APIs compiled with API %2$d; please update", revision.toShortString(),
// revision.toShortString(), compileSdkVersion));
// compileSdkVersion)); }
//}
} }
} }
@@ -24,8 +24,10 @@ import com.android.SdkConstants;
import com.android.annotations.NonNull; import com.android.annotations.NonNull;
import com.android.annotations.Nullable; import com.android.annotations.Nullable;
import com.android.annotations.VisibleForTesting; import com.android.annotations.VisibleForTesting;
import com.android.repository.api.LocalPackage;
import com.android.sdklib.repositoryv2.AndroidSdkHandler;
import com.android.tools.klint.client.api.LintClient; import com.android.tools.klint.client.api.LintClient;
import com.android.tools.klint.client.api.SdkWrapper; //import com.android.tools.klint.client.api.SdkWrapper;
import com.android.tools.klint.detector.api.LintUtils; import com.android.tools.klint.detector.api.LintUtils;
import com.android.utils.Pair; import com.android.utils.Pair;
import com.google.common.base.Charsets; import com.google.common.base.Charsets;
@@ -140,9 +142,13 @@ public class ApiLookup {
@VisibleForTesting @VisibleForTesting
@Nullable @Nullable
static String getPlatformVersion(@NonNull LintClient client) { static String getPlatformVersion(@NonNull LintClient client) {
SdkWrapper sdk = client.getSdk(); AndroidSdkHandler sdk = client.getSdk();
if (sdk != null) { if (sdk != null) {
return sdk.getPlatformVersion(); LocalPackage pkgInfo = sdk
.getLocalPackage(SdkConstants.FD_PLATFORM_TOOLS, client.getRepositoryLogger());
if (pkgInfo != null) {
return pkgInfo.getVersion().toShortString();
}
} }
return null; return null;
} }
@@ -1,99 +0,0 @@
package org.jetbrains.android.inspections.klint
import com.android.builder.model.AndroidProject
import com.android.builder.model.SourceProvider
import com.android.builder.model.Variant
import com.android.tools.idea.gradle.util.GradleUtil
import com.android.tools.klint.client.api.SdkWrapper
import org.jetbrains.android.facet.AndroidFacet
import kotlin.reflect.memberFunctions
import kotlin.reflect.staticFunctions
class AndroidModelFacade(val facet: AndroidFacet) {
private val model by lazy { loadModel() }
private val modelClass by lazy {
try {
Class.forName("com.android.tools.idea.gradle.AndroidGradleModel")
}
catch(e: ClassNotFoundException) {
null
}
}
fun getLocalSdk(): SdkWrapper? {
val sdkData = facet.sdkData ?: return null
val localSdk = sdkData.javaClass.kotlin.memberFunctions
.firstOrNull { it.name == "getLocalSdk" || it.name == "getSdkHandler" }
?.call(sdkData) ?: return null
return SdkWrapper(localSdk)
}
fun isModelReady() = model != null
@Suppress("UNCHECKED_CAST")
fun getFlavorSourceProviders(): List<SourceProvider>?
= getFacetOrModel("getFlavorSourceProviders") as? List<SourceProvider>
fun getMultiFlavorSourceProvider(): SourceProvider?
= getFacetOrModel("getMultiFlavorSourceProvider") as? SourceProvider
fun getBuildTypeSourceProvider(): SourceProvider?
= getFacetOrModel("getBuildTypeSourceProvider") as? SourceProvider
fun getVariantSourceProvider(): SourceProvider?
= getFacetOrModel("getVariantSourceProvider") as? SourceProvider
private fun getFacetOrModel(methodName: String): Any? {
if (modelClass == null) {
return facet.javaClass.kotlin.memberFunctions
.firstOrNull { it.name == methodName }
?.call(facet)
}
val model = model ?: return null
return modelClass?.kotlin?.memberFunctions
?.firstOrNull { it.name == methodName }
?.call(model)
}
fun getDependsOn(artifact: String): Boolean {
val model = model ?: return false
return GradleUtil::class.staticFunctions.firstOrNull {
val type = it.parameters.firstOrNull()?.type?.toString() ?: ""
it.parameters.size == 2 && "IdeaAndroidProject" in type || "AndroidGradleModel" in type
}?.call(model, artifact) as? Boolean ?: false
}
fun getAndroidProject(): AndroidProject? {
val model = model ?: return null
return modelClass?.kotlin?.memberFunctions
?.firstOrNull { it.name == "getDelegate" || it.name == "getAndroidProject" }
?.call(model) as? AndroidProject
}
fun getSelectedVariant(): Variant? {
val model = model ?: return null
return modelClass?.kotlin?.memberFunctions
?.firstOrNull { it.name == "getSelectedVariant" }
?.call(model) as? Variant
}
private fun loadModel(): Any? {
try {
val getAndroidProjectInfoFun = AndroidFacet::class.memberFunctions.singleOrNull {
it.name == "getIdeaAndroidProject" || it.name == "getAndroidModel"
}
return getAndroidProjectInfoFun?.call(facet)
}
catch(e: Throwable) {
return false
}
}
fun computePackageName(): String? {
return getSelectedVariant()?.mainArtifact?.applicationId
}
}
@@ -7,10 +7,12 @@ import com.android.ide.common.repository.ResourceVisibilityLookup;
import com.android.ide.common.res2.AbstractResourceRepository; import com.android.ide.common.res2.AbstractResourceRepository;
import com.android.ide.common.res2.ResourceFile; import com.android.ide.common.res2.ResourceFile;
import com.android.ide.common.res2.ResourceItem; import com.android.ide.common.res2.ResourceItem;
import com.android.sdklib.repositoryv2.AndroidSdkHandler;
import com.android.tools.idea.gradle.util.Projects; import com.android.tools.idea.gradle.util.Projects;
import com.android.tools.idea.rendering.AppResourceRepository; import com.android.tools.idea.rendering.AppResourceRepository;
import com.android.tools.idea.rendering.LocalResourceRepository; import com.android.tools.idea.rendering.LocalResourceRepository;
import com.android.tools.idea.sdk.IdeSdks; import com.android.tools.idea.sdk.IdeSdks;
import com.android.tools.idea.welcome.install.AndroidSdk;
import com.android.tools.klint.checks.ApiLookup; import com.android.tools.klint.checks.ApiLookup;
import com.android.tools.klint.client.api.*; import com.android.tools.klint.client.api.*;
import com.android.tools.klint.detector.api.*; import com.android.tools.klint.detector.api.*;
@@ -332,10 +334,10 @@ public class IntellijLintClient extends LintClient implements Disposable {
@Nullable @Nullable
@Override @Override
public SdkWrapper getSdk() { public AndroidSdkHandler getSdk() {
if (mSdk == null) { if (mSdk == null) {
Module module = getModule(); Module module = getModule();
SdkWrapper sdk = getLocalSdk(module); AndroidSdkHandler sdk = getLocalSdk(module);
if (sdk != null) { if (sdk != null) {
mSdk = sdk; mSdk = sdk;
} else { } else {
@@ -357,11 +359,14 @@ public class IntellijLintClient extends LintClient implements Disposable {
} }
@Nullable @Nullable
private static SdkWrapper getLocalSdk(@Nullable Module module) { private static AndroidSdkHandler getLocalSdk(@Nullable Module module) {
if (module != null) { if (module != null) {
AndroidFacet facet = AndroidFacet.getInstance(module); AndroidFacet facet = AndroidFacet.getInstance(module);
if (facet != null) { if (facet != null) {
return IntellijLintUtils.getModelFacade(facet).getLocalSdk(); AndroidSdkData sdkData = facet.getSdkData();
if (sdkData != null) {
return sdkData.getSdkHandler();
}
} }
} }
@@ -337,10 +337,6 @@ public class IntellijLintUtils {
return true; return true;
} }
public static AndroidModelFacade getModelFacade(AndroidFacet facet) {
return new AndroidModelFacade(facet);
}
private static boolean appendJvmSignature(@NonNull StringBuilder buffer, @Nullable PsiType type) { private static boolean appendJvmSignature(@NonNull StringBuilder buffer, @Nullable PsiType type) {
if (type == null) { if (type == null) {
return false; return false;