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="android-plugin" level="project" />
<orderEntry type="library" name="intellij-core" level="project" /> <orderEntry type="library" name="intellij-core" level="project" />
<orderEntry type="module" module-name="android-annotations" /> <orderEntry type="module" module-name="android-annotations" />
<orderEntry type="library" name="kotlin-runtime" level="project" />
</component> </component>
</module> </module>
@@ -685,7 +685,7 @@ public abstract class LintClient {
@NonNull @NonNull
public IAndroidTarget[] getTargets() { public IAndroidTarget[] getTargets() {
if (mTargets == null) { if (mTargets == null) {
LocalSdk localSdk = getSdk(); SdkWrapper localSdk = getSdk();
if (localSdk != null) { if (localSdk != null) {
mTargets = localSdk.getTargets(); mTargets = localSdk.getTargets();
} else { } else {
@@ -696,7 +696,7 @@ public abstract class LintClient {
return mTargets; return mTargets;
} }
protected LocalSdk mSdk; protected SdkWrapper mSdk;
/** /**
* Returns the SDK installation (used to look up platforms etc) * Returns the SDK installation (used to look up platforms etc)
@@ -704,11 +704,11 @@ public abstract class LintClient {
* @return the SDK if known * @return the SDK if known
*/ */
@Nullable @Nullable
public LocalSdk getSdk() { public SdkWrapper getSdk() {
if (mSdk == null) { if (mSdk == null) {
File sdkHome = getSdkHome(); File sdkHome = getSdkHome();
if (sdkHome != null) { if (sdkHome != null) {
mSdk = new LocalSdk(sdkHome); mSdk = SdkWrapper.createLocalSdk(sdkHome);
} }
} }
@@ -1927,7 +1927,7 @@ public class LintDriver {
@Nullable @Nullable
@Override @Override
public LocalSdk getSdk() { public SdkWrapper getSdk() {
return mDelegate.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.NonNull;
import com.android.annotations.Nullable; import com.android.annotations.Nullable;
import com.android.annotations.VisibleForTesting; 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.LintClient;
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.google.common.base.Charsets; import com.google.common.base.Charsets;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
@@ -138,15 +135,9 @@ public class ApiLookup {
@VisibleForTesting @VisibleForTesting
@Nullable @Nullable
static String getPlatformVersion(@NonNull LintClient client) { static String getPlatformVersion(@NonNull LintClient client) {
LocalSdk sdk = client.getSdk(); SdkWrapper sdk = client.getSdk();
if (sdk != null) { if (sdk != null) {
LocalPkgInfo pkgInfo = sdk.getPkgInfo(PkgType.PKG_PLATFORM_TOOLS); return sdk.getPlatformVersion();
if (pkgInfo != null) {
FullRevision version = pkgInfo.getDesc().getFullRevision();
if (version != null) {
return version.toShortString();
}
}
} }
return null; return null;
@@ -4,6 +4,7 @@ import com.android.builder.model.AndroidProject
import com.android.builder.model.SourceProvider import com.android.builder.model.SourceProvider
import com.android.builder.model.Variant import com.android.builder.model.Variant
import com.android.tools.idea.gradle.util.GradleUtil import com.android.tools.idea.gradle.util.GradleUtil
import com.android.tools.klint.client.api.SdkWrapper
import org.jetbrains.android.facet.AndroidFacet import org.jetbrains.android.facet.AndroidFacet
import kotlin.reflect.memberFunctions import kotlin.reflect.memberFunctions
import kotlin.reflect.staticFunctions 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 fun isModelReady() = model != null
@Suppress("UNCHECKED_CAST") @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.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.repository.local.LocalSdk;
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;
@@ -50,7 +48,6 @@ import com.intellij.util.containers.HashMap;
import com.intellij.util.net.HttpConfigurable; import com.intellij.util.net.HttpConfigurable;
import org.jetbrains.android.facet.AndroidFacet; import org.jetbrains.android.facet.AndroidFacet;
import org.jetbrains.android.facet.AndroidRootUtil; import org.jetbrains.android.facet.AndroidRootUtil;
import org.jetbrains.android.sdk.AndroidSdkData;
import org.jetbrains.android.sdk.AndroidSdkType; import org.jetbrains.android.sdk.AndroidSdkType;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@@ -329,10 +326,10 @@ public class IntellijLintClient extends LintClient implements Disposable {
@Nullable @Nullable
@Override @Override
public LocalSdk getSdk() { public SdkWrapper getSdk() {
if (mSdk == null) { if (mSdk == null) {
Module module = getModule(); Module module = getModule();
LocalSdk sdk = getLocalSdk(module); SdkWrapper sdk = getLocalSdk(module);
if (sdk != null) { if (sdk != null) {
mSdk = sdk; mSdk = sdk;
} else { } else {
@@ -354,14 +351,11 @@ public class IntellijLintClient extends LintClient implements Disposable {
} }
@Nullable @Nullable
private static LocalSdk getLocalSdk(@Nullable Module module) { private static SdkWrapper 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) {
AndroidSdkData sdkData = facet.getSdkData(); return IntellijLintUtils.getModelFacade(facet).getLocalSdk();
if (sdkData != null) {
return sdkData.getLocalSdk();
}
} }
} }