diff --git a/plugins/lint/lint-checks/lint-checks.iml b/plugins/lint/lint-checks/lint-checks.iml
index 4348c78f8f4..84af3755987 100644
--- a/plugins/lint/lint-checks/lint-checks.iml
+++ b/plugins/lint/lint-checks/lint-checks.iml
@@ -9,6 +9,7 @@
+
diff --git a/plugins/lint/lint-idea/lint-idea.iml b/plugins/lint/lint-idea/lint-idea.iml
index 9041e5bc8e8..93dc751f6a3 100644
--- a/plugins/lint/lint-idea/lint-idea.iml
+++ b/plugins/lint/lint-idea/lint-idea.iml
@@ -10,6 +10,7 @@
+
diff --git a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidModelFacade.kt b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidModelFacade.kt
new file mode 100644
index 00000000000..7bf38c07e49
--- /dev/null
+++ b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/AndroidModelFacade.kt
@@ -0,0 +1,120 @@
+/*
+ * 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.
+ */
+
+/*
+ * 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 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 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 isModelReady() = model != null
+
+ @Suppress("UNCHECKED_CAST")
+ fun getFlavorSourceProviders(): List?
+ = getFacetOrModel("getFlavorSourceProviders") as? List
+
+ 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)
+ }
+
+ 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[0].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
+ }
+
+}
\ No newline at end of file
diff --git a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IntellijLintClient.java b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IntellijLintClient.java
index 235e06a454e..c211eb38b80 100644
--- a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IntellijLintClient.java
+++ b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IntellijLintClient.java
@@ -382,9 +382,9 @@ public class IntellijLintClient extends com.android.tools.klint.client.api.LintC
Module module = getModule();
if (module != null) {
AndroidFacet facet = AndroidFacet.getInstance(module);
- return facet != null && facet.isGradleProject();
+ return facet != null && IntellijLintUtils.isGradleModule(facet);
}
- return Projects.isGradleProject(myProject);
+ return false;
}
@Override
diff --git a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IntellijLintProject.java b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IntellijLintProject.java
index a724c0773ad..4c1281b350e 100644
--- a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IntellijLintProject.java
+++ b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IntellijLintProject.java
@@ -19,7 +19,6 @@ import com.android.annotations.NonNull;
import com.android.builder.model.*;
import com.android.sdklib.AndroidTargetHash;
import com.android.sdklib.AndroidVersion;
-import com.android.tools.idea.gradle.IdeaAndroidProject;
import com.android.tools.idea.gradle.util.GradleUtil;
import com.android.tools.idea.model.AndroidModuleInfo;
import com.android.tools.idea.model.ManifestInfo;
@@ -54,6 +53,7 @@ import java.util.*;
import static com.android.SdkConstants.APPCOMPAT_LIB_ARTIFACT;
import static com.android.SdkConstants.SUPPORT_LIB_ARTIFACT;
+import static org.jetbrains.android.inspections.klint.IntellijLintUtils.*;
/**
* An {@linkplain IntellijLintProject} represents a lint project, which typically corresponds to a {@link Module},
@@ -245,7 +245,7 @@ class IntellijLintProject extends Project {
}
AndroidFacet facet = AndroidFacet.getInstance(module);
- if (facet != null && facet.isGradleProject()) {
+ if (facet != null && isGradleModule(facet)) {
addGradleLibraryProjects(client, files, libraryMap, projects, facet, project, projectMap, dependencies);
}
@@ -301,10 +301,10 @@ class IntellijLintProject extends Project {
project = new LintModuleProject(client, dir, dir, module);
AndroidFacet f = findAndroidFacetInProject(module.getProject());
if (f != null) {
- project.mGradleProject = f.isGradleProject();
+ project.mGradleProject = isGradleModule(f);
}
}
- else if (facet.isGradleProject()) {
+ else if (isGradleModule((facet))) {
project = new LintGradleProject(client, dir, dir, facet);
}
else {
@@ -340,9 +340,11 @@ class IntellijLintProject extends Project {
@NonNull LintModuleProject project,
@NonNull Map projectMap,
@NonNull List dependencies) {
- File dir;IdeaAndroidProject gradleProject = facet.getIdeaAndroidProject();
- if (gradleProject != null) {
- Collection libraries = gradleProject.getSelectedVariant().getMainArtifact().getDependencies().getLibraries();
+ File dir;
+ AndroidModelFacade androidModelFacade = getModelFacade(facet);
+ Variant selectedVariant = androidModelFacade.getSelectedVariant();
+ if (selectedVariant != null) {
+ Collection libraries = selectedVariant.getMainArtifact().getDependencies().getLibraries();
for (AndroidLibrary library : libraries) {
Project p = libraryMap.get(library);
if (p == null) {
@@ -540,7 +542,7 @@ class IntellijLintProject extends Project {
@Override
public List getProguardFiles() {
if (mProguardFiles == null) {
- assert !myFacet.isGradleProject(); // Should be overridden to read from gradle state
+ assert !isGradleModule(myFacet); // Should be overridden to read from gradle state
final JpsAndroidModuleProperties properties = myFacet.getProperties();
if (properties.RUN_PROGUARD) {
@@ -659,7 +661,7 @@ class IntellijLintProject extends Project {
mManifestFiles.add(mainManifest);
}
- List flavorSourceProviders = myFacet.getFlavorSourceProviders();
+ List flavorSourceProviders = getModelFacade(myFacet).getFlavorSourceProviders();
if (flavorSourceProviders != null) {
for (SourceProvider provider : flavorSourceProviders) {
File manifestFile = provider.getManifestFile();
@@ -669,7 +671,7 @@ class IntellijLintProject extends Project {
}
}
- SourceProvider multiProvider = myFacet.getMultiFlavorSourceProvider();
+ SourceProvider multiProvider = getModelFacade(myFacet).getMultiFlavorSourceProvider();
if (multiProvider != null) {
File manifestFile = multiProvider.getManifestFile();
if (manifestFile.exists()) {
@@ -677,7 +679,7 @@ class IntellijLintProject extends Project {
}
}
- SourceProvider buildTypeSourceProvider = myFacet.getBuildTypeSourceProvider();
+ SourceProvider buildTypeSourceProvider = getModelFacade(myFacet).getBuildTypeSourceProvider();
if (buildTypeSourceProvider != null) {
File manifestFile = buildTypeSourceProvider.getManifestFile();
if (manifestFile.exists()) {
@@ -685,7 +687,7 @@ class IntellijLintProject extends Project {
}
}
- SourceProvider variantProvider = myFacet.getVariantSourceProvider();
+ SourceProvider variantProvider = getModelFacade(myFacet).getVariantSourceProvider();
if (variantProvider != null) {
File manifestFile = variantProvider.getManifestFile();
if (manifestFile.exists()) {
@@ -701,10 +703,11 @@ class IntellijLintProject extends Project {
@Override
public List getProguardFiles() {
if (mProguardFiles == null) {
- if (myFacet.isGradleProject()) {
- IdeaAndroidProject gradleProject = myFacet.getIdeaAndroidProject();
- if (gradleProject != null) {
- ProductFlavor flavor = gradleProject.getDelegate().getDefaultConfig().getProductFlavor();
+ if (isGradleModule(myFacet)) {
+ AndroidModelFacade androidModelFacade = getModelFacade(myFacet);
+ AndroidProject androidProject = androidModelFacade.getAndroidProject();
+ if (androidProject != null) {
+ ProductFlavor flavor = androidProject.getDefaultConfig().getProductFlavor();
mProguardFiles = Lists.newArrayList();
for (File file : flavor.getProguardFiles()) {
if (file.exists()) {
@@ -742,10 +745,10 @@ class IntellijLintProject extends Project {
// the AndroidDexCompiler settings the way java source roots are mapped into
// the module content root settings
File dir = null;
- if (myFacet.isGradleProject()) {
- IdeaAndroidProject gradleProject = myFacet.getIdeaAndroidProject();
- if (gradleProject != null) {
- Variant variant = gradleProject.getSelectedVariant();
+ if (isGradleModule(myFacet)) {
+ AndroidModelFacade androidModelFacade = getModelFacade(myFacet);
+ Variant variant = androidModelFacade.getSelectedVariant();
+ if (variant != null) {
dir = variant.getMainArtifact().getClassesFolder();
}
}
@@ -767,9 +770,10 @@ class IntellijLintProject extends Project {
public List getJavaLibraries() {
if (SUPPORT_CLASS_FILES) {
if (mJavaLibraries == null) {
- if (myFacet.isGradleProject() && myFacet.getIdeaAndroidProject() != null) {
- IdeaAndroidProject gradleProject = myFacet.getIdeaAndroidProject();
- Collection libs = gradleProject.getSelectedVariant().getMainArtifact().getDependencies().getJavaLibraries();
+ AndroidModelFacade androidModelFacade = getModelFacade(myFacet);
+ Variant selectedVariant = androidModelFacade.getSelectedVariant();
+ if (isGradleModule(myFacet) && selectedVariant != null) {
+ Collection libs = selectedVariant.getMainArtifact().getDependencies().getJavaLibraries();
mJavaLibraries = Lists.newArrayListWithExpectedSize(libs.size());
for (JavaLibrary lib : libs) {
File jar = lib.getJarFile();
@@ -798,12 +802,7 @@ class IntellijLintProject extends Project {
return manifestPackage;
}
- IdeaAndroidProject project = myFacet.getIdeaAndroidProject();
- if (project != null) {
- return project.computePackageName();
- }
-
- return null;
+ return getModelFacade(myFacet).computePackageName();
}
@NonNull
@@ -828,9 +827,10 @@ class IntellijLintProject extends Project {
@Override
public int getBuildSdk() {
- IdeaAndroidProject ideaAndroidProject = myFacet.getIdeaAndroidProject();
- if (ideaAndroidProject != null) {
- String compileTarget = ideaAndroidProject.getDelegate().getCompileTarget();
+ AndroidModelFacade androidModelFacade = getModelFacade(myFacet);
+ AndroidProject androidProject = androidModelFacade.getAndroidProject();
+ if (androidProject != null) {
+ String compileTarget = androidProject.getCompileTarget();
AndroidVersion version = AndroidTargetHash.getPlatformVersion(compileTarget);
if (version != null) {
return version.getApiLevel();
@@ -848,24 +848,14 @@ class IntellijLintProject extends Project {
@Nullable
@Override
public AndroidProject getGradleProjectModel() {
- IdeaAndroidProject project = myFacet.getIdeaAndroidProject();
- if (project != null) {
- project.getSelectedVariant();
- return project.getDelegate();
- }
-
- return null;
+ AndroidModelFacade androidModelFacade = getModelFacade(myFacet);
+ return androidModelFacade.getAndroidProject();
}
@Nullable
@Override
public Variant getCurrentVariant() {
- IdeaAndroidProject project = myFacet.getIdeaAndroidProject();
- if (project != null) {
- return project.getSelectedVariant();
- }
-
- return null;
+ return getModelFacade(myFacet).getSelectedVariant();
}
@Nullable
@@ -879,8 +869,9 @@ class IntellijLintProject extends Project {
public Boolean dependsOn(@NonNull String artifact) {
if (SUPPORT_LIB_ARTIFACT.equals(artifact)) {
if (mSupportLib == null) {
- if (myFacet.isGradleProject() && myFacet.getIdeaAndroidProject() != null) {
- mSupportLib = GradleUtil.dependsOn(myFacet.getIdeaAndroidProject(), artifact);
+ AndroidModelFacade facade = getModelFacade(myFacet);
+ if (isGradleModule(myFacet) && facade.isModelReady()) {
+ mSupportLib = facade.getDependsOn(artifact);
} else {
mSupportLib = depsDependsOn(this, artifact);
}
@@ -888,8 +879,9 @@ class IntellijLintProject extends Project {
return mSupportLib;
} else if (APPCOMPAT_LIB_ARTIFACT.equals(artifact)) {
if (mAppCompat == null) {
- if (myFacet.isGradleProject() && myFacet.getIdeaAndroidProject() != null) {
- mAppCompat = GradleUtil.dependsOn(myFacet.getIdeaAndroidProject(), artifact);
+ AndroidModelFacade facade = getModelFacade(myFacet);
+ if (isGradleModule(myFacet) && facade.isModelReady()) {
+ mAppCompat = facade.getDependsOn(artifact);
} else {
mAppCompat = depsDependsOn(this, artifact);
}
@@ -897,8 +889,9 @@ class IntellijLintProject extends Project {
return mAppCompat;
} else {
// Some other (not yet directly cached result)
- if (myFacet.isGradleProject() && myFacet.getIdeaAndroidProject() != null
- && GradleUtil.dependsOn(myFacet.getIdeaAndroidProject(), artifact)) {
+ AndroidModelFacade facade = getModelFacade(myFacet);
+ if (isGradleModule(myFacet) && facade.isModelReady()
+ && facade.getDependsOn(artifact)) {
return true;
}
diff --git a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IntellijLintUtils.java b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IntellijLintUtils.java
index 9eca40210f7..896764b2a31 100644
--- a/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IntellijLintUtils.java
+++ b/plugins/lint/lint-idea/src/org/jetbrains/android/inspections/klint/IntellijLintUtils.java
@@ -22,7 +22,11 @@ import com.android.builder.model.SourceProvider;
import com.android.tools.klint.client.api.LintRequest;
import com.google.common.base.Splitter;
import com.intellij.debugger.engine.JVMNameUtil;
+import com.intellij.facet.Facet;
import com.intellij.ide.util.JavaAnonymousClassesHelper;
+import com.intellij.openapi.externalSystem.model.ProjectSystemId;
+import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
+import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.io.FileUtil;
@@ -61,6 +65,8 @@ public class IntellijLintUtils {
@NonNls
public static final String SUPPRESS_WARNINGS_FQCN = "java.lang.SuppressWarnings";
+ private static final ProjectSystemId GRADLE_ID = new ProjectSystemId("GRADLE");
+
/**
* Gets the location of the given element
*
@@ -362,13 +368,33 @@ public class IntellijLintUtils {
return true;
}
+ public static boolean isProjectReady(AndroidFacet facet) {
+ try {
+ return AndroidFacet.class.getMethod("getIdeaAndroidProject", AndroidFacet.class).invoke(facet) != null;
+ } catch (Exception e) {
+ try {
+ return AndroidFacet.class.getMethod("getAndroidModel", AndroidFacet.class).invoke(facet) != null;
+ } catch (Exception ignored) {}
+ }
+ return false;
+ }
+
+ public static AndroidModelFacade getModelFacade(AndroidFacet facet) {
+ return new AndroidModelFacade(facet);
+ }
+
+ public static boolean isGradleModule(Facet> facet) {
+ Module module = facet.getModule();
+ return ExternalSystemApiUtil.isExternalSystemAwareModule(GRADLE_ID, module);
+ }
+
/** Returns the resource directories to use for the given module */
@NotNull
public static List getResourceDirectories(@NotNull AndroidFacet facet) {
- if (facet.isGradleProject()) {
+ if (isGradleModule(facet)) {
List resDirectories = new ArrayList();
resDirectories.addAll(facet.getMainSourceProvider().getResDirectories());
- List flavorSourceProviders = facet.getFlavorSourceProviders();
+ List flavorSourceProviders = getModelFacade(facet).getFlavorSourceProviders();
if (flavorSourceProviders != null) {
for (SourceProvider provider : flavorSourceProviders) {
for (File file : provider.getResDirectories()) {
@@ -379,7 +405,7 @@ public class IntellijLintUtils {
}
}
- SourceProvider buildTypeSourceProvider = facet.getBuildTypeSourceProvider();
+ SourceProvider buildTypeSourceProvider = getModelFacade(facet).getBuildTypeSourceProvider();
if (buildTypeSourceProvider != null) {
for (File file : buildTypeSourceProvider.getResDirectories()) {
if (file.isDirectory()) {