Lint: support both IJ 15 and Android Studio 2.0 (different Android plugins)

Dirty hack :(
This commit is contained in:
Yan Zhulanow
2016-04-13 23:29:21 +03:00
parent b782d2cd11
commit 8304c85f4f
7 changed files with 126 additions and 27 deletions
+1
View File
@@ -14,5 +14,6 @@
<orderEntry type="library" name="android-plugin" level="project" />
<orderEntry type="library" name="intellij-core" level="project" />
<orderEntry type="module" module-name="android-annotations" />
<orderEntry type="library" name="kotlin-runtime" level="project" />
</component>
</module>
@@ -685,7 +685,7 @@ public abstract class LintClient {
@NonNull
public IAndroidTarget[] getTargets() {
if (mTargets == null) {
LocalSdk localSdk = getSdk();
SdkWrapper localSdk = getSdk();
if (localSdk != null) {
mTargets = localSdk.getTargets();
} else {
@@ -696,7 +696,7 @@ public abstract class LintClient {
return mTargets;
}
protected LocalSdk mSdk;
protected SdkWrapper mSdk;
/**
* Returns the SDK installation (used to look up platforms etc)
@@ -704,11 +704,11 @@ public abstract class LintClient {
* @return the SDK if known
*/
@Nullable
public LocalSdk getSdk() {
public SdkWrapper getSdk() {
if (mSdk == null) {
File sdkHome = getSdkHome();
if (sdkHome != null) {
mSdk = new LocalSdk(sdkHome);
mSdk = SdkWrapper.createLocalSdk(sdkHome);
}
}
@@ -1927,7 +1927,7 @@ public class LintDriver {
@Nullable
@Override
public LocalSdk getSdk() {
public SdkWrapper getSdk() {
return mDelegate.getSdk();
}
@@ -0,0 +1,104 @@
/*
* 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()
}
}
@@ -22,11 +22,8 @@ import static com.android.SdkConstants.DOT_XML;
import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
import com.android.annotations.VisibleForTesting;
import com.android.sdklib.repository.FullRevision;
import com.android.sdklib.repository.descriptors.PkgType;
import com.android.sdklib.repository.local.LocalPkgInfo;
import com.android.sdklib.repository.local.LocalSdk;
import com.android.tools.klint.client.api.LintClient;
import com.android.tools.klint.client.api.SdkWrapper;
import com.android.tools.klint.detector.api.LintUtils;
import com.google.common.base.Charsets;
import com.google.common.collect.Lists;
@@ -138,15 +135,9 @@ public class ApiLookup {
@VisibleForTesting
@Nullable
static String getPlatformVersion(@NonNull LintClient client) {
LocalSdk sdk = client.getSdk();
SdkWrapper sdk = client.getSdk();
if (sdk != null) {
LocalPkgInfo pkgInfo = sdk.getPkgInfo(PkgType.PKG_PLATFORM_TOOLS);
if (pkgInfo != null) {
FullRevision version = pkgInfo.getDesc().getFullRevision();
if (version != null) {
return version.toShortString();
}
}
return sdk.getPlatformVersion();
}
return null;
@@ -4,6 +4,7 @@ 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
@@ -19,6 +20,14 @@ class AndroidModelFacade(val facet: AndroidFacet) {
}
}
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")
@@ -7,8 +7,6 @@ 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.repository.local.LocalSdk;
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;
@@ -50,7 +48,6 @@ import com.intellij.util.containers.HashMap;
import com.intellij.util.net.HttpConfigurable;
import org.jetbrains.android.facet.AndroidFacet;
import org.jetbrains.android.facet.AndroidRootUtil;
import org.jetbrains.android.sdk.AndroidSdkData;
import org.jetbrains.android.sdk.AndroidSdkType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -329,10 +326,10 @@ public class IntellijLintClient extends LintClient implements Disposable {
@Nullable
@Override
public LocalSdk getSdk() {
public SdkWrapper getSdk() {
if (mSdk == null) {
Module module = getModule();
LocalSdk sdk = getLocalSdk(module);
SdkWrapper sdk = getLocalSdk(module);
if (sdk != null) {
mSdk = sdk;
} else {
@@ -354,14 +351,11 @@ public class IntellijLintClient extends LintClient implements Disposable {
}
@Nullable
private static LocalSdk getLocalSdk(@Nullable Module module) {
private static SdkWrapper getLocalSdk(@Nullable Module module) {
if (module != null) {
AndroidFacet facet = AndroidFacet.getInstance(module);
if (facet != null) {
AndroidSdkData sdkData = facet.getSdkData();
if (sdkData != null) {
return sdkData.getLocalSdk();
}
return IntellijLintUtils.getModelFacade(facet).getLocalSdk();
}
}