<commit_before>/*
 * Copyright 2000-2005 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.intellij.psi.util;

import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.*;
import gnu.trove.THashMap;
import gnu.trove.TObjectHashingStrategy;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;


public class MethodSignatureUtil {
  private static final Logger LOG = Logger.getInstance("#com.intellij.psi.util.MethodSignatureUtil");

  private static final Key<CachedValue<MethodSignatureToMethods>> METHOD_SIGNATURES_COLLECTION_KEY = Key.create("METHOD_SIGNATURES_COLLECTION");

  public static MethodSignature createMethodSignature(@NonNls String name,
                                                      PsiParameterList parameterTypes,
                                                      PsiTypeParameterList typeParameterList,
                                                      PsiSubstitutor substitutor) {
    LOG.assertTrue(name != null);
    LOG.assertTrue(substitutor != null);
    return new MethodSignatureHandMade(name, parameterTypes, typeParameterList, substitutor);
  }

  public static MethodSignature createMethodSignature(@NonNls String name,
                                                      PsiType[] parameterTypes,
                                                      PsiTypeParameter[] typeParameterList,
                                                      PsiSubstitutor substitutor) {
    LOG.assertTrue(name != null);
    LOG.assertTrue(substitutor != null);
    return new MethodSignatureHandMade(name, parameterTypes, typeParameterList, substitutor);
  }

  public static final TObjectHashingStrategy<MethodSignature> METHOD_PARAMETERS_ERASURE_EQUALITY = new MethodParametersErasureEquality();

  /**
   * @deprecated use areSignaturesEqual() which takes correct substitutors
   */
  public static boolean areSignaturesEqual(PsiMethod method1, PsiMethod method2) {
    return method1.getSignature(PsiSubstitutor.EMPTY).equals(method2.getSignature(PsiSubstitutor.EMPTY));
  }

  public static boolean areSignaturesEqual(MethodSignature method1, MethodSignature method2) {
    if (method2 == method1) return true;
    if (checkDifferentSignaturesLightweight(method1, method2)) return false;
    PsiSubstitutor unifyingSubstitutor = getSuperMethodSignatureSubstitutor(method1, method2);
    return checkSignaturesEqualInner(method1, method2, unifyingSubstitutor);
  }

  private static boolean checkSignaturesEqualInner(final MethodSignature subSignature,
                                                   final MethodSignature superSignature,
                                                   PsiSubstitutor unifyingSubstitutor) {
    if (unifyingSubstitutor == null) return false;

    final PsiType[] subParameterTypes = subSignature.getParameterTypes();
    final PsiType[] superParameterTypes = superSignature.getParameterTypes();
    for (int i = 0; i < subParameterTypes.length; i++) {
      PsiType type1 = unifyingSubstitutor.substitute(subParameterTypes[i]);
      PsiType type2 = unifyingSubstitutor.substitute(superParameterTypes[i]);
      if (!Comparing.equal(type1, type2)) {
        return false;
      }
    }

    return true;
  }

  private static boolean checkDifferentSignaturesLightweight (MethodSignature sig1, MethodSignature sig2) {
    String name1 = sig1.getName();
    String name2 = sig2.getName();
    if (!name1.equals(name2)) return true;
    final PsiType[] parameterTypes1 = sig1.getParameterTypes();
    final PsiType[] parameterTypes2 = sig2.getParameterTypes();
    if (parameterTypes1.length != parameterTypes2.length) return true;

    // optimization: check for really different types in method parameters
    for (int i = 0; i < parameterTypes1.length; i++) {
      PsiType type1 = parameterTypes1[i];
      PsiType type2 = parameterTypes2[i];
      if (type1 instanceof PsiPrimitiveType != type2 instanceof PsiPrimitiveType) return true;
      if (type1 instanceof PsiPrimitiveType && !type1.equals(type2)) return true;
    }

    return false;
  }

  /**
   * @return Map: PsiMethod method -> List overrideEquivalentMethods list of override candidates methods declared in aClass ancestors including self
   */
  public static MethodSignatureToMethods getOverrideEquivalentMethods(PsiClass aClass) {
    CachedValue<MethodSignatureToMethods> cachedValue = aClass.getUserData(METHOD_SIGNATURES_COLLECTION_KEY);
    if (cachedValue == null) {
      MethodSignaturesProvider methodSignaturesProvider = new MethodSignaturesProvider(aClass);
      cachedValue = aClass.getManager().getCachedValuesManager().createCachedValue(methodSignaturesProvider,false);
      aClass.putUserData(METHOD_SIGNATURES_COLLECTION_KEY, cachedValue);
    }

    MethodSignatureToMethods map = cachedValue.getValue();
    if (map == null) {
      LOG.error("Return null for '" + PsiFormatUtil.formatClass(aClass, PsiFormatUtil.SHOW_FQ_NAME));
    }
    return map;
  }

  public static int computeHashCode(final MethodSignature methodSignature) {
    int result = methodSignature.getName().hashCode();

    PsiType[] parameterTypes = methodSignature.getParameterTypes();
    result += 37 * parameterTypes.length;
    PsiType firstParamType = parameterTypes.length != 0 ? parameterTypes[0] : null;
    if (firstParamType != null) {
      firstParamType = TypeConversionUtil.erasure(firstParamType);
      result += firstParamType.hashCode();
    }
    return result;
  }

  public static class MethodSignatureToMethods {
    private Map<MethodSignature, List<MethodSignatureBackedByPsiMethod>> myMap;

    public MethodSignatureToMethods() {
      myMap = new THashMap<MethodSignature, List<MethodSignatureBackedByPsiMethod>>(METHOD_PARAMETERS_ERASURE_EQUALITY);
    }

    public List<MethodSignatureBackedByPsiMethod> get(MethodSignature sig) {
      return myMap.get(sig);
    }

    public Collection<List<MethodSignatureBackedByPsiMethod>> values() {
      return myMap.values();
    }

    public void put(MethodSignature methodSignature, List<MethodSignatureBackedByPsiMethod> overrideEquivalentsList) {
      myMap.put(methodSignature, overrideEquivalentsList);
    }
  }

  private static class MethodSignaturesProvider
    implements CachedValueProvider<MethodSignatureToMethods> {
    private final PsiClass myClass;

    MethodSignaturesProvider(PsiClass aClass) {
      myClass = aClass;
    }

    public Result<MethodSignatureToMethods> compute() {
      long start = System.currentTimeMillis();
      try {
        MethodSignatureToMethods sameSignatureMethods = new MethodSignatureToMethods();
        computeMap(sameSignatureMethods, myClass);

        return new Result<MethodSignatureToMethods>
          (sameSignatureMethods,
           new Object[]{myClass, PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT});
      }
      finally {
        if (LOG.isDebugEnabled()) {
          long finish = System.currentTimeMillis();
          LOG.debug("Method collection built for " + PsiFormatUtil.formatClass(myClass, PsiFormatUtil.SHOW_FQ_NAME) + " in " +
                    (finish - start) +
                    " ms");
        }
      }<commit_msg>cleanup<commit_after>/*
 * Copyright 2000-2005 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.intellij.psi.util;

import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.*;
import gnu.trove.THashMap;
import gnu.trove.TObjectHashingStrategy;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;


public class MethodSignatureUtil {
  private static final Logger LOG = Logger.getInstance("#com.intellij.psi.util.MethodSignatureUtil");

  private static final Key<CachedValue<MethodSignatureToMethods>> METHOD_SIGNATURES_COLLECTION_KEY = Key.create("METHOD_SIGNATURES_COLLECTION");

  public static MethodSignature createMethodSignature(@NonNls String name,
                                                      PsiParameterList parameterTypes,
                                                      PsiTypeParameterList typeParameterList,
                                                      PsiSubstitutor substitutor) {
    LOG.assertTrue(name != null);
    LOG.assertTrue(substitutor != null);
    return new MethodSignatureHandMade(name, parameterTypes, typeParameterList, substitutor);
  }

  public static MethodSignature createMethodSignature(@NonNls String name,
                                                      PsiType[] parameterTypes,
                                                      PsiTypeParameter[] typeParameterList,
                                                      PsiSubstitutor substitutor) {
    LOG.assertTrue(name != null);
    LOG.assertTrue(substitutor != null);
    return new MethodSignatureHandMade(name, parameterTypes, typeParameterList, substitutor);
  }

  public static final TObjectHashingStrategy<MethodSignature> METHOD_PARAMETERS_ERASURE_EQUALITY = new MethodParametersErasureEquality();

  /**
   * @deprecated use areSignaturesEqual() which takes correct substitutors
   */
  public static boolean areSignaturesEqual(PsiMethod method1, PsiMethod method2) {
    return method1.getSignature(PsiSubstitutor.EMPTY).equals(method2.getSignature(PsiSubstitutor.EMPTY));
  }

  public static boolean areSignaturesEqual(MethodSignature method1, MethodSignature method2) {
    if (method2 == method1) return true;
    if (checkDifferentSignaturesLightweight(method1, method2)) return false;
    PsiSubstitutor unifyingSubstitutor = getSuperMethodSignatureSubstitutor(method1, method2);
    return checkSignaturesEqualInner(method1, method2, unifyingSubstitutor);
  }

  private static boolean checkSignaturesEqualInner(final MethodSignature subSignature,
                                                   final MethodSignature superSignature,
                                                   PsiSubstitutor unifyingSubstitutor) {
    if (unifyingSubstitutor == null) return false;

    final PsiType[] subParameterTypes = subSignature.getParameterTypes();
    final PsiType[] superParameterTypes = superSignature.getParameterTypes();
    for (int i = 0; i < subParameterTypes.length; i++) {
      PsiType type1 = unifyingSubstitutor.substitute(subParameterTypes[i]);
      PsiType type2 = unifyingSubstitutor.substitute(superParameterTypes[i]);
      if (!Comparing.equal(type1, type2)) {
        return false;
      }
    }

    return true;
  }

  private static boolean checkDifferentSignaturesLightweight (MethodSignature sig1, MethodSignature sig2) {
    String name1 = sig1.getName();
    String name2 = sig2.getName();
    if (!name1.equals(name2)) return true;
    final PsiType[] parameterTypes1 = sig1.getParameterTypes();
    final PsiType[] parameterTypes2 = sig2.getParameterTypes();
    if (parameterTypes1.length != parameterTypes2.length) return true;

    // optimization: check for really different types in method parameters
    for (int i = 0; i < parameterTypes1.length; i++) {
      PsiType type1 = parameterTypes1[i];
      PsiType type2 = parameterTypes2[i];
      if (type1 instanceof PsiPrimitiveType != type2 instanceof PsiPrimitiveType) return true;
      if (type1 instanceof PsiPrimitiveType && !type1.equals(type2)) return true;
    }

    return false;
  }

  /**
   * @return Map: PsiMethod method -> List overrideEquivalentMethods list of override candidates methods declared in aClass ancestors including self
   */
  public static MethodSignatureToMethods getOverrideEquivalentMethods(PsiClass aClass) {
    CachedValue<MethodSignatureToMethods> cachedValue = aClass.getUserData(METHOD_SIGNATURES_COLLECTION_KEY);
    if (cachedValue == null) {
      MethodSignaturesProvider methodSignaturesProvider = new MethodSignaturesProvider(aClass);
      cachedValue = aClass.getManager().getCachedValuesManager().createCachedValue(methodSignaturesProvider,false);
      aClass.putUserData(METHOD_SIGNATURES_COLLECTION_KEY, cachedValue);
    }

    MethodSignatureToMethods map = cachedValue.getValue();
    if (map == null) {
      LOG.error("Return null for '" + PsiFormatUtil.formatClass(aClass, PsiFormatUtil.SHOW_FQ_NAME));
    }
    return map;
  }

  public static int computeHashCode(final MethodSignature methodSignature) {
    int result = methodSignature.getName().hashCode();

    PsiType[] parameterTypes = methodSignature.getParameterTypes();
    result += 37 * parameterTypes.length;
    PsiType firstParamType = parameterTypes.length != 0 ? parameterTypes[0] : null;
    if (firstParamType != null) {
      firstParamType = TypeConversionUtil.erasure(firstParamType);
      result += firstParamType.hashCode();
    }
    return result;
  }

  public static class MethodSignatureToMethods {
    private Map<MethodSignature, List<MethodSignatureBackedByPsiMethod>> myMap;

    public MethodSignatureToMethods() {
      myMap = new THashMap<MethodSignature, List<MethodSignatureBackedByPsiMethod>>(METHOD_PARAMETERS_ERASURE_EQUALITY);
    }

    public List<MethodSignatureBackedByPsiMethod> get(MethodSignature sig) {
      return myMap.get(sig);
    }

    public Collection<List<MethodSignatureBackedByPsiMethod>> values() {
      return myMap.values();
    }

    public void put(MethodSignature methodSignature, List<MethodSignatureBackedByPsiMethod> overrideEquivalentsList) {
      myMap.put(methodSignature, overrideEquivalentsList);
    }
  }

  private static class MethodSignaturesProvider
    implements CachedValueProvider<MethodSignatureToMethods> {
    private final PsiClass myClass;

    MethodSignaturesProvider(PsiClass aClass) {
      myClass = aClass;
    }

    public Result<MethodSignatureToMethods> compute() {
      long start = System.currentTimeMillis();
      try {
        MethodSignatureToMethods sameSignatureMethods = new MethodSignatureToMethods();
        computeMap(sameSignatureMethods, myClass);

        return new Result<MethodSignatureToMethods>
          (sameSignatureMethods, myClass, PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT);
      }
      finally {
        if (LOG.isDebugEnabled()) {
          long finish = System.currentTimeMillis();
          LOG.debug("Method collection built for " + PsiFormatUtil.formatClass(myClass, PsiFormatUtil.SHOW_FQ_NAME) + " in " +
                    (finish - start) +
                    " ms");
        }
      }
{'fraction_non_alphanumeric': 0.08039376538146022, 'fraction_numerical': 0.007572411181927178, 'mean_word_length': 3.493337113694358, 'pattern_counts': {'":': 0, '<': 37, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 32, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6813651', 'n_tokens_mistral': 4208, 'n_tokens_neox': 4084, 'n_words': 989}