package com.intellij.refactoring.genUtils;
import com.intellij.psi.*;
import com.intellij.util.IncorrectOperationException;
import java.util.Collection;
import java.util.Map;
/**
* Copyright 2012 Université de Nantes
* Contributor : Julien Cohen (Ascola team, Univ. Nantes)
*
* 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.
*/
public class GenBuildUtils {
public static void generifyAbstractMethod(PsiMethod m, ParamSubstitution lp){
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(m.getProject());
for (Integer pos : lp.keySet()){
final PsiTypeParameter t1 = lp.get(pos);
final String typename = t1.getName();
final PsiType t2 = factory.createTypeFromText(typename, null);
final PsiElement e = factory.createTypeElement(t2);
if (pos == -1) {
m.getReturnTypeElement().replace(e);
}
else {
m.getParameterList().getParameters()[pos].getTypeElement().replace(e);
}
}
}
static String buildTypeParameter(int pos, String name, Collection<String> boundNames){
String tentative = (pos == -1) ? ("T" + name + "RET") : ("T" + name + pos) ;
while (boundNames.contains(tentative)) tentative= tentative+"x" ;
return tentative;
}
public static void updateExtendsStatementsInSisterClasses(
DependentSubstitution megasub,
PsiClass superClass,
PsiElementFactory factory) {
for (PsiTypeParameter theTypeParameter: megasub.keySet()){
final Map<PsiClass,PsiType> m = megasub.get(theTypeParameter);
for (PsiClass c : m.keySet()){
final PsiJavaCodeReferenceElement extendsRef = findReferenceToSuperclass(c, superClass);
PsiType theConcreteType = megasub.get(theTypeParameter, c);
addTypeParameterToReference(extendsRef, theConcreteType, factory);
}
}
}
/** Replace "class A extends S" by "class A extends S < Object >" when S has a type parameter.
*
* @param superclass
* @param toBeAligned
* @param factory
*
* Modifies toBeAligned.
* If the extends is already aligned with the superclass, does nothing.
*
*/
public static void alignParameters(PsiClass superclass, PsiClass toBeAligned, PsiElementFactory factory){
final PsiJavaCodeReferenceElement extendsRef = findReferenceToSuperclass(toBeAligned, superclass);
final int len = extendsRef.getParameterList().getTypeParameterElements().length;
final int len_super = superclass.getTypeParameters().length;
final PsiType ob = factory.createTypeFromText("Object", null);
for (int i=0; i< len_super - len; i++ ) {
addTypeParameterToReference(extendsRef, ob, factory);
}
}
static PsiJavaCodeReferenceElement findReferenceToSuperclass(PsiClass c, PsiClass s){
final String superName = s.getQualifiedName();
if (s.isInterface()){
for (PsiJavaCodeReferenceElement elem : c.getImplementsList().getReferenceElements()) {
if ((elem.getQualifiedName()).equals(superName)) return elem ;
}
}
//else {
for (PsiJavaCodeReferenceElement elem : c.getExtendsList().getReferenceElements()) { // for classes and interfaces
if ((elem.getQualifiedName()).equals(superName)) return elem ;
}
//}
throw new IncorrectOperationException("Internal error: Super class extends/implement statement not found.");
}
static void addTypeParameterToReference(PsiJavaCodeReferenceElement r, PsiType t, PsiElementFactory factory ){
r.getParameterList().add(factory.createTypeElement(t));
}
}