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.ResourceItem;
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.IAndroidTarget;
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.Detector;
import com.android.tools.klint.detector.api.Issue;
@@ -741,9 +744,12 @@ public abstract class LintClient {
@NonNull
public IAndroidTarget[] getTargets() {
if (mTargets == null) {
SdkWrapper localSdk = getSdk();
if (localSdk != null) {
mTargets = localSdk.getTargets();
AndroidSdkHandler sdkHandler = getSdk();
if (sdkHandler != null) {
ProgressIndicator logger = getRepositoryLogger();
Collection<IAndroidTarget> targets = sdkHandler.getAndroidTargetManager(logger)
.getTargets(logger);
mTargets = targets.toArray(new IAndroidTarget[targets.size()]);
} else {
mTargets = new IAndroidTarget[0];
}
@@ -752,7 +758,7 @@ public abstract class LintClient {
return mTargets;
}
protected SdkWrapper mSdk;
protected AndroidSdkHandler mSdk;
/**
* Returns the SDK installation (used to look up platforms etc)
@@ -760,13 +766,13 @@ public abstract class LintClient {
* @return the SDK if known
*/
@Nullable
public SdkWrapper getSdk() {
if (mSdk == null) {
File sdkHome = getSdkHome();
if (sdkHome != null) {
mSdk = SdkWrapper.createLocalSdk(sdkHome);
}
}
public AndroidSdkHandler getSdk() {
if (mSdk == null) {
File sdkHome = getSdkHome();
if (sdkHome != null) {
mSdk = AndroidSdkHandler.getInstance(sdkHome);
}
}
return mSdk;
}
@@ -1217,4 +1223,33 @@ public abstract class LintClient {
public static boolean isGradle() {
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.sdklib.BuildToolInfo;
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.detector.api.ClassContext;
import com.android.tools.klint.detector.api.Context;
@@ -2129,7 +2130,7 @@ public class LintDriver {
@Nullable
@Override
public SdkWrapper getSdk() {
public AndroidSdkHandler 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.ProductFlavorContainer;
import com.android.builder.model.Variant;
import com.android.ide.common.repository.GradleVersion;
import com.android.ide.common.repository.ResourceVisibilityLookup;
import com.android.resources.Density;
import com.android.resources.ResourceFolderType;
@@ -136,6 +137,7 @@ public class Project {
protected Boolean mGradleProject;
protected Boolean mSupportLib;
protected Boolean mAppCompat;
protected GradleVersion mGradleVersion;
private Map<String, String> mSuperClassMap;
private ResourceVisibilityLookup mResourceVisibility;
private BuildToolInfo mBuildTools;
@@ -190,6 +192,24 @@ public class Project {
public AndroidProject getGradleProjectModel() {
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
@@ -63,10 +63,8 @@ import com.android.resources.ResourceType;
import com.android.sdklib.AndroidVersion;
import com.android.sdklib.BuildToolInfo;
import com.android.sdklib.SdkVersionInfo;
import com.android.tools.klint.client.api.IssueRegistry;
import com.android.tools.klint.client.api.JavaEvaluator;
import com.android.tools.klint.client.api.LintDriver;
import com.android.tools.klint.client.api.UastLintUtils;
import com.android.sdklib.repositoryv2.AndroidSdkHandler;
import com.android.tools.klint.client.api.*;
import com.android.tools.klint.detector.api.Category;
import com.android.tools.klint.detector.api.ClassContext;
import com.android.tools.klint.detector.api.Context;
@@ -339,68 +337,67 @@ public class ApiDetector extends ResourceXmlDetector
@Override
public void beforeCheckProject(@NonNull Context context) {
if (mApiDatabase == null) {
//TODO
//mApiDatabase = ApiLookup.get(context.getClient());
//// 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.
//// For now it's initialized lazily in getMinSdk(Context), but the
//// lint infrastructure should be fixed to parse manifest file up front.
//
//if (mApiDatabase == null && !mWarnedMissingDb) {
// mWarnedMissingDb = true;
// context.report(IssueRegistry.LINT_ERROR, Location.create(context.file),
// "Can't find API database; API check not performed");
//} else {
// // See if you don't have at least version 23.0.1 of platform tools installed
// AndroidSdkHandler sdk = context.getClient().getSdk();
// if (sdk == null) {
// return;
// }
// LocalPackage pkgInfo = sdk.getLocalPackage(SdkConstants.FD_PLATFORM_TOOLS,
// context.getClient().getRepositoryLogger());
// if (pkgInfo == null) {
// return;
// }
// Revision revision = pkgInfo.getVersion();
//
// // The platform tools must be at at least the same revision
// // as the compileSdkVersion!
// // And as a special case, for 23, they must be at 23.0.1
// // because 23.0.0 accidentally shipped without Android M APIs.
// int compileSdkVersion = context.getProject().getBuildSdk();
// if (compileSdkVersion == 23) {
// if (revision.getMajor() > 23 || revision.getMajor() == 23
// && (revision.getMinor() > 0 || revision.getMicro() > 0)) {
// return;
// }
// } else if (compileSdkVersion <= revision.getMajor()) {
// return;
// }
//
// // Pick a location: when incrementally linting in the IDE, tie
// // it to the current file
// List<File> currentFiles = context.getProject().getSubset();
// Location location;
// if (currentFiles != null && currentFiles.size() == 1) {
// File file = currentFiles.get(0);
// String contents = context.getClient().readFile(file);
// int firstLineEnd = contents.indexOf('\n');
// if (firstLineEnd == -1) {
// firstLineEnd = contents.length();
// }
// location = Location.create(file,
// new DefaultPosition(0, 0, 0), new
// DefaultPosition(0, firstLineEnd, firstLineEnd));
// } else {
// location = Location.create(context.file);
// }
// context.report(UNSUPPORTED,
// location,
// String.format("The SDK platform-tools version (%1$s) is too old "
// + " to check APIs compiled with API %2$d; please update",
// revision.toShortString(),
// compileSdkVersion));
//}
mApiDatabase = ApiLookup.get(context.getClient());
// 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.
// For now it's initialized lazily in getMinSdk(Context), but the
// lint infrastructure should be fixed to parse manifest file up front.
if (mApiDatabase == null && !mWarnedMissingDb) {
mWarnedMissingDb = true;
context.report(IssueRegistry.LINT_ERROR, Location.create(context.file),
"Can't find API database; API check not performed");
} else {
// See if you don't have at least version 23.0.1 of platform tools installed
AndroidSdkHandler sdk = context.getClient().getSdk();
if (sdk == null) {
return;
}
LocalPackage pkgInfo = sdk.getLocalPackage(SdkConstants.FD_PLATFORM_TOOLS,
context.getClient().getRepositoryLogger());
if (pkgInfo == null) {
return;
}
Revision revision = pkgInfo.getVersion();
// The platform tools must be at at least the same revision
// as the compileSdkVersion!
// And as a special case, for 23, they must be at 23.0.1
// because 23.0.0 accidentally shipped without Android M APIs.
int compileSdkVersion = context.getProject().getBuildSdk();
if (compileSdkVersion == 23) {
if (revision.getMajor() > 23 || revision.getMajor() == 23
&& (revision.getMinor() > 0 || revision.getMicro() > 0)) {
return;
}
} else if (compileSdkVersion <= revision.getMajor()) {
return;
}
// Pick a location: when incrementally linting in the IDE, tie
// it to the current file
List<File> currentFiles = context.getProject().getSubset();
Location location;
if (currentFiles != null && currentFiles.size() == 1) {
File file = currentFiles.get(0);
String contents = context.getClient().readFile(file);
int firstLineEnd = contents.indexOf('\n');
if (firstLineEnd == -1) {
firstLineEnd = contents.length();
}
location = Location.create(file,
new DefaultPosition(0, 0, 0), new
DefaultPosition(0, firstLineEnd, firstLineEnd));
} else {
location = Location.create(context.file);
}
context.report(UNSUPPORTED,
location,
String.format("The SDK platform-tools version (%1$s) is too old "
+ " to check APIs compiled with API %2$d; please update",
revision.toShortString(),
compileSdkVersion));
}
}
}
@@ -24,8 +24,10 @@ import com.android.SdkConstants;
import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
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.SdkWrapper;
//import com.android.tools.klint.client.api.SdkWrapper;
import com.android.tools.klint.detector.api.LintUtils;
import com.android.utils.Pair;
import com.google.common.base.Charsets;
@@ -140,9 +142,13 @@ public class ApiLookup {
@VisibleForTesting
@Nullable
static String getPlatformVersion(@NonNull LintClient client) {
SdkWrapper sdk = client.getSdk();
AndroidSdkHandler sdk = client.getSdk();
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;
}
@@ -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.ResourceFile;
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.rendering.AppResourceRepository;
import com.android.tools.idea.rendering.LocalResourceRepository;
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.client.api.*;
import com.android.tools.klint.detector.api.*;
@@ -332,10 +334,10 @@ public class IntellijLintClient extends LintClient implements Disposable {
@Nullable
@Override
public SdkWrapper getSdk() {
public AndroidSdkHandler getSdk() {
if (mSdk == null) {
Module module = getModule();
SdkWrapper sdk = getLocalSdk(module);
AndroidSdkHandler sdk = getLocalSdk(module);
if (sdk != null) {
mSdk = sdk;
} else {
@@ -357,11 +359,14 @@ public class IntellijLintClient extends LintClient implements Disposable {
}
@Nullable
private static SdkWrapper getLocalSdk(@Nullable Module module) {
private static AndroidSdkHandler getLocalSdk(@Nullable Module module) {
if (module != null) {
AndroidFacet facet = AndroidFacet.getInstance(module);
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;
}
public static AndroidModelFacade getModelFacade(AndroidFacet facet) {
return new AndroidModelFacade(facet);
}
private static boolean appendJvmSignature(@NonNull StringBuilder buffer, @Nullable PsiType type) {
if (type == null) {
return false;