summaryrefslogtreecommitdiff
path: root/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/ParametersMatcher.java
blob: fd4d5d7c2d0bf1bcef48fa57650cb408372b49af (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
package com.intellij.codeInsight.completion.methodChains.search;

import com.intellij.codeInsight.completion.methodChains.completion.context.ChainCompletionContext;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiParameter;
import com.intellij.psi.PsiPrimitiveType;
import com.intellij.psi.PsiType;
import org.jetbrains.annotations.NotNull;

import java.util.NavigableSet;
import java.util.Set;
import java.util.TreeSet;

/**
 * @author Dmitry Batkovich
 */
public final class ParametersMatcher {

  private ParametersMatcher() {}

  public static MatchResult matchParameters(final MethodsChain chain, final ChainCompletionContext context) {
    MatchResult overallResult = EMPTY;
    for (final PsiMethod[] methods : chain.getPath()) {
      final NavigableSet<MatchResult> matchResults = new TreeSet<MatchResult>();
      for (final PsiMethod method : methods) {
        matchResults.add(matchParameters(method, context, chain.getExcludedQNames()));
      }
      final MatchResult best = matchResults.first();
      overallResult = overallResult.add(best);
    }
    return overallResult;
  }

  private static MatchResult matchParameters(final PsiMethod method, final ChainCompletionContext context, final Set<String> additionalExcludedNames) {
    int matched = 0;
    int unMatched = 0;
    boolean hasTarget = false;
    for (final PsiParameter parameter : method.getParameterList().getParameters()) {
      final PsiType type = parameter.getType();
      final String canonicalText = type.getCanonicalText();
      if (context.contains(canonicalText) || type instanceof PsiPrimitiveType) {
        matched++;
      }
      else {
        unMatched++;
      }
      if (context.getTargetQName().equals(canonicalText) || additionalExcludedNames.contains(canonicalText)) {
        hasTarget = true;
      }
    }
    return new MatchResult(matched, unMatched, hasTarget);
  }

  private static final MatchResult EMPTY = new MatchResult(0, 0, false);

  public static class MatchResult implements Comparable<MatchResult> {
    private final int myMatched;
    private final int myUnMatched;
    private final boolean myHasTarget;

    private MatchResult(final int matched, final int unMatched, final boolean hasTarget) {
      myMatched = matched;
      myUnMatched = unMatched;
      myHasTarget = hasTarget;
    }

    public int getMatched() {
      return myMatched;
    }

    public int getUnMatched() {
      return myUnMatched;
    }

    public boolean hasTarget() {
      return myHasTarget;
    }

    public MatchResult add(final MatchResult other) {
      return new MatchResult(getMatched() + other.getMatched(), getUnMatched() + other.getUnMatched(), other.myHasTarget || myHasTarget);
    }

    public boolean noUnmatchedAndHasMatched() {
      return myUnMatched == 0 && myMatched != 0;
    }

    @Override
    public int compareTo(@NotNull final MatchResult other) {
      final int sub = getUnMatched() - other.getUnMatched();
      if (sub != 0) {
        return sub;
      }
      return getMatched() - other.getMatched();
    }
  }
}