Skip to content
This repository has been archived by the owner on Aug 26, 2021. It is now read-only.

Commit

Permalink
Add support for checking generic type parameters
Browse files Browse the repository at this point in the history
In addition to checking qualifier annotations for matching up @Inject and @provides, this now also checks for matching generic type parameters.
  • Loading branch information
Matt Logan authored and Matt Logan committed Nov 26, 2015
1 parent 09b1ef6 commit ecded0a
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 6 deletions.
26 changes: 20 additions & 6 deletions src/com/squareup/ideaplugin/dagger/Decider.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@
import com.intellij.psi.PsiField;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiParameter;
import com.intellij.psi.PsiType;
import com.intellij.usages.Usage;
import com.intellij.usages.UsageInfo2UsageAdapter;
import com.intellij.usages.UsageTarget;

import java.util.List;
import java.util.Set;

import static com.squareup.ideaplugin.dagger.DaggerConstants.CLASS_INJECT;
Expand All @@ -21,10 +24,12 @@ public interface Decider {
public class ProvidesMethodDecider implements Decider {
private final PsiClass returnType;
private final Set<String> qualifierAnnotations;
private final List<PsiType> typeParameters;

public ProvidesMethodDecider(PsiMethod psiMethod) {
this.returnType = PsiConsultantImpl.getReturnClassFromMethod(psiMethod);
this.qualifierAnnotations = PsiConsultantImpl.getQualifierAnnotations(psiMethod);
this.typeParameters = PsiConsultantImpl.getTypeParameters(psiMethod);
}

@Override public boolean shouldShow(UsageTarget target, Usage usage) {
Expand All @@ -33,7 +38,8 @@ public ProvidesMethodDecider(PsiMethod psiMethod) {
PsiField field = PsiConsultantImpl.findField(element);
if (field != null //
&& PsiConsultantImpl.hasAnnotation(field, CLASS_INJECT) //
&& PsiConsultantImpl.hasQuailifierAnnotations(field, qualifierAnnotations)) {
&& PsiConsultantImpl.hasQuailifierAnnotations(field, qualifierAnnotations)
&& PsiConsultantImpl.hasTypeParameters(field, typeParameters)) {
return true;
}

Expand All @@ -43,7 +49,8 @@ public ProvidesMethodDecider(PsiMethod psiMethod) {
for (PsiParameter parameter : parameters) {
PsiClass parameterClass = PsiConsultantImpl.checkForLazyOrProvider(parameter);
if (parameterClass.equals(returnType) && PsiConsultantImpl.hasQuailifierAnnotations(
parameter, qualifierAnnotations)) {
parameter, qualifierAnnotations)
&& PsiConsultantImpl.hasTypeParameters(parameter, typeParameters)) {
return true;
}
}
Expand All @@ -59,7 +66,8 @@ public ProvidesMethodDecider(PsiMethod psiMethod) {
*/
public class ConstructorParameterInjectDecider extends IsAProviderDecider {
public ConstructorParameterInjectDecider(PsiParameter psiParameter) {
super(PsiConsultantImpl.getQualifierAnnotations(psiParameter));
super(PsiConsultantImpl.getQualifierAnnotations(psiParameter),
PsiConsultantImpl.getTypeParameters(psiParameter));
}
}

Expand All @@ -69,15 +77,18 @@ public ConstructorParameterInjectDecider(PsiParameter psiParameter) {
*/
public class FieldInjectDecider extends IsAProviderDecider {
public FieldInjectDecider(PsiField psiField) {
super(PsiConsultantImpl.getQualifierAnnotations(psiField));
super(PsiConsultantImpl.getQualifierAnnotations(psiField),
PsiConsultantImpl.getTypeParameters(psiField));
}
}

class IsAProviderDecider implements Decider {
private final Set<String> qualifierAnnotations;
private final List<PsiType> typeParameters;

public IsAProviderDecider(Set<String> qualifierAnnotations) {
public IsAProviderDecider(Set<String> qualifierAnnotations, List<PsiType> typeParameters) {
this.qualifierAnnotations = qualifierAnnotations;
this.typeParameters = typeParameters;
}

@Override public boolean shouldShow(UsageTarget target, Usage usage) {
Expand All @@ -98,7 +109,10 @@ public IsAProviderDecider(Set<String> qualifierAnnotations) {
// Right return type.
&& PsiConsultantImpl.getReturnClassFromMethod(psimethod)
.getName()
.equals(target.getName());
.equals(target.getName())

// Right type parameters.
&& PsiConsultantImpl.hasTypeParameters(psimethod, typeParameters);
}
}
}
33 changes: 33 additions & 0 deletions src/com/squareup/ideaplugin/dagger/PsiConsultantImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@
import com.intellij.psi.PsiType;
import com.intellij.psi.PsiVariable;
import com.intellij.psi.search.GlobalSearchScope;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import static com.squareup.ideaplugin.dagger.DaggerConstants.CLASS_LAZY;
Expand Down Expand Up @@ -158,6 +162,35 @@ private static PsiClass getPsiClass(PsiClass wrapperClass, PsiType psiFieldType)
return wrapperClass;
}

public static boolean hasTypeParameters(PsiElement psiElement, List<PsiType> typeParameters) {
List<PsiType> actualTypeParameters = getTypeParameters(psiElement);
return actualTypeParameters.equals(typeParameters);
}

public static List<PsiType> getTypeParameters(PsiElement psiElement) {
PsiClassType psiClassType = getPsiClassType(psiElement);
if (psiClassType == null) {
return new ArrayList<PsiType>();
}

if (PsiConsultantImpl.isLazyOrProvider(getClass(psiClassType))) {
psiClassType = extractFirstTypeParameter(psiClassType);
}

Collection<PsiType> typeParameters =
psiClassType.resolveGenerics().getSubstitutor().getSubstitutionMap().values();
return new ArrayList<PsiType>(typeParameters);
}

private static PsiClassType getPsiClassType(PsiElement psiElement) {
if (psiElement instanceof PsiVariable) {
return (PsiClassType) ((PsiVariable) psiElement).getType();
} else if (psiElement instanceof PsiMethod) {
return (PsiClassType) ((PsiMethod) psiElement).getReturnType();
}
return null;
}

private static boolean isLazyOrProvider(PsiClass psiClass) {
if (psiClass == null) {
return false;
Expand Down

0 comments on commit ecded0a

Please sign in to comment.