type migration: make part of platform

This commit is contained in:
Anna Kozlova
2014-07-14 15:33:14 +02:00
parent 581cf8056c
commit 5253ba2ac8
986 changed files with 14 additions and 25 deletions
@@ -0,0 +1,23 @@
<idea-plugin>
<extensions defaultExtensionNs="com.intellij">
<codeInsight.changeVariableTypeQuickFixProvider
implementation="com.intellij.refactoring.typeMigration.TypeMigrationVariableTypeFixProvider"/>
<conversion.rule implementation="com.intellij.refactoring.typeMigration.rules.ListArrayConversionRule"/>
<conversion.rule implementation="com.intellij.refactoring.typeMigration.rules.AtomicConversionRule"/>
<conversion.rule implementation="com.intellij.refactoring.typeMigration.rules.BoxingTypeConversionRule"/>
<conversion.rule implementation="com.intellij.refactoring.typeMigration.rules.ElementToArrayConversionRule"/>
<conversion.rule implementation="com.intellij.refactoring.typeMigration.rules.ThreadLocalConversionRule"/>
<intentionAction>
<className>com.intellij.refactoring.typeMigration.intentions.ConvertFieldToAtomicIntention</className>
<category>Concurrency</category>
</intentionAction>
<intentionAction>
<className>com.intellij.refactoring.typeMigration.intentions.ConvertFieldToThreadLocalIntention</className>
<category>Concurrency</category>
</intentionAction>
<intentionAction>
<className>com.intellij.refactoring.typeMigration.intentions.ChangeClassParametersIntention</className>
<category>Declaration</category>
</intentionAction>
</extensions>
</idea-plugin>
@@ -0,0 +1,101 @@
package com.intellij.refactoring.typeMigration;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiExpression;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.structuralsearch.MatchOptions;
import com.intellij.structuralsearch.plugin.replace.ReplaceOptions;
import com.intellij.structuralsearch.plugin.replace.impl.Replacer;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NonNls;
/**
* Created by IntelliJ IDEA.
* User: db
* Date: Sep 28, 2004
* Time: 7:13:53 PM
* To change this template use File | Settings | File Templates.
*/
public class TypeConversionDescriptor extends TypeConversionDescriptorBase {
private static final Logger LOG = Logger.getInstance("#" + TypeConversionDescriptor.class.getName());
private String myStringToReplace = null;
private String myReplaceByString = "$";
private PsiExpression myExpression;
public TypeConversionDescriptor(@NonNls final String stringToReplace, @NonNls final String replaceByString) {
myStringToReplace = stringToReplace;
myReplaceByString = replaceByString;
}
public TypeConversionDescriptor(@NonNls final String stringToReplace, @NonNls final String replaceByString, final PsiExpression expression) {
myStringToReplace = stringToReplace;
myReplaceByString = replaceByString;
myExpression = expression;
}
public void setStringToReplace(String stringToReplace) {
myStringToReplace = stringToReplace;
}
public void setReplaceByString(String replaceByString) {
myReplaceByString = replaceByString;
}
public String getStringToReplace() {
return myStringToReplace;
}
public String getReplaceByString() {
return myReplaceByString;
}
public PsiExpression getExpression() {
return myExpression;
}
public void setExpression(final PsiExpression expression) {
myExpression = expression;
}
@Override
public void replace(PsiExpression expression) {
if (getExpression() != null) expression = getExpression();
final Project project = expression.getProject();
final ReplaceOptions options = new ReplaceOptions();
options.setMatchOptions(new MatchOptions());
final Replacer replacer = new Replacer(project, null);
try {
final String replacement = replacer.testReplace(expression.getText(), getStringToReplace(), getReplaceByString(), options);
try {
JavaCodeStyleManager.getInstance(project).shortenClassReferences(expression.replace(
JavaPsiFacade.getInstance(project).getElementFactory().createExpressionFromText(replacement, expression)));
}
catch (IncorrectOperationException e) {
LOG.error(e);
}
}
catch (IncorrectOperationException e) {
LOG.error(e);
}
}
@Override
public String toString() {
StringBuffer buf = new StringBuffer();
if (myReplaceByString != null) {
buf.append(myReplaceByString);
}
if (myStringToReplace != null) {
if (buf.length() > 0) buf.append(" ");
buf.append(myStringToReplace);
}
if (myExpression != null) {
if (buf.length() > 0) buf.append(" ");
buf.append(myExpression.getText());
}
return buf.toString();
}
}
@@ -0,0 +1,61 @@
/*
* User: anna
* Date: 27-Aug-2009
*/
package com.intellij.refactoring.typeMigration;
import com.intellij.codeInsight.FileModificationService;
import com.intellij.codeInsight.daemon.impl.quickfix.VariableTypeFix;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInsight.quickfix.ChangeVariableTypeQuickFixProvider;
import com.intellij.openapi.command.undo.UndoUtil;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiType;
import com.intellij.psi.PsiVariable;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class TypeMigrationVariableTypeFixProvider implements ChangeVariableTypeQuickFixProvider {
private static final Logger LOG1 = Logger.getInstance("#" + TypeMigrationVariableTypeFixProvider.class.getName());
@NotNull
public IntentionAction[] getFixes(@NotNull PsiVariable variable, @NotNull PsiType toReturn) {
return new IntentionAction[]{new VariableTypeFix(variable, toReturn) {
@NotNull
@Override
public String getText() {
return "Migrate \'" + myName + "\' type to \'" + getReturnType().getCanonicalText() + "\'";
}
@Override
public void invoke(@NotNull Project project,
@NotNull PsiFile file,
@Nullable("is null when called from inspection") Editor editor,
@NotNull PsiElement startElement,
@NotNull PsiElement endElement) {
final PsiVariable myVariable = (PsiVariable)startElement;
if (!FileModificationService.getInstance().prepareFileForWrite(myVariable.getContainingFile())) return;
try {
myVariable.normalizeDeclaration();
final TypeMigrationRules rules = new TypeMigrationRules(TypeMigrationLabeler.getElementType(myVariable));
rules.setMigrationRootType(getReturnType());
rules.setBoundScope(GlobalSearchScope.projectScope(project));
TypeMigrationProcessor.runHighlightingTypeMigration(project, editor, rules, myVariable);
JavaCodeStyleManager.getInstance(project).shortenClassReferences(myVariable);
UndoUtil.markPsiFileForUndo(file);
}
catch (IncorrectOperationException e) {
LOG1.error(e);
}
}
}};
}
}
@@ -0,0 +1,124 @@
package com.intellij.refactoring.typeMigration.intentions;
import com.intellij.codeInsight.FileModificationService;
import com.intellij.codeInsight.hint.HintManager;
import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction;
import com.intellij.codeInsight.intention.impl.TypeExpression;
import com.intellij.codeInsight.template.*;
import com.intellij.codeInsight.template.impl.TemplateState;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.search.LocalSearchScope;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.refactoring.typeMigration.TypeMigrationProcessor;
import com.intellij.refactoring.typeMigration.TypeMigrationRules;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
/**
* @author anna
*/
public class ChangeClassParametersIntention extends PsiElementBaseIntentionAction {
private static final Logger LOG = Logger.getInstance("#" + ChangeClassParametersIntention.class);
@NotNull
@Override
public String getText() {
return getFamilyName();
}
@NotNull
@Override
public String getFamilyName() {
return "Change class type parameter";
}
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element) {
final PsiTypeElement typeElement = PsiTreeUtil.getTopmostParentOfType(element, PsiTypeElement.class);
final PsiElement parent = typeElement != null ? typeElement.getParent() : null;
final PsiReferenceParameterList parameterList = parent instanceof PsiReferenceParameterList ? (PsiReferenceParameterList)parent : null;
if (parameterList != null && parameterList.getTypeArguments().length > 0) {
final PsiMember member = PsiTreeUtil.getParentOfType(parameterList, PsiMember.class);
if (member instanceof PsiAnonymousClass) {
final PsiClassType.ClassResolveResult result = ((PsiAnonymousClass)member).getBaseClassType().resolveGenerics();
return result.getElement() != null && ((PsiAnonymousClass)member).getBaseClassReference().getParameterList() == parameterList;
}
}
return false;
}
@Override
public void invoke(@NotNull final Project project, final Editor editor, @NotNull final PsiElement element) throws IncorrectOperationException {
if (!FileModificationService.getInstance().preparePsiElementsForWrite(element)) return;
final PsiTypeElement typeElement = PsiTreeUtil.getTopmostParentOfType(element, PsiTypeElement.class);
final PsiReferenceParameterList parameterList = PsiTreeUtil.getParentOfType(element, PsiReferenceParameterList.class);
if (parameterList != null && typeElement != null) {
final PsiClass aClass = PsiTreeUtil.getParentOfType(element, PsiClass.class);
if (aClass instanceof PsiAnonymousClass) {
editor.getCaretModel().moveToOffset(aClass.getTextOffset());
final PsiTypeElement[] typeElements = parameterList.getTypeParameterElements();
final int changeIdx = ArrayUtil.find(typeElements, typeElement);
final PsiClassType.ClassResolveResult result = ((PsiAnonymousClass)aClass).getBaseClassType().resolveGenerics();
final PsiClass baseClass = result.getElement();
LOG.assertTrue(baseClass != null);
final PsiTypeParameter typeParameter = baseClass.getTypeParameters()[changeIdx];
final TemplateBuilderImpl templateBuilder = (TemplateBuilderImpl)TemplateBuilderFactory.getInstance().createTemplateBuilder(aClass);
final String oldTypeText = typeElement.getText();
final String varName = "param";
templateBuilder.replaceElement(typeElement, varName, new TypeExpression(project, new PsiType[]{typeElement.getType()}), true);
final Template template = templateBuilder.buildInlineTemplate();
TemplateManager.getInstance(project).startTemplate(editor, template, false, null, new TemplateEditingAdapter() {
private String myNewType;
@Override
public void beforeTemplateFinished(TemplateState state, Template template) {
final TextResult value = state.getVariableValue(varName);
myNewType = value != null ? value.getText() : "";
final int segmentsCount = state.getSegmentsCount();
final Document document = state.getEditor().getDocument();
for (int i = 0; i < segmentsCount; i++) {
final TextRange segmentRange = state.getSegmentRange(i);
document.replaceString(segmentRange.getStartOffset(), segmentRange.getEndOffset(), oldTypeText);
}
}
@Override
public void templateFinished(Template template, boolean brokenOff) {
if (!brokenOff) {
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project);
try {
final PsiType targetParam = elementFactory.createTypeFromText(myNewType, aClass);
final TypeMigrationRules myRules = new TypeMigrationRules(((PsiAnonymousClass)aClass).getBaseClassType());
final PsiSubstitutor substitutor = result.getSubstitutor().put(typeParameter, targetParam);
final PsiType targetClassType = elementFactory.createType(baseClass, substitutor);
myRules.setMigrationRootType(targetClassType);
myRules.setBoundScope(new LocalSearchScope(aClass));
new TypeMigrationProcessor(project, ((PsiAnonymousClass)aClass).getBaseClassReference().getParameterList(), myRules).run();
}
catch (IncorrectOperationException e) {
HintManager.getInstance().showErrorHint(editor, "Incorrect type");
}
}
}
});
}
}
}
@Override
public boolean startInWriteAction() {
return true;
}
}
@@ -0,0 +1,218 @@
package com.intellij.refactoring.typeMigration.intentions;
import com.intellij.codeInsight.FileModificationService;
import com.intellij.codeInsight.intention.LowPriorityAction;
import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction;
import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.impl.AllowedApiFilterExtension;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.refactoring.typeMigration.TypeConversionDescriptor;
import com.intellij.refactoring.typeMigration.TypeMigrationReplacementUtil;
import com.intellij.refactoring.typeMigration.rules.AtomicConversionRule;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.Query;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.*;
import static com.intellij.psi.util.TypeConversionUtil.isBinaryOperatorApplicable;
import static com.intellij.util.ObjectUtils.assertNotNull;
/**
* @author anna
* @since 26-Aug-2009
*/
public class ConvertFieldToAtomicIntention extends PsiElementBaseIntentionAction implements LowPriorityAction {
private static final Logger LOG = Logger.getInstance("#" + ConvertFieldToAtomicIntention.class.getName());
private final Map<PsiType, String> myFromToMap = ContainerUtil.newHashMap();
{
myFromToMap.put(PsiType.INT, AtomicInteger.class.getName());
myFromToMap.put(PsiType.LONG, AtomicLong.class.getName());
myFromToMap.put(PsiType.BOOLEAN, AtomicBoolean.class.getName());
myFromToMap.put(PsiType.INT.createArrayType(), AtomicIntegerArray.class.getName());
myFromToMap.put(PsiType.LONG.createArrayType(), AtomicLongArray.class.getName());
}
@NotNull
@Override
public String getText() {
return "Convert to atomic";
}
@NotNull
@Override
public String getFamilyName() {
return getText();
}
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element) {
PsiVariable psiVariable = getVariable(element);
if (psiVariable == null || psiVariable instanceof PsiResourceVariable) return false;
if (psiVariable.getLanguage() != JavaLanguage.INSTANCE) return false;
if (psiVariable.getTypeElement() == null) return false;
if (!PsiUtil.isLanguageLevel5OrHigher(psiVariable)) return false;
final PsiType psiType = psiVariable.getType();
final PsiClass psiTypeClass = PsiUtil.resolveClassInType(psiType);
if (psiTypeClass != null) {
final String qualifiedName = psiTypeClass.getQualifiedName();
if (qualifiedName != null) { //is already atomic
if (myFromToMap.values().contains(qualifiedName) ||
qualifiedName.equals(AtomicReference.class.getName()) ||
qualifiedName.equals(AtomicReferenceArray.class.getName())) {
return false;
}
}
}
else if (!myFromToMap.containsKey(psiType)) {
return false;
}
return AllowedApiFilterExtension.isClassAllowed(AtomicReference.class.getName(), element);
}
private static PsiVariable getVariable(PsiElement element) {
if (element instanceof PsiIdentifier) {
final PsiElement parent = element.getParent();
if (parent instanceof PsiLocalVariable || parent instanceof PsiField) {
return (PsiVariable)parent;
}
}
return null;
}
@Override
public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException {
final PsiVariable psiVariable = getVariable(element);
LOG.assertTrue(psiVariable != null);
final Query<PsiReference> refs = ReferencesSearch.search(psiVariable);
final Set<PsiElement> elements = new HashSet<PsiElement>();
elements.add(element);
for (PsiReference reference : refs) {
elements.add(reference.getElement());
}
if (!FileModificationService.getInstance().preparePsiElementsForWrite(elements)) return;
final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project);
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
final PsiType fromType = psiVariable.getType();
PsiClassType toType;
final String atomicQualifiedName = myFromToMap.get(fromType);
if (atomicQualifiedName != null) {
final PsiClass atomicClass = psiFacade.findClass(atomicQualifiedName, GlobalSearchScope.allScope(project));
if (atomicClass == null) {//show warning
return;
}
toType = factory.createType(atomicClass);
}
else if (fromType instanceof PsiArrayType) {
final PsiClass atomicReferenceArrayClass =
psiFacade.findClass(AtomicReferenceArray.class.getName(), GlobalSearchScope.allScope(project));
if (atomicReferenceArrayClass == null) {//show warning
return;
}
final Map<PsiTypeParameter, PsiType> substitutor = ContainerUtil.newHashMap();
final PsiTypeParameter[] typeParameters = atomicReferenceArrayClass.getTypeParameters();
if (typeParameters.length == 1) {
PsiType componentType = ((PsiArrayType)fromType).getComponentType();
if (componentType instanceof PsiPrimitiveType) componentType = ((PsiPrimitiveType)componentType).getBoxedType(element);
substitutor.put(typeParameters[0], componentType);
}
toType = factory.createType(atomicReferenceArrayClass, factory.createSubstitutor(substitutor));
}
else {
final PsiClass atomicReferenceClass = psiFacade.findClass(AtomicReference.class.getName(), GlobalSearchScope.allScope(project));
if (atomicReferenceClass == null) {//show warning
return;
}
final Map<PsiTypeParameter, PsiType> substitutor = ContainerUtil.newHashMap();
final PsiTypeParameter[] typeParameters = atomicReferenceClass.getTypeParameters();
if (typeParameters.length == 1) {
PsiType type = fromType;
if (type instanceof PsiPrimitiveType) type = ((PsiPrimitiveType)fromType).getBoxedType(element);
substitutor.put(typeParameters[0], type);
}
toType = factory.createType(atomicReferenceClass, factory.createSubstitutor(substitutor));
}
try {
for (PsiReference reference : refs) {
PsiElement psiElement = reference.getElement();
if (psiElement instanceof PsiExpression) {
final PsiElement parent = psiElement.getParent();
if (parent instanceof PsiExpression && !(parent instanceof PsiReferenceExpression || parent instanceof PsiPolyadicExpression)) {
psiElement = parent;
}
if (psiElement instanceof PsiBinaryExpression) {
PsiBinaryExpression binary = (PsiBinaryExpression)psiElement;
if (isBinaryOperatorApplicable(binary.getOperationTokenType(), binary.getLOperand(), binary.getROperand(), true)) {
continue;
}
}
else if (psiElement instanceof PsiAssignmentExpression) {
final PsiAssignmentExpression assignment = (PsiAssignmentExpression)psiElement;
final IElementType opSign = TypeConversionUtil.convertEQtoOperation(assignment.getOperationTokenType());
if (opSign != null && isBinaryOperatorApplicable(opSign, assignment.getLExpression(), assignment.getRExpression(), true)) {
continue;
}
}
final TypeConversionDescriptor directConversion = AtomicConversionRule.findDirectConversion(psiElement, toType, fromType);
if (directConversion != null) {
TypeMigrationReplacementUtil.replaceExpression((PsiExpression)psiElement, project, directConversion);
}
}
}
final PsiExpression initializer = psiVariable.getInitializer();
if (initializer != null) {
final TypeConversionDescriptor directConversion = AtomicConversionRule.wrapWithNewExpression(toType, fromType, null, element);
if (directConversion != null) {
TypeMigrationReplacementUtil.replaceExpression(initializer, project, directConversion);
}
}
else if (!assertNotNull(psiVariable.getModifierList()).hasModifierProperty(PsiModifier.FINAL)) {
final PsiExpression newInitializer = factory.createExpressionFromText("new " + toType.getCanonicalText() + "()", psiVariable);
if (psiVariable instanceof PsiLocalVariable) {
((PsiLocalVariable)psiVariable).setInitializer(newInitializer);
}
else if (psiVariable instanceof PsiField) {
((PsiField)psiVariable).setInitializer(newInitializer);
}
JavaCodeStyleManager.getInstance(project).shortenClassReferences(psiVariable.getInitializer());
}
PsiElement replaced = assertNotNull(psiVariable.getTypeElement()).replace(factory.createTypeElement(toType));
JavaCodeStyleManager.getInstance(project).shortenClassReferences(replaced);
if (psiVariable instanceof PsiField || CodeStyleSettingsManager.getSettings(project).GENERATE_FINAL_LOCALS) {
final PsiModifierList modifierList = assertNotNull(psiVariable.getModifierList());
modifierList.setModifierProperty(PsiModifier.FINAL, true);
modifierList.setModifierProperty(PsiModifier.VOLATILE, false);
}
}
catch (IncorrectOperationException e) {
LOG.error(e);
}
}
@Override
public boolean startInWriteAction() {
return true;
}
}
@@ -0,0 +1,145 @@
/*
* User: anna
* Date: 26-Aug-2009
*/
package com.intellij.refactoring.typeMigration.intentions;
import com.intellij.codeInsight.FileModificationService;
import com.intellij.codeInsight.intention.LowPriorityAction;
import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction;
import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.impl.AllowedApiFilterExtension;
import com.intellij.psi.impl.PsiDiamondTypeUtil;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.refactoring.typeMigration.TypeConversionDescriptor;
import com.intellij.refactoring.typeMigration.TypeMigrationLabeler;
import com.intellij.refactoring.typeMigration.TypeMigrationReplacementUtil;
import com.intellij.refactoring.typeMigration.TypeMigrationRules;
import com.intellij.refactoring.typeMigration.rules.ThreadLocalConversionRule;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.Query;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import static com.intellij.util.ObjectUtils.assertNotNull;
public class ConvertFieldToThreadLocalIntention extends PsiElementBaseIntentionAction implements LowPriorityAction {
private static final Logger LOG = Logger.getInstance("#" + ConvertFieldToThreadLocalIntention.class.getName());
@NotNull
@Override
public String getText() {
return "Convert to ThreadLocal";
}
@NotNull
@Override
public String getFamilyName() {
return getText();
}
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element) {
if (!(element instanceof PsiIdentifier)) return false;
final PsiField psiField = PsiTreeUtil.getParentOfType(element, PsiField.class);
if (psiField == null) return false;
if (psiField.getLanguage() != JavaLanguage.INSTANCE) return false;
if (psiField.getTypeElement() == null) return false;
final PsiType fieldType = psiField.getType();
final PsiClass fieldTypeClass = PsiUtil.resolveClassInType(fieldType);
if (fieldType instanceof PsiPrimitiveType || fieldType instanceof PsiArrayType) return true;
return fieldTypeClass != null && !Comparing.strEqual(fieldTypeClass.getQualifiedName(), ThreadLocal.class.getName())
&& AllowedApiFilterExtension.isClassAllowed(ThreadLocal.class.getName(), element);
}
@Override
public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException {
final PsiField psiField = PsiTreeUtil.getParentOfType(element, PsiField.class);
LOG.assertTrue(psiField != null);
final Query<PsiReference> refs = ReferencesSearch.search(psiField);
final Set<PsiElement> elements = new HashSet<PsiElement>();
elements.add(element);
for (PsiReference reference : refs) {
elements.add(reference.getElement());
}
if (!FileModificationService.getInstance().preparePsiElementsForWrite(elements)) return;
final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project);
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
final PsiType fromType = psiField.getType();
final PsiClass threadLocalClass = psiFacade.findClass(ThreadLocal.class.getName(), GlobalSearchScope.allScope(project));
if (threadLocalClass == null) {//show warning
return;
}
final Map<PsiTypeParameter, PsiType> substitutor = ContainerUtil.newHashMap();
final PsiTypeParameter[] typeParameters = threadLocalClass.getTypeParameters();
if (typeParameters.length == 1) {
PsiType type = fromType;
if (fromType instanceof PsiPrimitiveType) type = ((PsiPrimitiveType)fromType).getBoxedType(element);
substitutor.put(typeParameters[0], type);
}
final PsiClassType toType = factory.createType(threadLocalClass, factory.createSubstitutor(substitutor));
try {
final TypeMigrationRules rules = new TypeMigrationRules(fromType);
rules.setMigrationRootType(toType);
rules.setBoundScope(GlobalSearchScope.fileScope(element.getContainingFile()));
final TypeMigrationLabeler labeler = new TypeMigrationLabeler(rules);
labeler.getMigratedUsages(false, psiField);
for (PsiReference reference : refs) {
PsiElement psiElement = reference.getElement();
if (psiElement instanceof PsiExpression) {
final PsiElement parent = psiElement.getParent();
if (parent instanceof PsiExpression && !(parent instanceof PsiReferenceExpression || parent instanceof PsiPolyadicExpression)) {
psiElement = parent;
}
final TypeConversionDescriptor conversion = ThreadLocalConversionRule.findDirectConversion(psiElement, toType, fromType, labeler);
if (conversion != null) {
TypeMigrationReplacementUtil.replaceExpression((PsiExpression)psiElement, project, conversion);
}
}
}
final PsiExpression initializer = psiField.getInitializer();
if (initializer != null) {
final TypeConversionDescriptor conversion = ThreadLocalConversionRule.wrapWithNewExpression(toType, fromType, initializer);
TypeMigrationReplacementUtil.replaceExpression(initializer, project, conversion);
CodeStyleManager.getInstance(project).reformat(psiField);
}
else if (!assertNotNull(psiField.getModifierList()).hasModifierProperty(PsiModifier.FINAL)) {
final String text = "new " + PsiDiamondTypeUtil.getCollapsedType(toType, psiField) + "()";
final PsiExpression newInitializer = factory.createExpressionFromText(text, psiField);
psiField.setInitializer(newInitializer);
}
assertNotNull(psiField.getTypeElement()).replace(factory.createTypeElement(toType));
final PsiModifierList modifierList = assertNotNull(psiField.getModifierList());
modifierList.setModifierProperty(PsiModifier.FINAL, true);
modifierList.setModifierProperty(PsiModifier.VOLATILE, false);
}
catch (IncorrectOperationException e) {
LOG.error(e);
}
}
@Override
public boolean startInWriteAction() {
return true;
}
}
@@ -0,0 +1,420 @@
/*
* User: anna
* Date: 18-Aug-2009
*/
package com.intellij.refactoring.typeMigration.rules;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Comparing;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiDiamondTypeUtil;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.refactoring.typeMigration.TypeConversionDescriptor;
import com.intellij.refactoring.typeMigration.TypeConversionDescriptorBase;
import com.intellij.refactoring.typeMigration.TypeMigrationLabeler;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.concurrent.atomic.*;
public class AtomicConversionRule extends TypeConversionRule {
private static final Logger LOG = Logger.getInstance("#" + AtomicConversionRule.class.getName());
@Override
public TypeConversionDescriptorBase findConversion(PsiType from,
PsiType to,
PsiMember member,
PsiExpression context,
TypeMigrationLabeler labeler) {
if (to instanceof PsiClassType && isAtomicTypeMigration(from, (PsiClassType)to, context)) {
return findDirectConversion(context, to, from);
}
else if (from instanceof PsiClassType && isAtomicTypeMigration(to, (PsiClassType)from, context)) {
return findReverseConversion(context);
}
return null;
}
private static boolean isAtomicTypeMigration(PsiType from, PsiClassType to, PsiExpression context) {
if (from == PsiType.INT && to.getCanonicalText().equals(AtomicInteger.class.getName())) {
return true;
}
if (from.equals(PsiType.INT.createArrayType()) && to.getCanonicalText().equals(AtomicIntegerArray.class.getName())) {
return true;
}
if (from == PsiType.LONG && to.getCanonicalText().equals(AtomicLong.class.getName())) {
return true;
}
if (from.equals(PsiType.LONG.createArrayType()) && to.getCanonicalText().equals(AtomicLongArray.class.getName())) {
return true;
}
if (from == PsiType.BOOLEAN && to.getCanonicalText().equals(AtomicBoolean.class.getName())) {
return true;
}
final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(to);
final PsiClass atomicClass = resolveResult.getElement();
if (atomicClass != null) {
final String typeQualifiedName = atomicClass.getQualifiedName();
if (!Comparing.strEqual(typeQualifiedName, AtomicReference.class.getName()) &&
!Comparing.strEqual(typeQualifiedName, AtomicReferenceArray.class.getName())) {
return false;
}
final PsiTypeParameter[] typeParameters = atomicClass.getTypeParameters();
if (typeParameters.length != 1) return false;
final PsiType toTypeParameterValue = resolveResult.getSubstitutor().substitute(typeParameters[0]);
if (toTypeParameterValue != null) {
if (from.getDeepComponentType() instanceof PsiPrimitiveType) {
final PsiPrimitiveType unboxedInitialType = PsiPrimitiveType.getUnboxedType(toTypeParameterValue);
if (unboxedInitialType != null) {
return TypeConversionUtil.areTypesConvertible(from.getDeepComponentType(), unboxedInitialType);
}
}
else {
return TypeConversionUtil.isAssignable(from.getDeepComponentType(), PsiUtil.captureToplevelWildcards(toTypeParameterValue, context));
}
}
}
return false;
}
@Nullable
public static TypeConversionDescriptor findDirectConversion(PsiElement context, PsiType to, PsiType from) {
final PsiClass toTypeClass = PsiUtil.resolveClassInType(to);
LOG.assertTrue(toTypeClass != null);
final String qualifiedName = toTypeClass.getQualifiedName();
if (qualifiedName != null) {
if (qualifiedName.equals(AtomicInteger.class.getName()) || qualifiedName.equals(AtomicLong.class.getName())) {
if (context instanceof PsiPostfixExpression) {
final IElementType operationSign = ((PsiPostfixExpression)context).getOperationTokenType();
if (operationSign == JavaTokenType.MINUSMINUS) {
return new TypeConversionDescriptor("$qualifier$--", "$qualifier$.getAndDecrement()");
}
if (operationSign == JavaTokenType.PLUSPLUS) {
return new TypeConversionDescriptor("$qualifier$++", "$qualifier$.getAndIncrement()");
}
}
else if (context instanceof PsiPrefixExpression) {
final IElementType operationSign = ((PsiPrefixExpression)context).getOperationTokenType();
if (operationSign == JavaTokenType.MINUSMINUS) {
return new TypeConversionDescriptor("--$qualifier$", "$qualifier$.decrementAndGet()");
}
if (operationSign == JavaTokenType.PLUSPLUS) {
return new TypeConversionDescriptor("++$qualifier$", "$qualifier$.incrementAndGet()");
}
}
else if (context instanceof PsiAssignmentExpression) {
final PsiJavaToken signToken = ((PsiAssignmentExpression)context).getOperationSign();
final IElementType operationSign = signToken.getTokenType();
final String sign = signToken.getText();
if (operationSign == JavaTokenType.PLUSEQ || operationSign == JavaTokenType.MINUSEQ) {
return new TypeConversionDescriptor("$qualifier$ " + sign + " $val$", "$qualifier$.getAndAdd(" +
(operationSign == JavaTokenType.MINUSEQ ? "-" : "") +
"($val$))");
}
}
}
else if (qualifiedName.equals(AtomicIntegerArray.class.getName()) || qualifiedName.equals(AtomicLongArray.class.getName())) {
PsiElement parentExpression = context.getParent();
if (parentExpression instanceof PsiPostfixExpression) {
final IElementType operationSign = ((PsiPostfixExpression)parentExpression).getOperationTokenType();
if (operationSign == JavaTokenType.MINUSMINUS) {
return new TypeConversionDescriptor("$qualifier$[$idx$]--", "$qualifier$.getAndDecrement($idx$)",
(PsiExpression)parentExpression);
}
if (operationSign == JavaTokenType.PLUSPLUS) {
return new TypeConversionDescriptor("$qualifier$[$idx$]++", "$qualifier$.getAndIncrement($idx$)",
(PsiExpression)parentExpression);
}
}
else if (parentExpression instanceof PsiPrefixExpression) {
final IElementType operationSign = ((PsiPrefixExpression)parentExpression).getOperationTokenType();
if (operationSign == JavaTokenType.MINUSMINUS) {
return new TypeConversionDescriptor("--$qualifier$[$idx$]", "$qualifier$.decrementAndGet($idx$)",
(PsiExpression)parentExpression);
}
if (operationSign == JavaTokenType.PLUSPLUS) {
return new TypeConversionDescriptor("++$qualifier$[$idx$]", "$qualifier$.incrementAndGet($idx$)",
(PsiExpression)parentExpression);
}
}
else if (parentExpression instanceof PsiAssignmentExpression) {
final PsiJavaToken signToken = ((PsiAssignmentExpression)parentExpression).getOperationSign();
final IElementType operationSign = signToken.getTokenType();
final String sign = signToken.getText();
if (operationSign == JavaTokenType.PLUSEQ || operationSign == JavaTokenType.MINUSEQ) {
return new TypeConversionDescriptor("$qualifier$[$idx$] " + sign + " $val$", "$qualifier$.getAndAdd($idx$, " +
(operationSign == JavaTokenType.MINUSEQ
? "-"
: "") +
"($val$))", (PsiExpression)parentExpression);
}
}
}
}
return from instanceof PsiArrayType
? findDirectConversionForAtomicReferenceArray(context, to, from)
: findDirectConversionForAtomicReference(context, to, from);
}
@Nullable
private static TypeConversionDescriptor findDirectConversionForAtomicReference(PsiElement context, PsiType to, PsiType from) {
final PsiElement parent = context.getParent();
if (parent instanceof PsiAssignmentExpression) {
final IElementType operationSign = ((PsiAssignmentExpression)parent).getOperationTokenType();
if (operationSign == JavaTokenType.EQ) {
return new TypeConversionDescriptor("$qualifier$ = $val$", "$qualifier$.set($val$)", (PsiAssignmentExpression)parent);
}
}
if (context instanceof PsiReferenceExpression) {
final PsiExpression qualifierExpression = ((PsiReferenceExpression)context).getQualifierExpression();
final PsiExpression expression = context.getParent() instanceof PsiMethodCallExpression && qualifierExpression != null
? qualifierExpression
: (PsiExpression)context;
return new TypeConversionDescriptor("$qualifier$", "$qualifier$.get()", expression);
}
else if (context instanceof PsiAssignmentExpression) {
final PsiJavaToken signToken = ((PsiAssignmentExpression)context).getOperationSign();
final IElementType operationSign = signToken.getTokenType();
final String sign = signToken.getText();
if (parent instanceof PsiExpressionStatement) {
if (operationSign == JavaTokenType.EQ) {
final PsiExpression lExpression = ((PsiAssignmentExpression)context).getLExpression();
if (lExpression instanceof PsiReferenceExpression) {
final PsiElement element = ((PsiReferenceExpression)lExpression).resolve();
if (element instanceof PsiVariable && ((PsiVariable)element).hasModifierProperty(PsiModifier.FINAL)) {
return wrapWithNewExpression(to, from, ((PsiAssignmentExpression)context).getRExpression(), element);
}
}
return new TypeConversionDescriptor("$qualifier$ = $val$", "$qualifier$.set($val$)");
}
else {
return new TypeConversionDescriptor("$qualifier$" + sign + "$val$", "$qualifier$.set(" +
getBoxedWrapper(from, to, "$qualifier$.get() " +
sign.charAt(0) +
" $val$") +
")");
}
} //else should be a conflict
}
else if (context instanceof PsiPostfixExpression) {
final String sign = ((PsiPostfixExpression)context).getOperationSign().getText();
return new TypeConversionDescriptor("$qualifier$" + sign, "$qualifier$.getAndSet(" +
getBoxedWrapper(from, to, "$qualifier$.get() " + sign.charAt(0) + " 1") +
")");
}
else if (context instanceof PsiPrefixExpression) {
final PsiJavaToken operationSign = ((PsiPrefixExpression)context).getOperationSign();
if (operationSign.getTokenType() == JavaTokenType.EXCL) {
return new TypeConversionDescriptor("!$qualifier$", "!$qualifier$.get()");
}
final String sign = operationSign.getText();
return new TypeConversionDescriptor(sign + "$qualifier$", "$qualifier$.set(" + //todo reject?
getBoxedWrapper(from, to, "$qualifier$.get() " + sign.charAt(0) + " 1") +
")");
} else if (context instanceof PsiBinaryExpression) {
final String sign = ((PsiBinaryExpression)context).getOperationSign().getText();
return new TypeConversionDescriptor("$qualifier$" + sign + "$val$", "$qualifier$.get() " + sign + " $val$");
}
if (parent instanceof PsiVariable) {
return wrapWithNewExpression(to, from, null, parent);
}
return null;
}
public static TypeConversionDescriptor wrapWithNewExpression(PsiType to, PsiType from, @Nullable PsiExpression expression, PsiElement context) {
final String typeText = PsiDiamondTypeUtil.getCollapsedType(to, context);
final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(to);
final PsiClass atomicClass = resolveResult.getElement();
LOG.assertTrue(atomicClass != null);
final PsiTypeParameter[] typeParameters = atomicClass.getTypeParameters();
if (typeParameters.length == 1) {
final PsiType initial = resolveResult.getSubstitutor().substitute(typeParameters[0]);
final PsiPrimitiveType unboxedInitialType = PsiPrimitiveType.getUnboxedType(initial);
if (unboxedInitialType != null) {
LOG.assertTrue(initial != null);
if (from instanceof PsiPrimitiveType) {
final PsiClassType boxedFromType = ((PsiPrimitiveType)from).getBoxedType(atomicClass);
LOG.assertTrue(boxedFromType != null);
if (!TypeConversionUtil.isAssignable(initial, boxedFromType)) {
return new TypeConversionDescriptor("$val$", "new " + typeText + "((" + unboxedInitialType.getCanonicalText() + ")$val$)", expression);
}
}
}
}
return new TypeConversionDescriptor("$val$", "new " + typeText + "($val$)", expression);
}
@Nullable
private static TypeConversionDescriptor findDirectConversionForAtomicReferenceArray(PsiElement context, PsiType to, PsiType from) {
LOG.assertTrue(from instanceof PsiArrayType);
from = ((PsiArrayType)from).getComponentType();
final PsiElement parent = context.getParent();
final PsiElement parentParent = parent.getParent();
if (parent instanceof PsiAssignmentExpression) {
final PsiAssignmentExpression assignmentExpression = (PsiAssignmentExpression)parent;
final IElementType operationSign = assignmentExpression.getOperationTokenType();
final String sign = assignmentExpression.getOperationSign().getText();
if (context instanceof PsiArrayAccessExpression) {
if (parentParent instanceof PsiExpressionStatement) {
if (assignmentExpression.getLExpression() == context) {
if (operationSign == JavaTokenType.EQ) {
return new TypeConversionDescriptor("$qualifier$[$idx$] = $val$", "$qualifier$.set($idx$, $val$)", assignmentExpression);
}
else {
return new TypeConversionDescriptor("$qualifier$[$idx$]" + sign + "$val$",
"$qualifier$.set($idx$, " + getBoxedWrapper(from, to, "$qualifier$.get($idx$) " + sign.charAt(0) + " $val$") + ")",
assignmentExpression);
}
}
} //else should be a conflict
}
else {
final PsiExpression rExpression = assignmentExpression.getRExpression();
if (rExpression == context && operationSign == JavaTokenType.EQ) { //array = new T[l];
return wrapWithNewExpression(to, from, rExpression, context);
}
}
} else if (parent instanceof PsiVariable) {
if (((PsiVariable)parent).getInitializer() == context) {
return wrapWithNewExpression(to, from, (PsiExpression)context, context);
}
}
if (parentParent instanceof PsiExpressionStatement) {
if (parent instanceof PsiPostfixExpression) {
final String sign = ((PsiPostfixExpression)parent).getOperationSign().getText();
return new TypeConversionDescriptor("$qualifier$[$idx$]" + sign, "$qualifier$.getAndSet($idx$, " +
getBoxedWrapper(from, to,
"$qualifier$.get($idx$) " + sign.charAt(0) + " 1") +
")", (PsiExpression)parent);
}
else if (parent instanceof PsiPrefixExpression) {
final String sign = ((PsiPrefixExpression)parent).getOperationSign().getText();
return new TypeConversionDescriptor(sign + "$qualifier$[$idx$]", "$qualifier$.set($idx$, " +
getBoxedWrapper(from, to,
"$qualifier$.get($idx$) " + sign.charAt(0) + " 1") +
")", (PsiExpression)parent);
}
else if (parent instanceof PsiBinaryExpression) {
final String sign = ((PsiBinaryExpression)parent).getOperationSign().getText();
return new TypeConversionDescriptor("$qualifier$[$idx$]" + sign + "$val$", "$qualifier$.set($idx$, " +
getBoxedWrapper(from, to, "$qualifier$.get($idx$) " +
sign +
" $val$)") +
")", (PsiExpression)parent);
}
}
if (context instanceof PsiArrayAccessExpression) {
return new TypeConversionDescriptor("$qualifier$[$idx$]", "$qualifier$.get($idx$)", (PsiExpression)context);
}
return null;
}
private static String getBoxedWrapper(final PsiType from, final PsiType to, @NotNull String arg) {
final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(to);
final PsiClass atomicClass = resolveResult.getElement();
LOG.assertTrue(atomicClass != null);
final PsiTypeParameter[] typeParameters = atomicClass.getTypeParameters();
if (typeParameters.length == 1) {
final PsiSubstitutor substitutor = resolveResult.getSubstitutor();
LOG.assertTrue(substitutor.isValid());
final PsiType initial = substitutor.substitute(typeParameters[0]);
final PsiPrimitiveType unboxedInitialType = PsiPrimitiveType.getUnboxedType(initial);
if (unboxedInitialType != null) {
LOG.assertTrue(initial != null);
if (from instanceof PsiPrimitiveType) {
final PsiClassType boxedFromType = ((PsiPrimitiveType)from).getBoxedType(atomicClass);
LOG.assertTrue(boxedFromType != null);
return "new " + initial.getPresentableText() + "((" + unboxedInitialType.getCanonicalText() + ")(" + arg + "))";
}
}
}
return arg;
}
@Nullable
private static TypeConversionDescriptor findReverseConversion(PsiElement context) {
if (context instanceof PsiReferenceExpression) {
if (context.getParent() instanceof PsiMethodCallExpression) {
return findReverseConversionForMethodCall(context);
}
}
else if (context instanceof PsiNewExpression) {
return new TypeConversionDescriptor("new $type$($qualifier$)", "$qualifier$");
}
else if (context instanceof PsiMethodCallExpression) {
return findReverseConversionForMethodCall(((PsiMethodCallExpression)context).getMethodExpression());
}
return null;
}
@Nullable
private static TypeConversionDescriptor findReverseConversionForMethodCall(PsiElement context) {
final PsiElement resolved = ((PsiReferenceExpression)context).resolve();
if (resolved instanceof PsiMethod) {
final PsiMethod method = (PsiMethod)resolved;
final int parametersCount = method.getParameterList().getParametersCount();
final String resolvedName = method.getName();
if (Comparing.strEqual(resolvedName, "get")) {
return parametersCount == 0 ?
new TypeConversionDescriptor("$qualifier$.get()", "$qualifier$") :
new TypeConversionDescriptor("$qualifier$.get($idx$)", "$qualifier$[$idx$]");
}
else if (Comparing.strEqual(resolvedName, "set")) {
return parametersCount == 1 ?
new TypeConversionDescriptor("$qualifier$.set($val$)", "$qualifier$ = $val$") :
new TypeConversionDescriptor("$qualifier$.set($idx$, $val$)", "$qualifier$[$idx$] = $val$");
}
else if (Comparing.strEqual(resolvedName, "addAndGet")) {
return parametersCount == 1 ?
new TypeConversionDescriptor("$qualifier$.addAndGet($delta$)", "$qualifier$ + $delta$") :
new TypeConversionDescriptor("$qualifier$.addAndGet($idx$, $delta$)", "$qualifier$[$idx$] + $delta$");
}
else if (Comparing.strEqual(resolvedName, "incrementAndGet")) {
return parametersCount == 0 ?
new TypeConversionDescriptor("$qualifier$.incrementAndGet()", "++$qualifier$") :
new TypeConversionDescriptor("$qualifier$.incrementAndGet($idx$)", "++$qualifier$[$idx$]");
}
else if (Comparing.strEqual(resolvedName, "decrementAndGet")) {
return parametersCount == 0 ?
new TypeConversionDescriptor("$qualifier$.decrementAndGet()", "--$qualifier$") :
new TypeConversionDescriptor("$qualifier$.decrementAndGet($idx$)", "--$qualifier$[$idx$]");
}
else if (Comparing.strEqual(resolvedName, "getAndIncrement")) {
return parametersCount == 0 ?
new TypeConversionDescriptor("$qualifier$.getAndIncrement()", "$qualifier$++") :
new TypeConversionDescriptor("$qualifier$.getAndIncrement($idx$)", "$qualifier$[$idx$]++");
}
else if (Comparing.strEqual(resolvedName, "getAndDecrement")) {
return parametersCount == 0 ?
new TypeConversionDescriptor("$qualifier$.getAndDecrement()", "$qualifier$--") :
new TypeConversionDescriptor("$qualifier$.getAndDecrement($idx$)", "$qualifier$[$idx$]--");
}
else if (Comparing.strEqual(resolvedName, "getAndAdd")) {
return parametersCount == 1?
new TypeConversionDescriptor("$qualifier$.getAndAdd($val$)", "$qualifier$ += $val$") :
new TypeConversionDescriptor("$qualifier$.getAndAdd($idx$, $val$)", "$qualifier$[$idx$] += $val$");
}
else if (Comparing.strEqual(resolvedName, "getAndSet")) {
return parametersCount == 1 ?
new TypeConversionDescriptor("$qualifier$.getAndSet($val$)", "$qualifier$ = $val$") :
new TypeConversionDescriptor("$qualifier$.getAndSet($idx$, $val$)", "$qualifier$[$idx$] = $val$");
}
}
return null;
}
}
@@ -0,0 +1,36 @@
/*
* User: anna
* Date: 08-Aug-2008
*/
package com.intellij.refactoring.typeMigration.rules;
import com.intellij.openapi.util.Comparing;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiUtil;
import com.intellij.refactoring.typeMigration.TypeConversionDescriptor;
import com.intellij.refactoring.typeMigration.TypeConversionDescriptorBase;
import com.intellij.refactoring.typeMigration.TypeMigrationLabeler;
public class BoxingTypeConversionRule extends TypeConversionRule {
public TypeConversionDescriptorBase findConversion(final PsiType from, final PsiType to, final PsiMember member, final PsiExpression context,
final TypeMigrationLabeler labeler) {
if (to instanceof PsiClassType && from instanceof PsiPrimitiveType) {
if (!PsiUtil.isLanguageLevel5OrHigher(context)) {
final String boxedTypeName = ((PsiPrimitiveType)from).getBoxedTypeName();
if (Comparing.strEqual(boxedTypeName, to.getCanonicalText())) {
return new TypeConversionDescriptor("$qualifier$", boxedTypeName + ".valueOf($qualifier$)");
}
}
}
else if (from instanceof PsiClassType && to instanceof PsiPrimitiveType) {
if (!PsiUtil.isLanguageLevel5OrHigher(context)) {
final String boxedTypeName = ((PsiPrimitiveType)to).getBoxedTypeName();
if (Comparing.strEqual(boxedTypeName, from.getCanonicalText())) {
return new TypeConversionDescriptor("$qualifier$", "($qualifier$)." + to.getCanonicalText() + "Value()");
}
}
}
return null;
}
}
@@ -0,0 +1,36 @@
/*
* User: anna
* Date: 25-Aug-2008
*/
package com.intellij.refactoring.typeMigration.rules;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.refactoring.typeMigration.TypeConversionDescriptor;
import com.intellij.refactoring.typeMigration.TypeConversionDescriptorBase;
import com.intellij.refactoring.typeMigration.TypeMigrationLabeler;
public class ElementToArrayConversionRule extends TypeConversionRule{
public TypeConversionDescriptorBase findConversion(final PsiType from, final PsiType to, final PsiMember member, final PsiExpression context,
final TypeMigrationLabeler labeler) {
if (member == null && to instanceof PsiArrayType && TypeConversionUtil.isAssignable(((PsiArrayType)to).getComponentType(), from)) {
TypeConversionDescriptor wrapDescription =
new TypeConversionDescriptor("$qualifier$", "new " + from.getCanonicalText() + "[]{$qualifier$}", context);
if (((PsiArrayType)to).getComponentType() instanceof PsiClassType && from instanceof PsiPrimitiveType) {
final String boxedTypeName = ((PsiPrimitiveType)from).getBoxedTypeName();
final String normalizedArrayInitializer =
PsiUtil.isLanguageLevel5OrHigher(context) ? "$qualifier$" : boxedTypeName + ".valueOf($qualifier$)";
wrapDescription = new TypeConversionDescriptor("$qualifier$", "new " + boxedTypeName + "[]{" + normalizedArrayInitializer + "}", context);
}
final PsiElement parent = context.getParent();
if ((context instanceof PsiLiteralExpression || context instanceof PsiReferenceExpression) && parent instanceof PsiStatement) {
return wrapDescription;
}
if (parent instanceof PsiAssignmentExpression && ((PsiAssignmentExpression)parent).getRExpression() == context) {
return wrapDescription;
}
}
return null;
}
}
@@ -0,0 +1,177 @@
/*
* User: anna
* Date: 08-Aug-2008
*/
package com.intellij.refactoring.typeMigration.rules;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiImplUtil;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.refactoring.typeMigration.TypeConversionDescriptor;
import com.intellij.refactoring.typeMigration.TypeConversionDescriptorBase;
import com.intellij.refactoring.typeMigration.TypeMigrationLabeler;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
public class ListArrayConversionRule extends TypeConversionRule {
public TypeConversionDescriptorBase findConversion(final PsiType from,
final PsiType to,
PsiMember member,
final PsiExpression context,
final TypeMigrationLabeler labeler) {
PsiExpression expression = context;
PsiClassType classType = from instanceof PsiClassType ? (PsiClassType)from : to instanceof PsiClassType ? (PsiClassType)to : null;
PsiArrayType arrayType = from instanceof PsiArrayType ? (PsiArrayType)from : to instanceof PsiArrayType ? (PsiArrayType)to : null;
if (classType == null || arrayType == null) return null;
final PsiType collectionType = evaluateCollectionsType(classType, expression);
if (collectionType == null) return null;
if (member == null) {
final PsiMethodCallExpression callExpression = PsiTreeUtil.getParentOfType(context, PsiMethodCallExpression.class);
if (callExpression != null) {
member = callExpression.resolveMethod();
expression = callExpression;
}
}
if (member instanceof PsiMethod) {
TypeConversionDescriptor descriptor = changeCollectionCallsToArray((PsiMethod)member, context, collectionType, arrayType);
if (descriptor != null) return descriptor;
@NonNls final String memberName = member.getName();
assert memberName != null;
if (memberName.equals("sort")) {
if (((PsiMethod)member).getParameterList().getParametersCount() == 1) {
descriptor = new TypeConversionDescriptor("Arrays.sort($qualifier$)", "Collections.sort($qualifier$)", expression);
}
else {
descriptor =
new TypeConversionDescriptor("Arrays.sort($qualifier$, $expr$)", "Collections.sort($qualifier$, $expr$)", expression);
}
}
else if (memberName.equals("binarySearch")) {
if (((PsiMethod)member).getParameterList().getParametersCount() == 2) {
descriptor =
new TypeConversionDescriptor("Arrays.binarySearch($qualifier$, $key$)", "Collections.binarySearch($qualifier$, $key$)",
expression);
}
else {
descriptor = new TypeConversionDescriptor("Arrays.binarySearch($qualifier$, $key$, $comparator$)",
"Collections.binarySearch($qualifier$, $key$, $comparator$)", expression);
}
}
else if (memberName.equals("asList")) {
if (((PsiMethod)member).getParameterList().getParametersCount() == 1) {
descriptor =
new TypeConversionDescriptor("Arrays.asList($qualifier$)", "$qualifier$", expression);
}
}
else if (memberName.equals("fill")) {
descriptor = new TypeConversionDescriptor("Arrays.fill($qualifier$, $filler$)", "Collections.fill($qualifier$, $filler$)", expression);
}
if (descriptor != null) {
return from instanceof PsiClassType
? new TypeConversionDescriptor(descriptor.getReplaceByString(), descriptor.getStringToReplace(), descriptor.getExpression())
: descriptor;
}
}
if (member instanceof PsiField && member.getName().equals("length")) {
return new TypeConversionDescriptor("$qualifier$.length", "$qualifier$.size()");
}
final PsiElement parent = context.getParent();
if (parent instanceof PsiAssignmentExpression && ((PsiAssignmentExpression)parent).getLExpression() == context) {
if (TypeConversionUtil.isAssignable(collectionType, arrayType.getComponentType())) {
return new TypeConversionDescriptor("$qualifier$[$idx$] = $expr$", "$qualifier$.set($idx$, $expr$)",
(PsiExpression)parent);
}
}
else if (context instanceof PsiArrayAccessExpression && TypeConversionUtil.isAssignable(arrayType.getComponentType(), collectionType)) {
return new TypeConversionDescriptor("$qualifier$[$idx$]", "$qualifier$.get($idx$)");
}
return null;
}
@Nullable
public static PsiType evaluateCollectionsType(PsiClassType classType, PsiExpression expression) {
final PsiClassType.ClassResolveResult classResolveResult = PsiUtil.resolveGenericsClassInType(classType);
if (classResolveResult != null) {
final PsiClass psiClass = classResolveResult.getElement();
if (psiClass != null) {
final GlobalSearchScope allScope = GlobalSearchScope.allScope(psiClass.getProject());
final PsiClass collectionClass =
JavaPsiFacade.getInstance(psiClass.getProject()).findClass(CommonClassNames.JAVA_UTIL_LIST, allScope);
if (collectionClass != null && InheritanceUtil.isInheritorOrSelf(psiClass, collectionClass, true)) {
final PsiSubstitutor derivedSubstitutor = classResolveResult.getSubstitutor();
if (PsiUtil.isRawSubstitutor(psiClass, derivedSubstitutor)) return null;
final PsiSubstitutor substitutor =
TypeConversionUtil.getClassSubstitutor(collectionClass, psiClass, derivedSubstitutor);
assert substitutor != null;
final PsiType type = substitutor.substitute(collectionClass.getTypeParameters()[0]);
assert type != null;
return PsiImplUtil.normalizeWildcardTypeByPosition(type, expression);
}
}
}
return null;
}
@Override
public Pair<PsiType, PsiType> bindTypeParameters(final PsiType from,
final PsiType to,
final PsiMethod method,
final PsiExpression context,
final TypeMigrationLabeler labeler) {
if (findConversion(from, to, method, context, labeler) == null) return null;
if (from instanceof PsiArrayType && to instanceof PsiClassType) {
final PsiType collectionType = evaluateCollectionsType((PsiClassType)to, context);
if (collectionType != null) {
return Pair.create(((PsiArrayType)from).getComponentType(), collectionType);
}
}
if (to instanceof PsiArrayType && from instanceof PsiClassType) {
final PsiType collectionType = evaluateCollectionsType((PsiClassType)from, context);
if (collectionType != null) {
return Pair.create(collectionType, ((PsiArrayType)to).getComponentType());
}
}
return null;
}
@Nullable
private static TypeConversionDescriptor changeCollectionCallsToArray(final PsiMethod method,
final PsiElement context,
PsiType collectionType,
PsiArrayType arrayType) {
@NonNls final String methodName = method.getName();
if (methodName.equals("toArray")) {
if (method.getParameterList().getParameters().length == 0) {
return new TypeConversionDescriptor("$qualifier$.toArray()", "$qualifier$");
}
return new TypeConversionDescriptor("$qualifier$.toArray($expr$)", "$qualifier$");
}
else if (methodName.equals("size")) {
return new TypeConversionDescriptor("$qualifier$.size()", "$qualifier$.length");
}
else if (methodName.equals("get")) {
if (TypeConversionUtil.isAssignable(collectionType, arrayType.getComponentType())) {
return new TypeConversionDescriptor("$qualifier$.get($i$)", "$qualifier$[$i$]", PsiTreeUtil.getParentOfType(context, PsiMethodCallExpression.class));
}
}
else if (methodName.equals("set")) {
if (TypeConversionUtil.isAssignable(arrayType.getComponentType(), collectionType)) {
return new TypeConversionDescriptor("$qualifier$.set($i$, $val$)", "$qualifier$[$i$] = $val$");
}
}
return null;
}
}
@@ -0,0 +1,231 @@
/*
* User: anna
* Date: 18-Aug-2009
*/
package com.intellij.refactoring.typeMigration.rules;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Comparing;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiDiamondTypeUtil;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.refactoring.typeMigration.TypeConversionDescriptor;
import com.intellij.refactoring.typeMigration.TypeConversionDescriptorBase;
import com.intellij.refactoring.typeMigration.TypeMigrationLabeler;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class ThreadLocalConversionRule extends TypeConversionRule {
private static final Logger LOG = Logger.getInstance("#" + ThreadLocalConversionRule.class.getName());
@Override
public TypeConversionDescriptorBase findConversion(PsiType from,
PsiType to,
PsiMember member,
PsiExpression context,
TypeMigrationLabeler labeler) {
if (to instanceof PsiClassType && isThreadLocalTypeMigration(from, (PsiClassType)to, context)) {
return findDirectConversion(context, to, from, labeler);
}
return null;
}
private static boolean isThreadLocalTypeMigration(PsiType from, PsiClassType to, PsiExpression context) {
final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(to);
final PsiClass threadLocalClass = resolveResult.getElement();
if (threadLocalClass != null) {
final String typeQualifiedName = threadLocalClass.getQualifiedName();
if (!Comparing.strEqual(typeQualifiedName, ThreadLocal.class.getName())) {
return false;
}
final PsiTypeParameter[] typeParameters = threadLocalClass.getTypeParameters();
if (typeParameters.length != 1) return !PsiUtil.isLanguageLevel5OrHigher(context);
final PsiType toTypeParameterValue = resolveResult.getSubstitutor().substitute(typeParameters[0]);
if (toTypeParameterValue != null) {
if (from instanceof PsiPrimitiveType) {
final PsiPrimitiveType unboxedInitialType = PsiPrimitiveType.getUnboxedType(toTypeParameterValue);
if (unboxedInitialType != null) {
return TypeConversionUtil.areTypesConvertible(from, unboxedInitialType);
}
}
else {
return TypeConversionUtil.isAssignable(from, PsiUtil.captureToplevelWildcards(toTypeParameterValue, context));
}
}
return !PsiUtil.isLanguageLevel5OrHigher(context);
}
return false;
}
@Nullable
public static TypeConversionDescriptor findDirectConversion(PsiElement context, PsiType to, PsiType from, TypeMigrationLabeler labeler) {
final PsiClass toTypeClass = PsiUtil.resolveClassInType(to);
LOG.assertTrue(toTypeClass != null);
if (context instanceof PsiArrayAccessExpression) {
return new TypeConversionDescriptor("$qualifier$[$val$]", "$qualifier$.get()[$val$]");
}
final PsiElement parent = context.getParent();
if (parent instanceof PsiAssignmentExpression) {
final IElementType operationSign = ((PsiAssignmentExpression)parent).getOperationTokenType();
if (operationSign == JavaTokenType.EQ) {
return new TypeConversionDescriptor("$qualifier$ = $val$", "$qualifier$.set(" + toBoxed("$val$", from, context)+")", (PsiAssignmentExpression)parent);
}
}
if (context instanceof PsiReferenceExpression) {
final PsiExpression qualifierExpression = ((PsiReferenceExpression)context).getQualifierExpression();
final PsiExpression expression = context.getParent() instanceof PsiMethodCallExpression && qualifierExpression != null
? qualifierExpression
: (PsiExpression)context;
return new TypeConversionDescriptor("$qualifier$", toPrimitive("$qualifier$.get()", from, context), expression);
}
else if (context instanceof PsiBinaryExpression) {
final PsiBinaryExpression binaryExpression = (PsiBinaryExpression)context;
final String sign = binaryExpression.getOperationSign().getText();
return new TypeConversionDescriptor("$qualifier$" + sign + "$val$", toPrimitive("$qualifier$.get()", from, context) + " " + sign + " $val$");
}
if (parent instanceof PsiExpressionStatement) {
if (context instanceof PsiPostfixExpression) {
final PsiPostfixExpression postfixExpression = (PsiPostfixExpression)context;
final String sign = postfixExpression.getOperationSign().getText();
return new TypeConversionDescriptor("$qualifier$" + sign, "$qualifier$.set(" +
getBoxedWrapper(from, to, toPrimitive("$qualifier$.get()", from, context) + " " + sign.charAt(0) + " 1",
labeler, context, postfixExpression.getOperand().getText() +
sign.charAt(0) +
" 1") +
")");
}
else if (context instanceof PsiPrefixExpression) {
final PsiPrefixExpression prefixExpression = (PsiPrefixExpression)context;
final PsiJavaToken operationSign = ((PsiPrefixExpression)context).getOperationSign();
if (operationSign.getTokenType() == JavaTokenType.EXCL) {
return new TypeConversionDescriptor("!$qualifier$", "!$qualifier$.get()");
}
final String sign = operationSign.getText();
final PsiExpression operand = prefixExpression.getOperand();
return new TypeConversionDescriptor(sign + "$qualifier$", "$qualifier$.set(" +
getBoxedWrapper(from, to, toPrimitive("$qualifier$.get()", from, context) + " " + sign.charAt(0) + " 1",
labeler, context, operand != null ? operand.getText() +
sign.charAt(0) +
" 1" : null) +
")");
}
else if (context instanceof PsiAssignmentExpression) {
final PsiAssignmentExpression assignmentExpression = (PsiAssignmentExpression)context;
final PsiJavaToken signToken = assignmentExpression.getOperationSign();
final IElementType operationSign = signToken.getTokenType();
final String sign = signToken.getText();
final PsiExpression lExpression = assignmentExpression.getLExpression();
if (operationSign == JavaTokenType.EQ) {
if (lExpression instanceof PsiReferenceExpression) {
final PsiElement element = ((PsiReferenceExpression)lExpression).resolve();
if (element instanceof PsiVariable && ((PsiVariable)element).hasModifierProperty(PsiModifier.FINAL)) {
return wrapWithNewExpression(to, from, ((PsiAssignmentExpression)context).getRExpression());
}
}
return new TypeConversionDescriptor("$qualifier$ = $val$", "$qualifier$.set(" +
toBoxed("$val$", from, context) +
")");
}
else {
final PsiExpression rExpression = assignmentExpression.getRExpression();
return new TypeConversionDescriptor("$qualifier$" + sign + "$val$", "$qualifier$.set(" +
getBoxedWrapper(from, to, toPrimitive("$qualifier$.get()", from, context) +
" " + sign.charAt(0) +
" $val$", labeler, context,
rExpression != null
? lExpression
.getText() +
sign.charAt(0) +
rExpression.getText()
: null) +
")");
}
}
}
return null;
}
public static TypeConversionDescriptor wrapWithNewExpression(PsiType to, PsiType from, PsiExpression initializer) {
final String boxedTypeName = from instanceof PsiPrimitiveType ? ((PsiPrimitiveType)from).getBoxedTypeName() : from.getCanonicalText();
return new TypeConversionDescriptor("$qualifier$", "new " +
to.getCanonicalText() +
"() {\n" +
"@Override \n" +
"protected " +
boxedTypeName +
" initialValue() {\n" +
" return " +
(PsiUtil.isLanguageLevel5OrHigher(initializer)
? initializer.getText()
: (from instanceof PsiPrimitiveType ? "new " +
((PsiPrimitiveType)from).getBoxedTypeName() +
"(" +
initializer.getText() +
")" : initializer.getText())) +
";\n" +
"}\n" +
"}", initializer);
}
private static String toPrimitive(String replaceByArg, PsiType from, PsiElement context) {
return PsiUtil.isLanguageLevel5OrHigher(context)
? replaceByArg
: from instanceof PsiPrimitiveType ? "((" +
((PsiPrimitiveType)from).getBoxedTypeName() +
")" +
replaceByArg +
")." +
from.getCanonicalText() +
"Value()" : "((" + from.getCanonicalText() + ")" + replaceByArg + ")";
}
private static String toBoxed(String replaceByArg, PsiType from, PsiElement context) {
return PsiUtil.isLanguageLevel5OrHigher(context)
? replaceByArg
: from instanceof PsiPrimitiveType ? "new " + ((PsiPrimitiveType)from).getBoxedTypeName() +
"(" +
replaceByArg +
")"
: replaceByArg;
}
private static String getBoxedWrapper(final PsiType from,
final PsiType to,
@NotNull String arg,
TypeMigrationLabeler labeler,
PsiElement context,
@Nullable String tryType) {
if (from instanceof PsiPrimitiveType) {
final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(to);
final PsiClass threadLocalClass = resolveResult.getElement();
LOG.assertTrue(threadLocalClass != null);
final PsiTypeParameter[] typeParameters = threadLocalClass.getTypeParameters();
if (typeParameters.length == 1) {
final PsiType initial = resolveResult.getSubstitutor().substitute(typeParameters[0]);
final PsiPrimitiveType unboxedInitialType = PsiPrimitiveType.getUnboxedType(initial);
if (unboxedInitialType != null) {
LOG.assertTrue(initial != null);
if (tryType != null) {
final PsiType exprType = labeler.getTypeEvaluator().evaluateType(
JavaPsiFacade.getElementFactory(threadLocalClass.getProject()).createExpressionFromText(tryType, context));
if (exprType != null && unboxedInitialType.isAssignableFrom(exprType)) {
return toBoxed(arg, from, context);
}
}
return "new " + initial.getCanonicalText() + "((" + unboxedInitialType.getCanonicalText() + ")(" + arg + "))";
}
}
}
return toBoxed(arg, from, context);
}
}
@@ -0,0 +1,10 @@
public class X {
{
new Comparable<String>() {
@Override
public int compareTo(String o) {
return 0;
}
}
}
}
@@ -0,0 +1,10 @@
public class X {
{
new Comparable<<spam>Object</spam>>() {
@Override
public int compareTo(Object o) {
return 0;
}
}
}
}
@@ -0,0 +1,5 @@
<html>
<body>
Changes anonymous class type parameters in live template.
</body>
</html>
@@ -0,0 +1,4 @@
import java.util.concurrent.atomic.*;
public class X {
AtomicInteger count = new AtomicInteger(0);
}
@@ -0,0 +1,3 @@
public class X {
<spot>int count = 0;</spot>
}
@@ -0,0 +1,5 @@
<html>
<body>
This intention replaces variable type with corresponding atomic type.
</body>
</html>
@@ -0,0 +1,15 @@
import java.text.*;
import java.util.Date;
class X {
private static final ThreadLocal<DateFormat> dateFormat = new ThreadLocal<DateFormat>() {
@Override
protected DateFormat initialValue() {
return new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z");
}
};
public String getDateString() {
return dateFormat.get().format(new Date());
}
}
@@ -0,0 +1,10 @@
import java.text.*;
import java.util.Date;
public class X {
private static DateFormat <spot>dateFormat</spot> = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z");
public String getDateString() {
return dateFormat.format(new Date());
}
}
@@ -0,0 +1,5 @@
<html>
<body>
This intention replaces field type with corresponding thread local.
</body>
</html>
@@ -0,0 +1,30 @@
package com.intellij.codeInsight;
import com.intellij.codeInsight.daemon.quickFix.LightQuickFixParameterizedTestCase;
import com.intellij.testFramework.PlatformTestUtil;
import org.jetbrains.annotations.NotNull;
/**
* @author anna
*/
public class ConvertToAtomicIntentionTest extends LightQuickFixParameterizedTestCase {
@Override
protected boolean shouldBeAvailableAfterExecution() {
return true;
}
@Override
protected String getBasePath() {
return "/intentions/atomic";
}
@NotNull
@Override
protected String getTestDataPath() {
return PlatformTestUtil.getCommunityPath() + "/java/typeMigration/testData";
}
public void test() throws Exception {
doAllTests();
}
}
@@ -0,0 +1,30 @@
package com.intellij.codeInsight;
import com.intellij.codeInsight.daemon.quickFix.LightQuickFixParameterizedTestCase;
import com.intellij.testFramework.PlatformTestUtil;
import org.jetbrains.annotations.NotNull;
/**
* @author anna
*/
public class ConvertToThreadLocalIntentionTest extends LightQuickFixParameterizedTestCase {
@Override
protected boolean shouldBeAvailableAfterExecution() {
return true;
}
@Override
protected String getBasePath() {
return "/intentions/threadLocal";
}
@NotNull
@Override
protected String getTestDataPath() {
return PlatformTestUtil.getCommunityPath() + "/java/typeMigration/testData";
}
public void test() throws Exception {
doAllTests();
}
}
@@ -0,0 +1,26 @@
/*
* User: anna
* Date: 04-Aug-2008
*/
package com.intellij.refactoring;
import com.intellij.codeInsight.ConvertToAtomicIntentionTest;
import com.intellij.codeInsight.ConvertToThreadLocalIntentionTest;
import junit.framework.Test;
import junit.framework.TestSuite;
public class AllTypeMigrationTests {
@SuppressWarnings({"UnusedDeclaration"})
public static Test suite() {
final TestSuite suite = new TestSuite();
suite.addTestSuite(TypeMigrationTest.class);
suite.addTestSuite(TypeMigrationByAtomicRuleTest.class);
suite.addTestSuite(TypeMigrationByThreadLocalRuleTest.class);
suite.addTestSuite(MigrateTypeSignatureTest.class);
suite.addTestSuite(ChangeTypeSignatureTest.class);
suite.addTestSuite(WildcardTypeMigrationTest.class);
suite.addTestSuite(ConvertToAtomicIntentionTest.class);
suite.addTestSuite(ConvertToThreadLocalIntentionTest.class);
return suite;
}
}
@@ -0,0 +1,148 @@
/*
* User: anna
* Date: 18-Mar-2008
*/
package com.intellij.refactoring;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.PsiImmediateClassType;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.refactoring.typeMigration.TypeMigrationLabeler;
import com.intellij.refactoring.typeMigration.TypeMigrationProcessor;
import com.intellij.refactoring.typeMigration.TypeMigrationRules;
import com.intellij.testFramework.LightCodeInsightTestCase;
import com.intellij.testFramework.PlatformTestUtil;
import org.jetbrains.annotations.NotNull;
public class ChangeTypeSignatureTest extends LightCodeInsightTestCase {
@NotNull
@Override
protected String getTestDataPath() {
return PlatformTestUtil.getCommunityPath() + "/java/typeMigration/testData";
}
private void doTest(boolean success, String migrationTypeText) throws Exception {
String dataPath = "/refactoring/changeTypeSignature/";
configureByFile(dataPath + getTestName(false) + ".java");
final PsiFile file = getFile();
final PsiElement element = file.findElementAt(getEditor().getCaretModel().getOffset());
final PsiReferenceParameterList parameterList = PsiTreeUtil.getParentOfType(element, PsiReferenceParameterList.class);
assert parameterList != null;
final PsiClass superClass = (PsiClass)((PsiJavaCodeReferenceElement)parameterList.getParent()).resolve();
assert superClass != null;
PsiType migrationType = getJavaFacade().getElementFactory().createTypeFromText(migrationTypeText, null);
try {
final TypeMigrationRules rules = new TypeMigrationRules(TypeMigrationLabeler.getElementType(parameterList));
rules.setMigrationRootType(PsiSubstitutor.EMPTY.put(superClass.getTypeParameters()[0], migrationType).substitute(new PsiImmediateClassType(superClass, PsiSubstitutor.EMPTY)));
rules.setBoundScope(GlobalSearchScope.projectScope(getProject()));
new TypeMigrationProcessor(getProject(), parameterList, rules).run();
if (success) {
checkResultByFile(dataPath + getTestName(false) + ".java.after");
} else {
fail("Conflicts should be detected");
}
}
catch (RuntimeException e) {
if (success) {
e.printStackTrace();
fail("Conflicts should not appear");
}
}
}
private void doTest(boolean success) throws Exception {
doTest(success, CommonClassNames.JAVA_LANG_OBJECT);
}
public void testListTypeArguments() throws Exception {
doTest(true);
}
public void testFieldUsage() throws Exception {
doTest(true);
}
public void testFieldUsage1() throws Exception {
doTest(true);
}
public void testReturnType() throws Exception {
doTest(true);
}
public void testReturnType1() throws Exception {
doTest(true);
}
public void testReturnType2() throws Exception {
doTest(true);
}
public void testPassedParameter() throws Exception {
doTest(true);
}
public void testPassedParameter1() throws Exception {
doTest(true, "java.lang.Integer");
}
public void testPassedParameter2() throws Exception {
doTest(true);
}
public void testUsedInSuper() throws Exception {
doTest(true);
}
public void testCompositeReturnType() throws Exception {
doTest(true);
}
public void testTypeHierarchy() throws Exception {
doTest(true);
}
public void testTypeHierarchy1() throws Exception {
doTest(true);
}
public void testTypeHierarchy2() throws Exception {
doTest(true);
}
public void testTypeHierarchyFieldUsage() throws Exception {
doTest(true);
}
public void testTypeHierarchyFieldUsageConflict() throws Exception {
doTest(true);
}
public void testParameterMigration() throws Exception {
doTest(true);
}
public void testParameterMigration1() throws Exception {
doTest(true, "java.lang.Integer");
}
public void testParameterMigration2() throws Exception {
doTest(true, "java.lang.Integer");
}
public void testFieldTypeMigration() throws Exception {
doTest(true, "java.lang.String");
}
public void testMethodReturnTypeMigration() throws Exception {
doTest(true, "java.lang.Integer");
}
@Override
protected boolean isRunInWriteAction() {
return false;
}
}
@@ -0,0 +1,561 @@
/*
* User: anna
* Date: 30-Apr-2008
*/
package com.intellij.refactoring;
import com.intellij.psi.CommonClassNames;
import com.intellij.psi.PsiEllipsisType;
import com.intellij.psi.PsiType;
import org.jetbrains.annotations.NotNull;
public class MigrateTypeSignatureTest extends TypeMigrationTestBase {
@NotNull
@Override
public String getTestRoot() {
return "/refactoring/migrateTypeSignature/";
}
public void testExprAccess2Lvalue() throws Exception {
doTestFieldType("myForAccess", "Expr",
myJavaFacade.getElementFactory().createTypeFromText("ClassChild", null),
myJavaFacade.getElementFactory().createTypeFromText("ClassParent", null));
}
public void testExprAccess2Rvalue() throws Exception {
doTestFieldType("myField", "Expr",
myJavaFacade.getElementFactory().createTypeFromText("ClassChild", null),
myJavaFacade.getElementFactory().createTypeFromText("ClassGrandChild", null));
}
public void testExprAccessParent2Lvalue() throws Exception {
doTestFieldType("myForSuperAccess", "Ession",
myJavaFacade.getElementFactory().createTypeFromText("ClassChild", null),
myJavaFacade.getElementFactory().createTypeFromText("ClassParent", null));
}
public void testExprAccessParent2Rvalue() throws Exception {
doTestFieldType("myField", "Expr",
myJavaFacade.getElementFactory().createTypeFromText("ClassChild", null),
myJavaFacade.getElementFactory().createTypeFromText("ClassGrandChild", null));
}
public void testExprArrayAccessNegative() throws Exception {
doTestFirstParamType("meth", "Expr", PsiType.INT, PsiType.DOUBLE);
}
public void testExprArrayAccessPositive() throws Exception {
doTestFirstParamType("meth", "Expr", PsiType.INT, PsiType.CHAR);
}
public void testExprCalcBooleanBoolean() throws Exception {
doTestFirstParamType("meth", "Expr", PsiType.BOOLEAN, PsiType.INT);
}
public void testExprCalcBooleanNumeric() throws Exception {
doTestFirstParamType("meth", "Expr", PsiType.INT,
myJavaFacade.getElementFactory().createTypeFromText(CommonClassNames.JAVA_LANG_OBJECT, null));
}
public void testExprCalcBooleanReference() throws Exception {
doTestFirstParamType("meth", "Expr",
myJavaFacade.getElementFactory().createTypeFromText("java.lang.String", null),
PsiType.DOUBLE);
}
public void testExprCalcNumeric2Boolean() throws Exception {
doTestFirstParamType("meth", "Expr", PsiType.INT, PsiType.BOOLEAN);
}
public void testExprCalcNumeric2Floating() throws Exception {
doTestFirstParamType("meth", "Expr", PsiType.INT, PsiType.FLOAT);
}
public void testExprCalcNumeric2Int() throws Exception {
doTestFirstParamType("meth", "Expr", PsiType.INT, PsiType.LONG);
}
public void testExprCalcNumeric2String() throws Exception {
doTestFirstParamType("meth", "Expr", PsiType.INT,
myJavaFacade.getElementFactory().createTypeFromText("java.lang.String", null));
}
public void testExprCast2LvalueNeg() throws Exception {
doTestFirstParamType("meth", "Expr", PsiType.BYTE,
myJavaFacade.getElementFactory().createTypeFromText("java.lang.String", null));
}
public void testExprCast2LvaluePos() throws Exception {
doTestFirstParamType("meth", "Expr", PsiType.BYTE, PsiType.INT);
}
public void testExprConcatNumeric2Reference() throws Exception {
doTestFirstParamType("meth", "Expr", PsiType.INT,
myJavaFacade.getElementFactory().createTypeFromText(CommonClassNames.JAVA_LANG_OBJECT, null));
}
public void testExprConcatNumeric2String() throws Exception {
doTestFirstParamType("meth", "Expr", PsiType.INT,
myJavaFacade.getElementFactory().createTypeFromText("java.lang.String", null));
}
public void testExprConcatString2Numeric() throws Exception {
doTestFirstParamType("meth", "Expr",
myJavaFacade.getElementFactory().createTypeFromText("java.lang.String", null),
PsiType.INT);
}
public void testExprConcatString2Reference() throws Exception {
doTestFirstParamType("meth", "Expr",
myJavaFacade.getElementFactory().createTypeFromText("java.lang.String", null),
myJavaFacade.getElementFactory().createTypeFromText(CommonClassNames.JAVA_LANG_OBJECT, null));
}
public void testExprInstanceofNeg() throws Exception {
doTestFirstParamType("meth", "Expr",
myJavaFacade.getElementFactory().createTypeFromText(CommonClassNames.JAVA_UTIL_SET, null),
myJavaFacade.getElementFactory().createTypeFromText(CommonClassNames.JAVA_UTIL_LIST, null));
}
public void testExprInstanceofPos() throws Exception {
doTestFirstParamType("meth", "Expr",
myJavaFacade.getElementFactory().createTypeFromText(CommonClassNames.JAVA_UTIL_MAP, null),
myJavaFacade.getElementFactory().createTypeFromText("java.util.AbstractMap", null));
}
public void testExprLiteralBoolean() throws Exception {
doTestFieldType("myField", "Expr",
myJavaFacade.getElementFactory().createTypeFromText(CommonClassNames.JAVA_LANG_OBJECT, null),
PsiType.BOOLEAN);
}
public void testExprLiteralByte() throws Exception {
doTestFieldType("myField", "Expr",
myJavaFacade.getElementFactory().createTypeFromText(CommonClassNames.JAVA_LANG_OBJECT, null),
PsiType.BYTE);
}
public void testExprLiteralChar() throws Exception {
doTestFieldType("myField", "Expr",
myJavaFacade.getElementFactory().createTypeFromText(CommonClassNames.JAVA_LANG_OBJECT, null),
PsiType.CHAR);
}
public void testExprLiteralClassExtends() throws Exception {
doTestFieldType("myField", "Expr",
myJavaFacade.getElementFactory().createTypeFromText(CommonClassNames.JAVA_LANG_OBJECT, null),
myJavaFacade.getElementFactory().createTypeFromText("java.lang.Class<? extends java.util.Collection[]>", null));
}
public void testExprLiteralClassPrimitive() throws Exception {
doTestFieldType("myField", "Expr",
myJavaFacade.getElementFactory().createTypeFromText(CommonClassNames.JAVA_LANG_OBJECT, null),
myJavaFacade.getElementFactory().createTypeFromText("java.lang.Class<Integer>", null));
}
public void testExprLiteralClassPrimitiveArray() throws Exception {
doTestFieldType("myField", "Expr",
myJavaFacade.getElementFactory().createTypeFromText(CommonClassNames.JAVA_LANG_OBJECT, null),
myJavaFacade.getElementFactory().createTypeFromText("java.lang.Class<int[]>", null));
}
public void testExprLiteralClassRaw() throws Exception {
doTestFieldType("myField", "Expr",
myJavaFacade.getElementFactory().createTypeFromText(CommonClassNames.JAVA_LANG_OBJECT, null),
myJavaFacade.getElementFactory().createTypeFromText("java.lang.Class", null));
}
public void testExprLiteralClassReference() throws Exception {
doTestFieldType("myField", "Expr",
myJavaFacade.getElementFactory().createTypeFromText(CommonClassNames.JAVA_LANG_OBJECT, null),
myJavaFacade.getElementFactory().createTypeFromText("java.lang.Class<java.util.Set>", null));
}
public void testExprLiteralClassReferenceArray() throws Exception {
doTestFieldType("myField", "Expr",
myJavaFacade.getElementFactory().createTypeFromText(CommonClassNames.JAVA_LANG_OBJECT, null),
myJavaFacade.getElementFactory().createTypeFromText("java.lang.Class<java.util.Set[]>", null));
}
public void testExprLiteralClassSuper() throws Exception {
doTestFieldType("myField", "Expr",
myJavaFacade.getElementFactory().createTypeFromText(CommonClassNames.JAVA_LANG_OBJECT, null),
myJavaFacade.getElementFactory().createTypeFromText("java.lang.Class<? super java.util.AbstractSet[]>", null));
}
public void testExprLiteralDouble() throws Exception {
doTestFieldType("myField", "Expr",
myJavaFacade.getElementFactory().createTypeFromText(CommonClassNames.JAVA_LANG_OBJECT, null),
PsiType.DOUBLE);
}
public void testExprLiteralFloat() throws Exception {
doTestFieldType("myField", "Expr",
myJavaFacade.getElementFactory().createTypeFromText(CommonClassNames.JAVA_LANG_OBJECT, null),
PsiType.FLOAT);
}
public void testExprLiteralInt() throws Exception {
doTestFieldType("myField", "Expr",
myJavaFacade.getElementFactory().createTypeFromText(CommonClassNames.JAVA_LANG_OBJECT, null),
PsiType.INT);
}
public void testExprLiteralLong() throws Exception {
doTestFieldType("myField", "Expr",
myJavaFacade.getElementFactory().createTypeFromText(CommonClassNames.JAVA_LANG_OBJECT, null),
PsiType.LONG);
}
public void testExprLiteralShort() throws Exception {
doTestFieldType("myField", "Expr",
myJavaFacade.getElementFactory().createTypeFromText(CommonClassNames.JAVA_LANG_OBJECT, null),
PsiType.SHORT);
}
public void testExprLiteralString() throws Exception {
doTestFieldType("myField", "Expr",
myJavaFacade.getElementFactory().createTypeFromText(CommonClassNames.JAVA_LANG_OBJECT, null),
myJavaFacade.getElementFactory().createTypeFromText("java.lang.String", null));
}
public void testExprNewArrayArray2Lvalue() throws Exception {
doTestFirstParamType("meth", "Expr",
myJavaFacade.getElementFactory().createTypeFromText("FaceChild", null).createArrayType(),
myJavaFacade.getElementFactory().createTypeFromText("FaceParent", null).createArrayType());
}
public void testExprNewArrayArray2Rvalue() throws Exception {
doTestFieldType("myField", "Expr",
myJavaFacade.getElementFactory().createTypeFromText("FaceChild", null).createArrayType().createArrayType().createArrayType(),
myJavaFacade.getElementFactory().createTypeFromText("ClassParent", null).createArrayType().createArrayType().createArrayType());
}
public void testExprNewArrayGen2Rvalue() throws Exception {
doTestFieldType("myField", "Expr",
myJavaFacade.getElementFactory().createTypeFromText(CommonClassNames.JAVA_UTIL_SET, null).createArrayType(),
myJavaFacade.getElementFactory().createTypeFromText("java.util.Set<java.lang.Integer>", null).createArrayType());
}
public void testExprNewArrayPrimitive2Lvalue() throws Exception {
doTestFirstParamType("meth", "Expr", PsiType.BOOLEAN, PsiType.INT);
}
public void testExprNewArrayPrimitive2Rvalue() throws Exception {
doTestFieldType("myField", "Expr",
PsiType.BOOLEAN.createArrayType().createArrayType(),
PsiType.INT.createArrayType().createArrayType());
}
public void testExprNewArrayReftype2Lvalue() throws Exception {
doTestFirstParamType("meth", "Expr",
myJavaFacade.getElementFactory().createTypeFromText("FaceChild", null),
myJavaFacade.getElementFactory().createTypeFromText("FaceParent", null));
}
public void testExprNewArrayReftype2Rvalue() throws Exception {
doTestFieldType("myField", "Expr",
myJavaFacade.getElementFactory().createTypeFromText("FaceChild", null).createArrayType().createArrayType(),
myJavaFacade.getElementFactory().createTypeFromText("ClassParent", null).createArrayType().createArrayType());
}
public void testExprNewGen() throws Exception {
doTestFieldType("myField", "Expr",
myJavaFacade.getElementFactory().createTypeFromText(CommonClassNames.JAVA_LANG_OBJECT, null),
myJavaFacade.getElementFactory().createTypeFromText("java.util.Set<Subject>", null));
}
public void testExprNewGenExtends() throws Exception {
doTestFieldType("myField", "Expr",
myJavaFacade.getElementFactory().createTypeFromText(CommonClassNames.JAVA_LANG_OBJECT, null),
myJavaFacade.getElementFactory().createTypeFromText("java.util.Set<? extends Subject>", null));
}
public void testExprNewGenSuper() throws Exception {
doTestFieldType("myField", "Expr",
myJavaFacade.getElementFactory().createTypeFromText(CommonClassNames.JAVA_LANG_OBJECT, null),
myJavaFacade.getElementFactory().createTypeFromText("java.util.Set<? super Subject>", null));
}
public void testExprNewReference() throws Exception {
doTestFieldType("myField", "Expr",
myJavaFacade.getElementFactory().createTypeFromText("Expr.Ancestor", null),
myJavaFacade.getElementFactory().createTypeFromText("Expr.Subject", null));
}
public void testExprReturn2Lvalue() throws Exception {
doTestFirstParamType("meth", "Expr", PsiType.INT,
myJavaFacade.getElementFactory().createTypeFromText("java.lang.String", null));
}
public void testExprReturn2Rvalue() throws Exception {
doTestMethodType("meth", "Expr", PsiType.INT,
myJavaFacade.getElementFactory().createTypeFromText("java.lang.String", null));
}
public void testExprTernary() throws Exception {
doTestFirstParamType("meth", "Expr", PsiType.DOUBLE,
myJavaFacade.getElementFactory().createTypeFromText("java.lang.String", null));
}
public void testOverridingDown() throws Exception {
doTestMethodType("getInt", "Parent", PsiType.INT, PsiType.BYTE);
}
public void testOverridingUp() throws Exception {
doTestMethodType("getInt", "Child", PsiType.INT, PsiType.BYTE);
}
public void testSpecJavadoc() throws Exception {
doTestFirstParamType("meth", "Spec", PsiType.DOUBLE,
myJavaFacade.getElementFactory().createTypeFromText(CommonClassNames.JAVA_UTIL_SET, null));
}
public void testSpecNotUsed() throws Exception {
doTestFieldType("myField", "Spec", PsiType.INT, PsiType.BOOLEAN);
}
public void testTypeArrayReftype2Lvalue() throws Exception {
doTestFirstParamType("meth", "Type",
myJavaFacade.getElementFactory().createTypeFromText("Descendant", null).createArrayType(),
myJavaFacade.getElementFactory().createTypeFromText("Subject", null).createArrayType());
}
public void testTypeArrayReftype2Rvalue() throws Exception {
doTestFieldType("myField", "Type",
myJavaFacade.getElementFactory().createTypeFromText("Ancestor", null).createArrayType().createArrayType(),
myJavaFacade.getElementFactory().createTypeFromText("Subject", null).createArrayType().createArrayType());
}
public void testTypeArrayRoots2Lvalue() throws Exception {
doTestFirstParamType("meth", "Type",
myJavaFacade.getElementFactory().createTypeFromText("Holder", null),
myJavaFacade.getElementFactory().createTypeFromText("Holder", null).createArrayType());
}
public void testTypeArrayVararg2Lvalue() throws Exception {
doTestFirstParamType("meth", "Type",
myJavaFacade.getElementFactory().createTypeFromText("Descendant", null).createArrayType(),
new PsiEllipsisType(myJavaFacade.getElementFactory().createTypeFromText("Subject", null)));
}
public void testTypeArrayVararg2RvalueNeg() throws Exception {
doTestFieldType("myField", "Type",
myJavaFacade.getElementFactory().createTypeFromText("Ancestor", null).createArrayType(),
myJavaFacade.getElementFactory().createTypeFromText("Descendant", null).createArrayType());
}
public void testTypeArrayVararg2RvaluePos() throws Exception {
doTestFieldType("myField", "Type",
myJavaFacade.getElementFactory().createTypeFromText("Ancestor", null).createArrayType(),
myJavaFacade.getElementFactory().createTypeFromText("Subject", null).createArrayType());
}
public void testTypeAutoboxBoolean2Lvalue() throws Exception {
doTestFirstParamType("meth", "Type", PsiType.BOOLEAN,
myJavaFacade.getElementFactory().createTypeFromText("java.lang.Boolean", null));
}
public void testTypeAutoboxBoolean2Rvalue() throws Exception {
doTestFieldType("myField", "Type", myJavaFacade.getElementFactory().createTypeFromText("java.lang.Boolean", null),
PsiType.BOOLEAN);
}
public void testTypeAutoboxByte2Lvalue() throws Exception {
doTestFirstParamType("meth", "Type", PsiType.BYTE,
myJavaFacade.getElementFactory().createTypeFromText("java.lang.Byte", null));
}
public void testTypeAutoboxByte2Rvalue() throws Exception {
doTestFieldType("myField", "Type", myJavaFacade.getElementFactory().createTypeFromText("java.lang.Byte", null),
PsiType.BYTE);
}
public void testTypeAutoboxChar2Lvalue() throws Exception {
doTestFirstParamType("meth", "Type", PsiType.CHAR,
myJavaFacade.getElementFactory().createTypeFromText("java.lang.Character", null));
}
public void testTypeAutoboxChar2Rvalue() throws Exception {
doTestFieldType("myField", "Type", myJavaFacade.getElementFactory().createTypeFromText("java.lang.Character", null),
PsiType.CHAR);
}
public void testTypeAutoboxDouble2Lvalue() throws Exception {
doTestFirstParamType("meth", "Type", PsiType.DOUBLE,
myJavaFacade.getElementFactory().createTypeFromText("java.lang.Double", null));
}
public void testTypeAutoboxDouble2Rvalue() throws Exception {
doTestFieldType("myField", "Type", myJavaFacade.getElementFactory().createTypeFromText("java.lang.Double", null),
PsiType.DOUBLE);
}
public void testTypeAutoboxFloat2Lvalue() throws Exception {
doTestFirstParamType("meth", "Type", PsiType.FLOAT,
myJavaFacade.getElementFactory().createTypeFromText("java.lang.Float", null));
}
public void testTypeAutoboxFloat2Rvalue() throws Exception {
doTestFieldType("myField", "Type", myJavaFacade.getElementFactory().createTypeFromText("java.lang.Float", null),
PsiType.FLOAT);
}
public void testTypeAutoboxInt2Lvalue() throws Exception {
doTestFirstParamType("meth", "Type", PsiType.INT,
myJavaFacade.getElementFactory().createTypeFromText("java.lang.Integer", null));
}
public void testTypeAutoboxInt2Rvalue() throws Exception {
doTestFieldType("myField", "Type", myJavaFacade.getElementFactory().createTypeFromText("java.lang.Integer", null),
PsiType.INT);
}
public void testTypeAutoboxLong2Lvalue() throws Exception {
doTestFirstParamType("meth", "Type", PsiType.LONG,
myJavaFacade.getElementFactory().createTypeFromText("java.lang.Long", null));
}
public void testTypeAutoboxLong2Rvalue() throws Exception {
doTestFieldType("myField", "Type", myJavaFacade.getElementFactory().createTypeFromText("java.lang.Long", null),
PsiType.LONG);
}
public void testTypeAutoboxShort2Lvalue() throws Exception {
doTestFirstParamType("meth", "Type", PsiType.SHORT,
myJavaFacade.getElementFactory().createTypeFromText("java.lang.Short", null));
}
public void testTypeAutoboxShort2Rvalue() throws Exception {
doTestFieldType("myField", "Type", myJavaFacade.getElementFactory().createTypeFromText("java.lang.Short", null),
PsiType.SHORT);
}
public void testTypeGenAncestor2Lvalue() throws Exception {
doTestFirstParamType("meth", "Type",
myJavaFacade.getElementFactory().createTypeFromText(CommonClassNames.JAVA_UTIL_SET, null),
myJavaFacade.getElementFactory().createTypeFromText("java.util.Set<Subject>", null));
}
public void testTypeGenAncestorWildcard2Lvalue() throws Exception {
doTestFirstParamType("meth", "Type",
myJavaFacade.getElementFactory().createTypeFromText(CommonClassNames.JAVA_UTIL_SET, null),
myJavaFacade.getElementFactory().createTypeFromText("java.util.Set<? extends Subject>", null));
}
public void testTypeGenDescendant2Rvalue() throws Exception {
doTestFieldType("myField", "Type",
myJavaFacade.getElementFactory().createTypeFromText(CommonClassNames.JAVA_UTIL_SET, null),
myJavaFacade.getElementFactory().createTypeFromText("java.util.Set<Subject>", null));
}
public void testTypeGenDescendantWildcard2Rvalue() throws Exception {
doTestFieldType("myField", "Type",
myJavaFacade.getElementFactory().createTypeFromText(CommonClassNames.JAVA_UTIL_SET, null),
myJavaFacade.getElementFactory().createTypeFromText("java.util.Set<? super Subject>", null));
}
public void testTypeGenRaw2Lvalue() throws Exception {
doTestFirstParamType("meth", "Type",
myJavaFacade.getElementFactory().createTypeFromText("java.util.Set<Any>", null),
myJavaFacade.getElementFactory().createTypeFromText(CommonClassNames.JAVA_UTIL_SET, null));
}
public void testTypeGenRaw2Rvalue() throws Exception {
doTestFieldType("myField", "Type",
myJavaFacade.getElementFactory().createTypeFromText("java.util.Set<Any>", null),
myJavaFacade.getElementFactory().createTypeFromText(CommonClassNames.JAVA_UTIL_SET, null));
}
public void testTypePrimsubBoolean2Lvalue() throws Exception {
doTestFirstParamType("meth", "Type", PsiType.INT, PsiType.BOOLEAN);
}
public void testTypePrimsubBoolean2Rvalue() throws Exception {
doTestFieldType("myField", "Type", PsiType.INT, PsiType.BOOLEAN);
}
public void testTypePrimsubByte2Rvalue() throws Exception {
doTestFieldType("myField", "Type", PsiType.DOUBLE, PsiType.BYTE);
}
public void testTypePrimsubChar2Lvalue() throws Exception {
doTestFirstParamType("meth", "Type", PsiType.BYTE, PsiType.CHAR);
}
public void testTypePrimsubChar2Rvalue() throws Exception {
doTestFieldType("myField", "Type", PsiType.DOUBLE, PsiType.CHAR);
}
public void testTypePrimsubDouble2Lvalue() throws Exception {
doTestFirstParamType("meth", "Type", PsiType.BYTE, PsiType.DOUBLE);
}
public void testTypePrimsubFloat2Lvalue() throws Exception {
doTestFirstParamType("meth", "Type", PsiType.BYTE, PsiType.FLOAT);
}
public void testTypePrimsubFloat2Rvalue() throws Exception {
doTestFieldType("myField", "Type", PsiType.DOUBLE, PsiType.FLOAT);
}
public void testTypePrimsubInt2Lvalue() throws Exception {
doTestFirstParamType("meth", "Type", PsiType.BYTE, PsiType.INT);
}
public void testTypePrimsubInt2Rvalue() throws Exception {
doTestFieldType("myField", "Type", PsiType.DOUBLE, PsiType.INT);
}
public void testTypePrimsubLong2Lvalue() throws Exception {
doTestFirstParamType("meth", "Type", PsiType.BYTE, PsiType.LONG);
}
public void testTypePrimsubLong2Rvalue() throws Exception {
doTestFieldType("myField", "Type", PsiType.DOUBLE, PsiType.LONG);
}
public void testTypePrimsubShort2Lvalue() throws Exception {
doTestFirstParamType("meth", "Type", PsiType.BYTE, PsiType.SHORT);
}
public void testTypePrimsubShort2Rvalue() throws Exception {
doTestFieldType("myField", "Type", PsiType.DOUBLE, PsiType.SHORT);
}
public void testTypeRefClassChild2Rvalue() throws Exception {
doTestFieldType("myField", "Type",
myJavaFacade.getElementFactory().createTypeFromText("FaceParent", null),
myJavaFacade.getElementFactory().createTypeFromText("ClassChild", null));
}
public void testTypeRefClassParent2Lvalue() throws Exception {
doTestFirstParamType("meth", "Type",
myJavaFacade.getElementFactory().createTypeFromText("ClassChild", null),
myJavaFacade.getElementFactory().createTypeFromText("ClassParent", null));
}
public void testTypeRefClassParent2Rvalue() throws Exception {
doTestFieldType("myField", "Type",
myJavaFacade.getElementFactory().createTypeFromText("FaceParent", null),
myJavaFacade.getElementFactory().createTypeFromText("ClassParent", null));
}
public void testTypeRefFaceChild2Lvalue() throws Exception {
doTestFirstParamType("meth", "Type",
myJavaFacade.getElementFactory().createTypeFromText("ClassChild", null),
myJavaFacade.getElementFactory().createTypeFromText("FaceChild", null));
}
public void testTypeRefFaceChild2Rvalue() throws Exception {
doTestFieldType("myField", "Type",
myJavaFacade.getElementFactory().createTypeFromText("FaceParent", null),
myJavaFacade.getElementFactory().createTypeFromText("FaceChild", null));
}
public void testTypeRefFaceParent2Lvalue() throws Exception {
doTestFirstParamType("meth", "Type",
myJavaFacade.getElementFactory().createTypeFromText("ClassChild", null),
myJavaFacade.getElementFactory().createTypeFromText("FaceParent", null));
}
}
@@ -0,0 +1,100 @@
/*
* User: anna
* Date: 19-Aug-2009
*/
package com.intellij.refactoring;
import com.intellij.psi.PsiType;
import org.jetbrains.annotations.NotNull;
import java.util.concurrent.atomic.AtomicReferenceArray;
import java.util.concurrent.atomic.AtomicIntegerArray;
public class TypeMigrationByAtomicRuleTest extends TypeMigrationTestBase{
@NotNull
@Override
protected String getTestRoot() {
return "/refactoring/typeMigrationByAtomic/";
}
private void doTestDirectMigration() throws Exception {
doTestFieldType("i", PsiType.INT, myJavaFacade.getElementFactory().createTypeFromText("java.util.concurrent.atomic.AtomicInteger", null));
}
public void testDirectIncrementDecrement() throws Exception {
doTestDirectMigration();
}
public void testDirectAssignments() throws Exception {
doTestDirectMigration();
}
public void testDirectConditions() throws Exception {
doTestFieldType("b", PsiType.BOOLEAN, myJavaFacade.getElementFactory().createTypeFromText("java.util.concurrent.atomic.AtomicBoolean", null));
}
public void testDirectByte() throws Exception {
doTestFieldType("b", PsiType.BYTE, myJavaFacade.getElementFactory().createTypeFromText("java.util.concurrent.atomic.AtomicReference<java.lang.Byte>", null));
}
public void testDirectString() throws Exception {
doTestFieldType("s", myJavaFacade.getElementFactory().createTypeFromText("java.lang.String", null),
myJavaFacade.getElementFactory().createTypeFromText("java.util.concurrent.atomic.AtomicReference<java.lang.String>", null));
}
public void testDirectForeach() throws Exception {
doTestFieldType("lst", myJavaFacade.getElementFactory().createTypeFromText("java.util.List<java.lang.String>", null),
myJavaFacade.getElementFactory().createTypeFromText("java.util.concurrent.atomic.AtomicReference<java.util.List<java.lang.String>>", null));
}
public void testDirectStringArray() throws Exception {
doTestFieldType("s", myJavaFacade.getElementFactory().createTypeFromText("java.lang.String", null).createArrayType(),
myJavaFacade.getElementFactory().createTypeFromText(AtomicReferenceArray.class.getName() + "<java.lang.String>", null));
}
public void testDirectIntArray() throws Exception {
doTestFieldType("a", PsiType.INT.createArrayType(),
myJavaFacade.getElementFactory().createTypeFromText(AtomicIntegerArray.class.getName(), null));
}
private void doTestReverseMigration() throws Exception {
doTestFieldType("i", myJavaFacade.getElementFactory().createTypeFromText("java.util.concurrent.atomic.AtomicInteger", null), PsiType.INT);
}
public void testReverseIncrementDecrement() throws Exception {
doTestReverseMigration();
}
public void testReverseAssignments() throws Exception {
doTestReverseMigration();
}
public void testReverseConditions() throws Exception {
doTestFieldType("b", myJavaFacade.getElementFactory().createTypeFromText("java.util.concurrent.atomic.AtomicBoolean", null), PsiType.BOOLEAN);
}
public void testReverseByte() throws Exception {
doTestFieldType("b", myJavaFacade.getElementFactory().createTypeFromText("java.util.concurrent.atomic.AtomicReference<java.lang.Byte>", null), PsiType.BYTE);
}
public void testReverseString() throws Exception {
doTestFieldType("s",
myJavaFacade.getElementFactory().createTypeFromText("java.util.concurrent.atomic.AtomicReference<java.lang.String>", null),
myJavaFacade.getElementFactory().createTypeFromText("java.lang.String", null));
}
public void testReverseStringArray() throws Exception {
doTestFieldType("s",
myJavaFacade.getElementFactory().createTypeFromText("java.util.concurrent.atomic.AtomicReferenceArray<java.lang.String>", null),
myJavaFacade.getElementFactory().createTypeFromText("java.lang.String", null).createArrayType());
}
public void testReverseIntArray() throws Exception {
doTestFieldType("a",
myJavaFacade.getElementFactory().createTypeFromText("java.util.concurrent.atomic.AtomicIntegerArray", null),
PsiType.INT.createArrayType());
}
}
@@ -0,0 +1,44 @@
/*
* User: anna
* Date: 19-Aug-2009
*/
package com.intellij.refactoring;
import com.intellij.psi.PsiType;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.openapi.roots.LanguageLevelProjectExtension;
import com.intellij.pom.java.LanguageLevel;
import org.jetbrains.annotations.NotNull;
public class TypeMigrationByThreadLocalRuleTest extends TypeMigrationTestBase{
@NotNull
@Override
protected String getTestRoot() {
return "/refactoring/typeMigrationByThreadLocal/";
}
public void testDirectInt() throws Exception {
doTestFieldType("i", PsiType.INT, myJavaFacade.getElementFactory().createTypeFromText("java.lang.ThreadLocal<java.lang.Integer>", null));
}
public void testDirectByte() throws Exception {
doTestFieldType("i", PsiType.BYTE, myJavaFacade.getElementFactory().createTypeFromText("java.lang.ThreadLocal<java.lang.Byte>", null));
}
public void testDirectString() throws Exception {
doTestFieldType("myS", PsiType.getJavaLangString(myPsiManager, GlobalSearchScope.allScope(myProject)), myJavaFacade.getElementFactory().createTypeFromText("java.lang.ThreadLocal<java.lang.String>", null));
}
public void testLanguageLevel() throws Exception {
final LanguageLevelProjectExtension extension = LanguageLevelProjectExtension.getInstance(getProject());
final LanguageLevel languageLevel = extension.getLanguageLevel();
try {
extension.setLanguageLevel(LanguageLevel.JDK_1_3);
doTestFieldType("i", PsiType.INT, myJavaFacade.getElementFactory().createTypeFromText("java.lang.ThreadLocal", null));
}
finally {
extension.setLanguageLevel(languageLevel);
}
}
}
@@ -0,0 +1,883 @@
package com.intellij.refactoring;
import com.intellij.openapi.roots.LanguageLevelProjectExtension;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.refactoring.typeMigration.TypeMigrationRules;
import org.jetbrains.annotations.NotNull;
/**
* @author db
* @since 22.07.2003
*/
public class TypeMigrationTest extends TypeMigrationTestBase {
private PsiElementFactory myFactory;
@NotNull
@Override
public String getTestRoot() {
return "/refactoring/typeMigration/";
}
@Override
public void setUp() throws Exception {
super.setUp();
LanguageLevelProjectExtension.getInstance(getProject()).setLanguageLevel(LanguageLevel.HIGHEST);
myFactory = myJavaFacade.getElementFactory();
}
public void testT07() {
doTestFieldType("f",
PsiType.INT.createArrayType(),
myFactory.createTypeFromText("java.lang.Integer", null).createArrayType());
}
public void testT08() {
doTestFieldType("f",
myFactory.createTypeFromText("java.lang.Integer", null).createArrayType(),
myFactory.createTypeFromText("java.lang.String", null).createArrayType());
}
public void testT09() {
doTestFieldType("f",
myFactory.createTypeFromText("java.lang.Integer", null).createArrayType(),
myFactory.createTypeFromText("java.lang.String", null).createArrayType());
}
public void testT10() {
doTestFieldType("f",
myFactory.createTypeFromText("java.util.List<java.lang.Integer>", null),
myFactory.createTypeFromText("java.util.List<java.lang.String>", null));
}
public void testT11() {
doTestFieldType("f",
myFactory.createTypeFromText("java.util.Map<java.lang.Integer, java.lang.Integer>", null),
myFactory.createTypeFromText("java.util.Map<java.lang.String, java.lang.Integer>", null));
}
public void testT12() {
doTestFieldType("f",
myFactory.createTypeFromText("java.util.List<java.lang.Integer>", null),
myFactory.createTypeFromText("java.util.List<java.lang.String>", null));
}
public void testT13() {
doTestFieldType("f",
myFactory.createTypeFromText("java.util.List<java.lang.String>", null),
myFactory.createTypeFromText("java.util.List<java.lang.Integer>", null));
}
public void testT14() {
doTestFieldType("f",
myFactory.createTypeFromText("B", null),
myFactory.createTypeFromText("A", null));
}
//do not touch javadoc refs etc
public void testT15() {
doTestFieldType("f",
myFactory.createTypeFromText("B", null),
myFactory.createTypeFromText("A", null));
}
//do not touch signature with method type parameters
public void testT16() {
doTestFieldType("f",
myFactory.createTypeFromText("A", null),
myFactory.createTypeFromText("B", null));
}
//change method signature inspired by call on parameters
public void testT17() {
doTestFieldType("f",
myFactory.createTypeFromText("A", null),
myFactory.createTypeFromText("B", null));
}
//extending iterable -> used in foreach statement
public void testT18() {
doTestFieldType("f",
myFactory.createTypeFromText("A", null),
myFactory.createTypeFromText("B", null));
}
public void testT19() {
doTestFieldType("f",
myFactory.createTypeFromText("java.util.Map<java.lang.String, java.lang.String>", null),
myFactory.createTypeFromText("java.util.HashMap<java.lang.Integer, java.lang.Integer>", null));
}
public void testT20() {
doTestFieldType("f",
myFactory.createTypeFromText("java.util.HashMap<java.lang.Integer, java.lang.Integer>", null),
myFactory.createTypeFromText("java.util.Map<java.lang.String, java.lang.String>", null));
}
public void testT21() {
doTestFieldType("f",
myFactory.createTypeFromText("java.util.Map<java.lang.String, java.util.List<java.lang.String>>",
null),
myFactory.createTypeFromText("java.util.Map<java.lang.String, java.util.Set<java.lang.String>>",
null)
);
}
//varargs : removed after migration?!
public void testT22() {
doTestFieldType("f",
myFactory.createTypeFromText("java.lang.String", null),
myFactory.createTypeFromText("java.lang.Integer", null));
}
//substitution from super class: type params substitution needed
public void testT23() {
doTestFieldType("f",
myFactory.createTypeFromText("HashMap<java.lang.String, java.util.Set<java.lang.String>>", null),
myFactory.createTypeFromText("HashMap<java.lang.String, java.util.List<java.lang.String>>", null));
}
//check return type unchanged when it is possible
public void testT24() {
doTestFieldType("f",
myFactory.createTypeFromText("C", null),
myFactory.createTypeFromText("D", null));
}
public void testT25() {
doTestFieldType("f",
myFactory.createTypeFromText("C", null),
myFactory.createTypeFromText("D", null));
}
//check param type change
public void testT26() {
doTestFieldType("f",
myFactory.createTypeFromText("C", null),
myFactory.createTypeFromText("D", null));
}
public void testT27() {
doTestFieldType("f",
myFactory.createTypeFromText("C", null),
myFactory.createTypeFromText("D", null));
}
//list --> array
public void testT28() {
doTestFieldType("f",
myFactory.createTypeFromText("java.util.List<java.lang.String>", null),
myFactory.createTypeFromText("java.lang.String", null).createArrayType());
}
public void testT29() {
doTestMethodType("get",
myFactory.createTypeFromText("java.lang.String", null).createArrayType(),
myFactory.createTypeFromText("java.util.List<java.lang.String>", null));
}
public void testT30() {
doTestFieldType("f",
myFactory.createTypeFromText("java.util.List<java.lang.String>", null),
myFactory.createTypeFromText("java.lang.String", null).createArrayType());
}
public void testT31() {
doTestFieldType("f",
myFactory.createTypeFromText("Test", null),
myFactory.createTypeFromText(CommonClassNames.JAVA_LANG_OBJECT, null));
}
//non code usages
public void testT32() {
doTestFirstParamType("bar",
myFactory.createTypeFromText("long", null),
myFactory.createTypeFromText("int", null));
}
//change type arguments for new expressions: l = new ArrayList<String>() -> l = new ArrayList<Integer>()
public void testT33() {
doTestFieldType("l",
myFactory.createTypeFromText("java.util.List<java.lang.String>", null),
myFactory.createTypeFromText("java.util.List<java.lang.Integer>", null));
}
//new expression new ArrayList<String>() should be left without modifications
public void testT34() {
doTestFieldType("l",
myFactory.createTypeFromText("java.util.List<java.lang.String>", null),
myFactory.createTypeFromText("java.util.AbstractList<java.lang.String>", null));
}
public void testT35() {
doTestFieldType("myParent",
myFactory.createTypeFromText("Test", null),
myFactory.createTypeFromText("TestImpl", null));
}
//co-variant/contra-variant positions for primitive types 36-39
public void testT36() {
doTestFirstParamType("foo", PsiType.INT, PsiType.BYTE);
}
public void testT37() {
doTestFirstParamType("foo", PsiType.SHORT, PsiType.INT);
}
public void testT38() {
doTestFirstParamType("foo", PsiType.SHORT, PsiType.LONG);
}
public void testT39() {
doTestFirstParamType("foo", PsiType.SHORT, PsiType.BYTE);
}
//Set s = new HashSet() -> HashSet s = new HashSet();
public void testT40() {
doTestFieldType("l",
myFactory.createTypeFromText(CommonClassNames.JAVA_UTIL_LIST, null),
myFactory.createTypeFromText("java.util.ArrayList", null));
}
//Set s = new HashSet<String>() -> HashSet s = new HashSet<String>();
public void testT41() {
doTestFieldType("l",
myFactory.createTypeFromText(CommonClassNames.JAVA_UTIL_LIST, null),
myFactory.createTypeFromText("java.util.ArrayList", null));
}
//Set s = new HashSet() -> HashSet<String> s = new HashSet();
public void testT42() {
doTestFieldType("l",
myFactory.createTypeFromText(CommonClassNames.JAVA_UTIL_LIST, null),
myFactory.createTypeFromText("java.util.ArrayList<java.lang.String>", null));
}
//long l; Object o = l -> long l; Long o = l;
public void testT43() {
doTestFieldType("o",
myFactory.createTypeFromText(CommonClassNames.JAVA_LANG_OBJECT, null),
myFactory.createTypeFromText("java.lang.Long", null));
}
//long l; int i; l = i; -> long l; byte i; l = i;
public void testT44() {
doTestFieldType("i", PsiType.INT, PsiType.BYTE);
}
//long l; int i; l = i; -> byte l; -> byte i; l = i;
public void testT45() {
doTestFieldType("l", PsiType.LONG, PsiType.BYTE);
}
//byte i; long j = i; -> byte i; int j = i;
public void testT46() {
doTestFieldType("j", PsiType.LONG, PsiType.INT);
}
//o = null -? int o = null
public void testT47() {
doTestFieldType("o", myFactory.createTypeFromText(CommonClassNames.JAVA_LANG_OBJECT, null), PsiType.INT);
}
//co-variant/contra-variant assignments: leave types if possible change generics signature only 48-49
// foo(AbstractSet<String> s){Set<String> ss = s} -> foo(AbstractSet<Integer> s){Set<Integer> ss = s}
public void testT48() {
doTestFirstParamType("foo",
myFactory.createTypeFromText("java.util.AbstractSet<A>", null),
myFactory.createTypeFromText("java.util.AbstractSet<B>", null));
}
// Set<String> f; foo(AbstractSet<String> s){f = s} -> Set<Integer>f; foo(AbstractSet<Integer> s){f = s}
public void testT49() {
doTestFieldType("f",
myFactory.createTypeFromText("java.util.Set<A>", null),
myFactory.createTypeFromText("java.util.Set<B>", null));
}
//captured wildcard: Set<? extends JComponent> s; Set<? extends JComponent> c1 = s; ->
// Set<? extends JButton> s; Set<? extends JButton> c1 = s;
public void testT50() {
doTestFieldType("c1",
myFactory.createTypeFromText("java.util.Set<? extends JComponent>", null),
myFactory.createTypeFromText("java.util.Set<? extends JButton>", null));
}
//array initialization: 51-52
public void testT51() {
doTestFieldType("f",
myFactory.createTypeFromText("java.lang.String", null).createArrayType(),
myFactory.createTypeFromText(CommonClassNames.JAVA_LANG_OBJECT, null).createArrayType());
}
public void testT52() {
doTestFieldType("f",
myFactory.createTypeFromText(CommonClassNames.JAVA_UTIL_SET, null).createArrayType(),
myFactory.createTypeFromText(CommonClassNames.JAVA_LANG_OBJECT, null).createArrayType());
}
//generic type promotion to array initializer
public void testT53() {
doTestFieldType("f",
PsiType.DOUBLE.createArrayType(),
myFactory.createTypeFromText("java.util.Set<java.lang.String>", null).createArrayType());
}
//wildcard type promotion to expressions 54-55
public void testT54() {
doTestFieldType("f",
myFactory.createTypeFromText("java.util.Set<java.lang.Object>", null),
myFactory.createTypeFromText("java.util.Set<? extends java.lang.Integer>", null));
}
public void testT55() {
doTestFieldType("f",
myFactory.createTypeFromText("java.util.Set<java.lang.Object>", null),
myFactory.createTypeFromText("java.util.Set<?>", null));
}
//array index should be integer 56-57
public void testT56() {
doTestFirstParamType("foo", PsiType.INT, PsiType.DOUBLE);
}
public void testT57() {
doTestFirstParamType("foo", PsiType.INT, PsiType.BYTE);
}
//Arrays can be assignable to Object/Serializable/Cloneable 58-59; ~ 60 varargs
public void testT58() {
doTestFieldType("f",
myFactory.createTypeFromText("java.lang.String", null).createArrayType(),
myFactory.createTypeFromText(CommonClassNames.JAVA_LANG_OBJECT, null));
}
public void testT59() {
doTestFieldType("f",
myFactory.createTypeFromText("java.lang.String", null).createArrayType(),
myFactory.createTypeFromText("java.lang.Cloneable", null));
}
public void testT60() {
doTestFieldType("p",
PsiType.INT.createArrayType(),
myFactory.createTypeFromText(CommonClassNames.JAVA_LANG_OBJECT, null));
}
//change parameter type -> vararg; assignment changed to array
public void testT61() {
doTestFirstParamType("foo", PsiType.INT, new PsiEllipsisType(PsiType.INT));
}
//change field type -> change vararg parameter type due to assignment: 62-63
public void testT62() {
doTestFieldType("p", PsiType.INT.createArrayType(), myFactory.createTypeFromText(
CommonClassNames.JAVA_LANG_OBJECT, null));
}
public void testT63() {
doTestFieldType("p", PsiType.INT.createArrayType(), PsiType.DOUBLE.createArrayType());
}
//remove vararg type: 64-66
public void testT64() {
doTestFirstParamType("foo", new PsiEllipsisType(PsiType.INT), PsiType.INT);
}
public void testT65() {
doTestFirstParamType("foo",
new PsiEllipsisType(PsiType.INT),
myFactory.createTypeFromText("java.lang.String", null));
}
public void testT115() {
doTestFirstParamType("foo",
new PsiEllipsisType(myFactory.createTypeFromText(CommonClassNames.JAVA_LANG_OBJECT, null)),
new PsiEllipsisType(myFactory.createTypeFromText("java.lang.String", null)));
}
public void testT66() {
doTestFirstParamType("foo", new PsiEllipsisType(PsiType.INT), PsiType.INT);
}
public void testT67() {
doTestFirstParamType("methMemAcc",
myFactory.createTypeFromText(CommonClassNames.JAVA_LANG_OBJECT, null),
myFactory.createTypeFromText("java.lang.String", null));
}
public void testT68() {
doTestFirstParamType("foo", PsiType.INT, PsiType.DOUBLE);
}
public void testT69() {
doTestFirstParamType("foo", PsiType.INT, PsiType.BYTE);
}
public void testT70() {
doTestFieldType("a", PsiType.INT.createArrayType().createArrayType(), PsiType.FLOAT.createArrayType().createArrayType());
}
public void testT71() {
doTestFieldType("f",
myFactory.createTypeFromText(CommonClassNames.JAVA_LANG_CLASS, null),
myFactory.createTypeFromText("java.lang.Class<? extends java.lang.Number>", null));
}
public void testT72() {
doTestFieldType("f",
myFactory.createTypeFromText(CommonClassNames.JAVA_LANG_CLASS, null),
myFactory.createTypeFromText("java.lang.Class<java.lang.Integer>", null));
}
public void testT73() {
doTestFieldType("f",
myFactory.createTypeFromText("java.util.Set<javax.swing.JComponent>", null).createArrayType().createArrayType(),
myFactory.createTypeFromText("java.util.Set<java.awt.Component>", null).createArrayType().createArrayType());
}
//prefix/postfix expression; binary expressions 74-76
public void testT74() {
doTestFirstParamType("meth", PsiType.INT, PsiType.FLOAT);
}
public void testT75() {
doTestFirstParamType("meth", PsiType.INT, myFactory.createTypeFromText("java.lang.String", null));
}
public void testT76() {
doTestFirstParamType("meth", PsiType.BYTE, PsiType.FLOAT);
}
//+= , etc 77-78
public void testT77() {
doTestFirstParamType("meth", PsiType.INT, myFactory.createTypeFromText(CommonClassNames.JAVA_LANG_OBJECT, null));
}
public void testT78() {
doTestFirstParamType("meth", PsiType.INT, myFactory.createTypeFromText("java.lang.String", null));
}
//casts 79-80,83
public void testT79() {
doTestFirstParamType("meth", PsiType.INT, PsiType.BYTE);
}
public void testT80() {
doTestFirstParamType("meth", PsiType.INT, PsiType.DOUBLE);
}
public void testT83() {
doTestFirstParamType("meth", PsiType.INT, myFactory.createTypeFromText(CommonClassNames.JAVA_LANG_OBJECT, null));
}
//instanceofs 81-82
public void testT81() {
doTestFirstParamType("foo",
myFactory.createTypeFromText(CommonClassNames.JAVA_LANG_OBJECT, null),
myFactory.createTypeFromText("A", null));
}
public void testT82() {
doTestFirstParamType("foo",
myFactory.createTypeFromText(CommonClassNames.JAVA_LANG_OBJECT, null),
myFactory.createTypeFromText("C", null));
}
public void testT84() {
doTestFirstParamType("meth",
myFactory.createTypeFromText(CommonClassNames.JAVA_UTIL_SET, null),
myFactory.createTypeFromText("java.util.Set<? extends java.util.Set>", null));
}
public void testT85() {
doTestFieldType("str",
myFactory.createTypeFromText("java.lang.String", null),
myFactory.createTypeFromText("java.lang.Integer", null));
}
//array <-> list 86-89;94;95
public void testT86() {
doTestMethodType("getArray",
myFactory.createTypeFromText("java.lang.String", null).createArrayType(),
myFactory.createTypeFromText("java.util.List<java.lang.String>", null));
}
public void testT87() {
doTestMethodType("getArray",
myFactory.createTypeFromText("java.util.List<java.lang.String>", null),
myFactory.createTypeFromText("java.lang.String", null).createArrayType());
}
public void testT88() {
doTestMethodType("getArray",
myFactory.createTypeFromText("java.lang.String", null).createArrayType(),
myFactory.createTypeFromText("java.util.List<java.lang.String>", null));
}
public void testT89() {
doTestMethodType("getArray",
myFactory.createTypeFromText("java.util.List<java.lang.String>", null),
myFactory.createTypeFromText("java.lang.String", null).createArrayType());
}
public void testT94() {
doTestMethodType("getArray",
myFactory.createTypeFromText("java.util.List<java.lang.String>", null),
myFactory.createTypeFromText("java.lang.String", null).createArrayType());
}
public void testT95() {
doTestMethodType("getArray",
myFactory.createTypeFromText("java.lang.String", null).createArrayType(),
myFactory.createTypeFromText("java.util.List<java.lang.String>", null));
}
public void testT90() {
doTestFieldType("l",
myFactory.createTypeFromText("java.util.List<B>", null),
myFactory.createTypeFromText("java.util.List<A>", null));
}
//element type -> element type array
public void testT91() {
doTestMethodType("foo",
myFactory.createTypeFromText("java.lang.String", null),
myFactory.createTypeFromText("java.lang.String", null).createArrayType());
}
//List<S>=new ArrayList<S>{}; -> List<I>=new ArrayList<I>{}; anonymous
public void testT92() {
doTestFieldType("f",
myFactory.createTypeFromText("java.util.List<java.lang.String>", null),
myFactory.createTypeFromText("java.util.List<java.lang.Integer>", null));
}
//generics signature do not support primitives: Map<Boolean, String> - Map<boolean, String>
public void testT93() {
doTestFirstParamType("foo", myFactory.createTypeFromText("java.lang.Boolean", null), PsiType.BOOLEAN);
}
//field initializers procession
public void testT96() {
doTestFieldType("f1",
myFactory.createTypeFromText("java.lang.Integer", null),
myFactory.createTypeFromText("java.lang.String", null));
}
public void testT97() {
doTestFieldType("f1", myFactory.createTypeFromText("java.lang.Integer", null).createArrayType(), PsiType.INT);
}
//list <-> array conversion in assignment statements
public void testT98() {
doTestMethodType("getArray",
myFactory.createTypeFromText("java.lang.String", null).createArrayType(),
myFactory.createTypeFromText("java.util.List<java.lang.String>", null));
}
//escape pattern from []
public void testT99() {
doTestFieldType("f",
myFactory.createTypeFromText("java.util.Set<java.util.List<char[]>>", null),
myFactory.createTypeFromText("java.util.Set<java.util.List<int[]>>", null));
}
//non formatted type
public void testT100() {
doTestFieldType("f",
myFactory.createTypeFromText("java.util.Map<java.lang.String,java.lang.String>", null),
myFactory.createTypeFromText("java.util.Map<java.lang.String,java.lang.Integer>", null));
}
//param List -> Array[]
public void testT101() {
doTestFirstParamType("meth",
myFactory.createTypeFromText("java.util.List<java.util.ArrayList<java.lang.Integer>>", null),
myFactory.createTypeFromText("java.util.ArrayList<java.lang.Integer>[]", null));
}
//param Set.add() -> Array[] with conflict
public void testT102() {
doTestFirstParamType("method",
myFactory.createTypeFromText("java.util.Set<? extends java.lang.Object>", null),
myFactory.createTypeFromText("java.lang.Object[]", null));
}
//set(1, "") should be assignment-checked over String
public void testT103() {
doTestFirstParamType("method",
myFactory.createTypeFromText("java.util.ArrayList<java.lang.String>", null),
myFactory.createTypeFromText("java.lang.Integer", null).createArrayType());
}
//raw list type now should not be changed
public void testT104() {
doTestFirstParamType("method",
myFactory.createTypeFromText("java.util.ArrayList", null),
myFactory.createTypeFromText("java.lang.String", null).createArrayType());
}
//implicit type parameter change 105-107
public void testT105() {
doTestFieldType("t",
myFactory.createTypeFromText("T", null),
myFactory.createTypeFromText("java.lang.String", null));
}
public void testT106() {
doTestFieldType("t",
myFactory.createTypeFromText("T", null),
myFactory.createTypeFromText("java.lang.String", null));
}
public void testT107() {
doTestFieldType("t",
myFactory.createTypeFromText("T", null),
myFactory.createTypeFromText("java.lang.Integer", null));
}
//foreach && wildcards: 108-110
public void testT108() {
doTestFirstParamType("method",
myFactory.createTypeFromText("java.util.List<java.lang.Integer>", null),
myFactory.createTypeFromText("java.util.List<? extends java.lang.Number>", null));
}
public void testT109() {
doTestFirstParamType("method",
myFactory.createTypeFromText("java.util.List<java.lang.Integer>", null),
myFactory.createTypeFromText("java.util.List<? super java.lang.Number>", null));
}
public void testT110() {
doTestFirstParamType("method",
myFactory.createTypeFromText("java.util.List<java.lang.Integer>", null),
myFactory.createTypeFromText("java.util.List<? extends java.lang.String>", null));
}
//wrap with array creation only literals and refs outside of binary/unary expressions
public void testT111() {
doTestFirstParamType("method",
myFactory.createTypeFromText("java.lang.Integer", null),
myFactory.createTypeFromText("java.lang.Integer", null).createArrayType());
}
public void testT112() {
doTestMethodType("method",
myFactory.createTypeFromText("java.lang.Integer", null),
myFactory.createTypeFromText("java.lang.Integer", null).createArrayType());
}
//varargs
public void testT113() {
doTestFirstParamType("method",
new PsiEllipsisType(myFactory.createTypeFromText("java.lang.Integer", null)),
new PsiEllipsisType(myFactory.createTypeFromText("java.lang.Number", null)));
}
public void testT114() {
doTestFirstParamType("method",
new PsiEllipsisType(myFactory.createTypeFromText("java.lang.Integer", null)),
new PsiEllipsisType(myFactory.createTypeFromText("java.lang.String", null)));
}
//varargs && ArrayList
public void testT118() {
doTestFirstParamType("method",
myFactory.createTypeFromText("java.lang.Integer", null),
new PsiEllipsisType(myFactory.createTypeFromText("java.lang.Integer", null)));
}
//varargs && arrays
public void testT119() {
doTestFirstParamType("method",
myFactory.createTypeFromText("java.lang.Integer", null),
new PsiEllipsisType(myFactory.createTypeFromText("java.lang.Integer", null)));
}
public void testT120() {
doTestFirstParamType("method",
myFactory.createTypeFromText("java.lang.Integer", null),
new PsiEllipsisType(myFactory.createTypeFromText("java.lang.String", null)));
}
//change parameter type in foreach statement: 116 - array, 117 - list
public void testT116() {
doTestFieldType("str",
myFactory.createTypeFromText("java.lang.Number", null),
myFactory.createTypeFromText("java.lang.String", null));
}
public void testT117() {
doTestFieldType("str",
myFactory.createTypeFromText("java.lang.Number", null),
myFactory.createTypeFromText("java.lang.String", null));
}
public void testT121() {
doTestFirstParamType("method",
myFactory.createTypeFromText("java.util.ArrayList<java.lang.Number>", null),
myFactory.createTypeFromText("java.util.ArrayList<java.lang.Float>", null));
}
public void testT122() {
doTestFirstParamType("method",
myFactory.createTypeFromText("java.util.List<java.util.ArrayList<java.lang.Integer>>", null),
myFactory.createTypeFromText("java.util.List<java.lang.Integer>", null).createArrayType());
}
public void testT123() {
doTestFieldType("n",
myFactory.createTypeFromText("java.lang.Number", null),
myFactory.createTypeFromText("java.lang.Integer", null));
}
//124,125 - do not change formal method return type
public void testT124() {
doTestFirstParamType("meth",
myFactory.createTypeFromText("T", null),
myFactory.createTypeFromText("java.lang.Integer", null));
}
public void testT125() {
doTestFirstParamType("meth",
myFactory.createTypeFromText("T", null),
myFactory.createTypeFromText("java.lang.Integer", null));
}
public void testT126() {
doTestMethodType("meth",
myFactory.createTypeFromText("java.lang.String", null),
myFactory.createTypeFromText("T", null));
}
// Checking preserving method parameters alignment
public void testT127() {
getCurrentCodeStyleSettings().ALIGN_MULTILINE_PARAMETERS = true;
getCurrentCodeStyleSettings().ALIGN_MULTILINE_PARAMETERS_IN_CALLS = true;
doTestMethodType("test234",
myFactory.createTypeFromText("int", null),
myFactory.createTypeFromText("long", null));
}
// test type migration from disjunction type
public void testT128() {
doTestCatchParameter(myFactory.createTypeFromText("Test.E1 | Test.E2", null),
myFactory.createTypeFromText("Test.E", null));
}
// test type migration to disjunction type
public void testT129() {
doTestCatchParameter(myFactory.createTypeFromText("Test.E", null),
myFactory.createTypeFromText("Test.E1 | Test.E2", null));
}
// test type migration from disjunction type with interfaces
public void testT130() {
doTestCatchParameter(myFactory.createTypeFromText("Test.E1 | Test.E2", null),
myFactory.createTypeFromText("Test.E", null));
}
// test type migration between disjunction types
public void testT131() {
doTestCatchParameter(myFactory.createTypeFromText("Test.E1 | Test.E2", null),
myFactory.createTypeFromText("Test.E2 | Test.E1", null));
}
private void doTestCatchParameter(final PsiType rootType, final PsiType migrationType) {
start(new RulesProvider() {
@Override
public TypeMigrationRules provide() {
final TypeMigrationRules rules = new TypeMigrationRules(rootType);
rules.setMigrationRootType(migrationType);
return rules;
}
@Override
public PsiElement victims(final PsiClass aClass) {
final PsiCatchSection catchSection = PsiTreeUtil.findChildOfType(aClass, PsiCatchSection.class);
assert catchSection != null : aClass.getText();
final PsiParameter parameter = catchSection.getParameter();
assert parameter != null : catchSection.getText();
return parameter;
}
});
}
// IDEA-72420
public void testT132() {
doTestFirstParamType("h", "Test",
myFactory.createTypeFromText("J", null),
myFactory.createTypeFromText("I", null));
}
public void testT133() {
doTestFirstParamType("h", "Test",
myFactory.createTypeFromText("J", null),
myFactory.createTypeFromText("I", null));
}
public void testT134() {
doTestFirstParamType("buzz", "Test",
PsiType.INT,
myFactory.createTypeFromText("java.lang.String", null));
}
public void testT135() {
doTestFieldType("foo", "Test", PsiType.LONG, PsiType.INT);
}
public void testT136() {
final GlobalSearchScope scope = GlobalSearchScope.allScope(myProject);
doTestFirstParamType("foo", "Test",
myFactory.createTypeByFQClassName(CommonClassNames.JAVA_LANG_INTEGER, scope),
PsiType.getJavaLangString(myPsiManager, scope));
}
public void testT137() {
doTestFirstParamType("foo", "Test", PsiType.INT, myFactory.createTypeFromText("java.lang.String", null));
}
public void testT138() {
doTestFirstParamType("foo", "Test",
myFactory.createTypeFromText("java.util.Set<java.lang.String>", null),
myFactory.createTypeFromText("java.util.Collection<java.lang.String>", null));
}
public void testT139() {
doTestForeachParameter(myFactory.createTypeFromText("java.lang.String", null),
myFactory.createTypeFromText("java.lang.Integer", null));
}
private void doTestForeachParameter(final PsiType rootType, final PsiType migrationType) {
start(new RulesProvider() {
@Override
public TypeMigrationRules provide() {
final TypeMigrationRules rules = new TypeMigrationRules(rootType);
rules.setMigrationRootType(migrationType);
return rules;
}
@Override
public PsiElement victims(final PsiClass aClass) {
final PsiForeachStatement foreachStatement = PsiTreeUtil.findChildOfType(aClass, PsiForeachStatement.class);
assert foreachStatement != null : aClass.getText();
return foreachStatement.getIterationParameter();
}
});
}
public void testTypeAnno() {
doTestFieldType("list", "Test",
myFactory.createTypeFromText("java.util.ArrayList<java.lang.@TA Integer>", null),
myFactory.createTypeFromText("java.util.Collection<java.lang.@TA Integer>", null));
}
}
@@ -0,0 +1,193 @@
package com.intellij.refactoring;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiField;
import com.intellij.psi.PsiType;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.LocalSearchScope;
import com.intellij.refactoring.typeMigration.TypeMigrationProcessor;
import com.intellij.refactoring.typeMigration.TypeMigrationRules;
import com.intellij.testFramework.PlatformTestUtil;
import com.intellij.usageView.UsageInfo;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintWriter;
/**
* @author anna
* Date: 30-Apr-2008
*/
public abstract class TypeMigrationTestBase extends MultiFileTestCase {
@Override
protected String getTestDataPath() {
return PlatformTestUtil.getCommunityPath() + "/java/typeMigration/testData";
}
protected void doTestFieldType(@NonNls String fieldName, PsiType fromType, PsiType toType) {
doTestFieldType(fieldName, "Test", fromType, toType);
}
protected void doTestFieldType(@NonNls final String fieldName, String className, final PsiType rootType, final PsiType migrationType) {
final RulesProvider provider = new RulesProvider() {
@Override
public TypeMigrationRules provide() throws Exception {
final TypeMigrationRules rules = new TypeMigrationRules(rootType);
rules.setMigrationRootType(migrationType);
return rules;
}
@Override
public PsiElement victims(PsiClass aClass) {
final PsiField field = aClass.findFieldByName(fieldName, false);
assert field != null : fieldName + " not found in " + aClass;
return field;
}
};
start(provider, className);
}
protected void doTestMethodType(@NonNls final String methodName, final PsiType rootType, final PsiType migrationType) {
doTestMethodType(methodName, "Test", rootType, migrationType);
}
protected void doTestMethodType(@NonNls final String methodName, @NonNls String className, final PsiType rootType, final PsiType migrationType) {
final RulesProvider provider = new RulesProvider() {
@Override
public TypeMigrationRules provide() throws Exception {
final TypeMigrationRules rules = new TypeMigrationRules(rootType);
rules.setMigrationRootType(migrationType);
return rules;
}
@Override
public PsiElement victims(PsiClass aClass) {
return aClass.findMethodsByName(methodName, false)[0];
}
};
start(provider, className);
}
protected void doTestFirstParamType(@NonNls final String methodName, final PsiType rootType, final PsiType migrationType) {
doTestFirstParamType(methodName, "Test", rootType, migrationType);
}
protected void doTestFirstParamType(@NonNls final String methodName, String className, final PsiType rootType, final PsiType migrationType) {
final RulesProvider provider = new RulesProvider() {
@Override
public TypeMigrationRules provide() throws Exception {
final TypeMigrationRules rules = new TypeMigrationRules(rootType);
rules.setMigrationRootType(migrationType);
return rules;
}
@Override
public PsiElement victims(PsiClass aClass) {
return aClass.findMethodsByName(methodName, false)[0].getParameterList().getParameters()[0];
}
};
start(provider, className);
}
public void start(final RulesProvider provider) {
start(provider, "Test");
}
public void start(final RulesProvider provider, final String className) {
doTest(new PerformAction() {
@Override
public void performAction(VirtualFile rootDir, VirtualFile rootAfter) throws Exception {
TypeMigrationTestBase.this.performAction(className, rootDir.getName(), provider);
}
});
}
private void performAction(String className, String rootDir, RulesProvider provider) throws Exception {
PsiClass aClass = myJavaFacade.findClass(className, GlobalSearchScope.allScope(getProject()));
assertNotNull("Class " + className + " not found", aClass);
final TypeMigrationRules rules = provider.provide();
rules.setBoundScope(new LocalSearchScope(aClass.getContainingFile()));
final TestTypeMigrationProcessor pr = new TestTypeMigrationProcessor(getProject(), provider.victims(aClass), rules);
final UsageInfo[] usages = pr.findUsages();
final String report = pr.getLabeler().getMigrationReport();
WriteCommandAction.runWriteCommandAction(null, new Runnable() {
public void run() {
pr.performRefactoring(usages);
}
});
String itemName = className + ".items";
String patternName = getTestDataPath() + getTestRoot() + getTestName(true) + "/after/" + itemName;
File patternFile = new File(patternName);
if (!patternFile.exists()) {
PrintWriter writer = new PrintWriter(new FileOutputStream(patternFile));
try {
writer.print(report);
writer.close();
}
finally {
writer.close();
}
System.out.println("Pattern not found, file " + patternName + " created.");
LocalFileSystem.getInstance().refreshAndFindFileByIoFile(patternFile);
}
File graFile = new File(FileUtil.getTempDirectory() + File.separator + rootDir + File.separator + itemName);
PrintWriter writer = new PrintWriter(new FileOutputStream(graFile));
try {
writer.print(report);
writer.close();
}
finally {
writer.close();
}
LocalFileSystem.getInstance().refreshAndFindFileByIoFile(graFile);
FileDocumentManager.getInstance().saveAllDocuments();
}
interface RulesProvider {
TypeMigrationRules provide() throws Exception;
PsiElement victims(PsiClass aClass);
}
private static class TestTypeMigrationProcessor extends TypeMigrationProcessor {
public TestTypeMigrationProcessor(final Project project, final PsiElement root, final TypeMigrationRules rules) {
super(project, root, rules);
}
@NotNull
@Override
public UsageInfo[] findUsages() {
return super.findUsages();
}
@Override
public void performRefactoring(final UsageInfo[] usages) {
super.performRefactoring(usages);
}
}
}
@@ -0,0 +1,170 @@
/*
* User: anna
* Date: 19-Aug-2009
*/
package com.intellij.refactoring;
import com.intellij.psi.CommonClassNames;
import org.jetbrains.annotations.NotNull;
public class WildcardTypeMigrationTest extends TypeMigrationTestBase{
@NotNull
@Override
protected String getTestRoot() {
return "/refactoring/wildcard/";
}
public void testProducerExtends() throws Exception {
doTestFirstParamType("method",
myJavaFacade.getElementFactory().createTypeFromText("java.util.ArrayList<? super java.lang.Number>", null),
myJavaFacade.getElementFactory().createTypeFromText("java.util.ArrayList<? extends java.lang.Number>", null));
}
public void testProducerSuper() throws Exception {
doTestFirstParamType("method",
myJavaFacade.getElementFactory().createTypeFromText("java.util.ArrayList<? super java.lang.Number>", null),
myJavaFacade.getElementFactory().createTypeFromText("java.util.ArrayList<? super java.lang.Integer>", null));
}
public void testProducerUnbounded() throws Exception {
doTestFirstParamType("method",
myJavaFacade.getElementFactory().createTypeFromText("java.util.ArrayList<? super java.lang.Number>", null),
myJavaFacade.getElementFactory().createTypeFromText("java.util.ArrayList<?>", null));
}
public void testProducerCollectionChanged() throws Exception {
doTestFirstParamType("method",
myJavaFacade.getElementFactory().createTypeFromText("java.util.ArrayList<? super java.lang.Number>", null),
myJavaFacade.getElementFactory().createTypeFromText("java.util.Set<? super java.lang.Integer>", null));
}
public void testProducerExtendsCollectionChanged() throws Exception {
doTestFirstParamType("method",
myJavaFacade.getElementFactory().createTypeFromText("java.util.ArrayList<? super java.lang.Number>", null),
myJavaFacade.getElementFactory().createTypeFromText("java.util.Set<? extends java.lang.Object>", null));
}
public void testProducerStopAtWildcard() throws Exception {
doTestFirstParamType("method",
myJavaFacade.getElementFactory().createTypeFromText("java.util.List<java.lang.Number>", null),
myJavaFacade.getElementFactory().createTypeFromText("java.util.List<? super java.lang.Number>", null));
}
public void testProducerFailToStopAtWildcard() throws Exception {
doTestFirstParamType("method",
myJavaFacade.getElementFactory().createTypeFromText("java.util.List<? super java.lang.Number>", null),
myJavaFacade.getElementFactory().createTypeFromText("java.util.List<? super java.lang.Integer>", null));
}
public void testProducerExtendsFailToStopAtWildcard() throws Exception {
doTestFirstParamType("method",
myJavaFacade.getElementFactory().createTypeFromText("java.util.List<? super java.lang.Number>", null),
myJavaFacade.getElementFactory().createTypeFromText("java.util.List<? extends java.lang.Number>", null));
}
public void testConsumerExtends() throws Exception {
doTestFirstParamType("method",
myJavaFacade.getElementFactory().createTypeFromText("java.util.ArrayList<java.lang.Number>", null),
myJavaFacade.getElementFactory().createTypeFromText("java.util.ArrayList<? extends java.lang.Number>", null));
}
public void testConsumerSuper() throws Exception {
doTestFirstParamType("method",
myJavaFacade.getElementFactory().createTypeFromText("java.util.ArrayList<java.lang.Number>", null),
myJavaFacade.getElementFactory().createTypeFromText("java.util.ArrayList<? super java.lang.Number>", null));
}
public void testConsumerUnbounded() throws Exception {
doTestFirstParamType("method",
myJavaFacade.getElementFactory().createTypeFromText("java.util.ArrayList<java.lang.Number>", null),
myJavaFacade.getElementFactory().createTypeFromText("java.util.ArrayList<?>", null));
}
// array -> list
public void testAssignmentExtends() throws Exception {
doTestFirstParamType("method",
myJavaFacade.getElementFactory().createTypeFromText("java.lang.Integer", null).createArrayType(),
myJavaFacade.getElementFactory().createTypeFromText("java.util.ArrayList<? extends java.lang.Integer>", null));
}
public void testAssignmentSuper() throws Exception {
doTestFirstParamType("method",
myJavaFacade.getElementFactory().createTypeFromText("java.lang.Integer", null).createArrayType(),
myJavaFacade.getElementFactory().createTypeFromText("java.util.ArrayList<? super java.lang.Integer>", null));
}
public void testAssignmentUnbounded() throws Exception {
doTestFirstParamType("method",
myJavaFacade.getElementFactory().createTypeFromText("java.lang.Integer", null).createArrayType(),
myJavaFacade.getElementFactory().createTypeFromText("java.util.ArrayList<?>", null));
}
public void testGetExtends() throws Exception {
doTestFirstParamType("method",
myJavaFacade.getElementFactory().createTypeFromText("java.lang.Integer", null).createArrayType(),
myJavaFacade.getElementFactory().createTypeFromText("java.util.ArrayList<? extends java.lang.Integer>", null));
}
public void testGetSuper() throws Exception {
doTestFirstParamType("method",
myJavaFacade.getElementFactory().createTypeFromText("java.lang.Integer", null).createArrayType(),
myJavaFacade.getElementFactory().createTypeFromText("java.util.ArrayList<? super java.lang.Integer>", null));
}
public void testGetUnbounded() throws Exception {
doTestFirstParamType("method",
myJavaFacade.getElementFactory().createTypeFromText("java.lang.Integer", null).createArrayType(),
myJavaFacade.getElementFactory().createTypeFromText("java.util.ArrayList<?>", null));
}
public void testLengthSize() throws Exception {
doTestFirstParamType("method",
myJavaFacade.getElementFactory().createTypeFromText("java.lang.Integer", null).createArrayType(),
myJavaFacade.getElementFactory().createTypeFromText("java.util.ArrayList<?>", null));
}
//list -> array
public void testGetAssignmentExtendsToType() throws Exception {
doTestFirstParamType("method", myJavaFacade.getElementFactory().createTypeFromText("java.util.ArrayList<? extends java.lang.Number>", null),
myJavaFacade.getElementFactory().createTypeFromText("java.lang.Number", null).createArrayType());
}
public void testGetAssignmentExtendsToSuperType() throws Exception {
doTestFirstParamType("method", myJavaFacade.getElementFactory().createTypeFromText("java.util.ArrayList<? extends java.lang.Number>", null),
myJavaFacade.getElementFactory().createTypeFromText(CommonClassNames.JAVA_LANG_OBJECT, null).createArrayType());
}
public void testGetAssignmentExtendsToChildType() throws Exception {
doTestFirstParamType("method", myJavaFacade.getElementFactory().createTypeFromText("java.util.ArrayList<? extends java.lang.Number>", null),
myJavaFacade.getElementFactory().createTypeFromText("java.lang.Integer", null).createArrayType());
}
// -> threadlocal with wildcard
public void testThreadLocalProducerExtends() throws Exception {
doTestFirstParamType("method",
myJavaFacade.getElementFactory().createTypeFromText("java.util.List<java.lang.String>", null),
myJavaFacade.getElementFactory().createTypeFromText("java.lang.ThreadLocal<java.util.List<? extends String>>", null));
}
//List<? super String> is not assignable to List<String> though it is possible to pass string where ? super String was
public void _testThreadLocalProducerSuper() throws Exception {
doTestFirstParamType("method",
myJavaFacade.getElementFactory().createTypeFromText("java.util.List<java.lang.String>", null),
myJavaFacade.getElementFactory().createTypeFromText("java.lang.ThreadLocal<java.util.List<? super String>>", null));
}
public void testThreadLocalConsumerSuper() throws Exception {
doTestFirstParamType("method",
myJavaFacade.getElementFactory().createTypeFromText("java.lang.String", null),
myJavaFacade.getElementFactory().createTypeFromText("java.lang.ThreadLocal<? super String>", null));
}
public void testThreadLocalConsumerExtends() throws Exception {
doTestFirstParamType("method",
myJavaFacade.getElementFactory().createTypeFromText("java.lang.String", null),
myJavaFacade.getElementFactory().createTypeFromText("java.lang.ThreadLocal<? extends String>", null));
}
}
@@ -0,0 +1,9 @@
import java.util.concurrent.atomic.AtomicIntegerArray;
// "Convert to atomic" "true"
class Test {
final AtomicIntegerArray field= new AtomicIntegerArray(foo());
int[] foo() {
return null;
}
}
@@ -0,0 +1,10 @@
import java.util.concurrent.atomic.AtomicInteger;
// "Convert to atomic" "true"
class Test {
final AtomicInteger o = new AtomicInteger(0);
void foo() {
boolean b = this.o.get() == 1;
}
}
@@ -0,0 +1,12 @@
import java.util.concurrent.atomic.AtomicInteger;
// "Convert to atomic" "true"
class Test {
{
AtomicInteger i = new AtomicInteger(0);
Integer j = 0;
assert j == i.get();
}
}
@@ -0,0 +1,6 @@
import java.util.concurrent.atomic.AtomicInteger;
// "Convert to atomic" "true"
class Test {
final AtomicInteger i = new AtomicInteger(0);
}
@@ -0,0 +1,10 @@
import java.util.concurrent.atomic.AtomicLong;
// "Convert to atomic" "true"
class T {
private final AtomicLong l = new AtomicLong(10L);
public synchronized void update(long m) {
l.set(m);
}
}
@@ -0,0 +1,9 @@
import java.util.concurrent.atomic.AtomicReferenceArray;
// "Convert to atomic" "true"
class Test {
final AtomicReferenceArray<Object> field= new AtomicReferenceArray<>(foo());
Object[] foo() {
return null;
}
}
@@ -0,0 +1,7 @@
import java.util.concurrent.atomic.AtomicIntegerArray;
// "Convert to atomic" "true"
class Test {
final AtomicIntegerArray field= new AtomicIntegerArray(new int[]{1});
}
@@ -0,0 +1,9 @@
import java.util.concurrent.atomic.AtomicInteger;
// "Convert to atomic" "true"
class Test {
final AtomicInteger i = new AtomicInteger(0);
int j = i.get() + 5;
String s = "i = " + i.get();
}
@@ -0,0 +1,9 @@
import java.util.concurrent.atomic.AtomicInteger;
// "Convert to atomic" "true"
class Test {
final AtomicInteger i = new AtomicInteger(0 + 8);
int j = i.get() + 5;
String s = "i = " + i.get();
}
@@ -0,0 +1,6 @@
import java.util.concurrent.atomic.AtomicIntegerArray;
// "Convert to atomic" "true"
class Test {
final AtomicIntegerArray i = new AtomicIntegerArray(new int[0]);
}
@@ -0,0 +1,11 @@
import java.util.concurrent.atomic.AtomicInteger;
// "Convert to atomic" "true"
class Test {
final AtomicInteger o = new AtomicInteger(0);
int j = o.get();
void foo() {
while ((o = j) != 0) {}
}
}
@@ -0,0 +1,11 @@
import java.util.concurrent.atomic.AtomicInteger;
// "Convert to atomic" "true"
class Test {
final AtomicInteger o = new AtomicInteger();
int j = o.get();
void foo() {
while ((o = j) != 0) {}
}
}
@@ -0,0 +1,15 @@
import java.util.concurrent.atomic.AtomicInteger;
// "Convert to atomic" "true"
class Test {
final AtomicInteger o;
int j = o.get();
Test(int o) {
this.o = new AtomicInteger(o);
}
void foo() {
while ((o = j) != 0) {}
}
}
@@ -0,0 +1,9 @@
import java.util.concurrent.atomic.AtomicBoolean;
// "Convert to atomic" "true"
class Test {
final AtomicBoolean field= new AtomicBoolean(false);
{
boolean b = !field.get();
}
}
@@ -0,0 +1,10 @@
// "Convert to atomic" "true"
import java.lang.annotation.*;
import java.util.concurrent.atomic.AtomicReference;
@Target(value = ElementType.TYPE_USE)
public @interface TA { int value(); }
class T {
final AtomicReference<@TA(42) String> v = new AtomicReference<String>();
}
@@ -0,0 +1,7 @@
// "Convert to atomic" "true"
class Test {
int[] <caret>field=foo();
int[] foo() {
return null;
}
}
@@ -0,0 +1,8 @@
// "Convert to atomic" "true"
class Test {
final int <caret>o = 0;
void foo() {
boolean b = this.o == 1;
}
}
@@ -0,0 +1,8 @@
// "Convert to atomic" "false"
class Test {
void foo() {
try (AutoCloseable <caret>r = null) {
System.out.println(r);
}
}
}
@@ -0,0 +1,10 @@
// "Convert to atomic" "true"
class Test {
{
int <caret>i = 0;
Integer j = 0;
assert j == i;
}
}
@@ -0,0 +1,4 @@
// "Convert to atomic" "true"
class Test {
volatile int <caret>i = 0;
}
@@ -0,0 +1,8 @@
// "Convert to atomic" "true"
class T {
private long <caret>l = 10L;
public synchronized void update(long m) {
l = m;
}
}
@@ -0,0 +1,7 @@
// "Convert to atomic" "true"
class Test {
Object[] <caret>field=foo();
Object[] foo() {
return null;
}
}
@@ -0,0 +1,5 @@
// "Convert to atomic" "true"
class Test {
int[] <caret>field= new int[]{1};
}
@@ -0,0 +1,7 @@
// "Convert to atomic" "true"
class Test {
int <caret>i = 0;
int j = i + 5;
String s = "i = " + i;
}
@@ -0,0 +1,7 @@
// "Convert to atomic" "true"
class Test {
int <caret>i = 0 + 8;
int j = i + 5;
String s = "i = " + i;
}
@@ -0,0 +1,4 @@
// "Convert to atomic" "true"
class Test {
int[] <caret>i = new int[0];
}
@@ -0,0 +1,9 @@
// "Convert to atomic" "true"
class Test {
int <caret>o = 0;
int j = o;
void foo() {
while ((o = j) != 0) {}
}
}
@@ -0,0 +1,9 @@
// "Convert to atomic" "true"
class Test {
int <caret>o;
int j = o;
void foo() {
while ((o = j) != 0) {}
}
}
@@ -0,0 +1,13 @@
// "Convert to atomic" "true"
class Test {
final int <caret>o;
int j = o;
Test(int o) {
this.o = o;
}
void foo() {
while ((o = j) != 0) {}
}
}
@@ -0,0 +1,7 @@
// "Convert to atomic" "true"
class Test {
boolean <caret>field=false;
{
boolean b = !field;
}
}
@@ -0,0 +1,9 @@
// "Convert to atomic" "true"
import java.lang.annotation.*;
@Target(value = ElementType.TYPE_USE)
public @interface TA { int value(); }
class T {
@TA(42) String <caret>v;
}
@@ -0,0 +1,12 @@
// "Convert to ThreadLocal" "true"
class Test {
final ThreadLocal<Integer> field = new ThreadLocal<Integer>() {
@Override
protected Integer initialValue() {
return 0;
}
};
void foo() {
field.set(field.get() + 1);
}
}
@@ -0,0 +1,12 @@
// "Convert to ThreadLocal" "true"
class Test {
final ThreadLocal<String> field = new ThreadLocal<String>() {
@Override
protected String initialValue() {
return "";
}
};
void foo() {
System.out.println(field.get());
}
}
@@ -0,0 +1,12 @@
// "Convert to ThreadLocal" "true"
class Test {
final ThreadLocal<Integer> field = new ThreadLocal<Integer>() {
@Override
protected Integer initialValue() {
return new Integer(0);
}
};
void foo() {
if (field.get() == null) return;
}
}
@@ -0,0 +1,12 @@
// "Convert to ThreadLocal" "true"
class Test {
final ThreadLocal<String> field = new ThreadLocal<String>() {
@Override
protected String initialValue() {
return "";
}
};
void foo() {
if (field.get().indexOf("a") == -1) return;
}
}
@@ -0,0 +1,12 @@
// "Convert to ThreadLocal" "true"
class Test {
final ThreadLocal<Integer> field = new ThreadLocal<Integer>() {
@Override
protected Integer initialValue() {
return new Integer(0);
}
};
void foo(Test t) {
if (t.field.get() == null) return;
}
}
@@ -0,0 +1,12 @@
// "Convert to ThreadLocal" "true"
class Test {
static final ThreadLocal<Integer> field;
static {
field = new ThreadLocal<Integer>() {
@Override
protected Integer initialValue() {
return new Integer(0);
}
};
}
}
@@ -0,0 +1,15 @@
// "Convert to ThreadLocal" "true"
class X {
private final ThreadLocal<byte[]> bytes = new ThreadLocal<byte[]>() {
@Override
protected byte[] initialValue() {
return new byte[10];
}
};
byte foo(byte b) {
bytes.get()[0] = 1;
foo(bytes.get()[1])
return bytes.get()[2];
}
}
@@ -0,0 +1,9 @@
// "Convert to ThreadLocal" "true"
class X {
final ThreadLocal<Integer> i = new ThreadLocal<Integer>() {
@Override
protected Integer initialValue() {
return 0;
}
};
}
@@ -0,0 +1,14 @@
// "Convert to ThreadLocal" "true"
import java.lang.annotation.*;
@Target(value = ElementType.TYPE_USE)
public @interface TA { int value(); }
class Test {
final ThreadLocal<@TA(42) Integer> field = new ThreadLocal<Integer>() {
@Override
protected Integer initialValue() {
return 0;
}
};
}
@@ -0,0 +1,7 @@
// "Convert to ThreadLocal" "true"
class Test {
int <caret>field=0;
void foo() {
field++;
}
}
@@ -0,0 +1,7 @@
// "Convert to ThreadLocal" "true"
class Test {
String <caret>field="";
void foo() {
System.out.println(field);
}
}
@@ -0,0 +1,7 @@
// "Convert to ThreadLocal" "true"
class Test {
Integer <caret>field=new Integer(0);
void foo() {
if (field == null) return;
}
}
@@ -0,0 +1,7 @@
// "Convert to ThreadLocal" "true"
class Test {
String <caret>field="";
void foo() {
if (field.indexOf("a") == -1) return;
}
}
@@ -0,0 +1,7 @@
// "Convert to ThreadLocal" "true"
class Test {
Integer <caret>field=new Integer(0);
void foo(Test t) {
if (t.field == null) return;
}
}
@@ -0,0 +1,7 @@
// "Convert to ThreadLocal" "true"
class Test {
static final Integer <caret>field;
static {
field = new Integer(0);
}
}
@@ -0,0 +1,10 @@
// "Convert to ThreadLocal" "true"
class X {
private final byte[] <caret>bytes = new byte[10];
byte foo(byte b) {
bytes[0] = 1;
foo(bytes[1])
return bytes[2];
}
}
@@ -0,0 +1,4 @@
// "Convert to ThreadLocal" "true"
class X {
volatile int <caret>i = 0;
}
@@ -0,0 +1,9 @@
// "Convert to ThreadLocal" "true"
import java.lang.annotation.*;
@Target(value = ElementType.TYPE_USE)
public @interface TA { int value(); }
class Test {
@TA(42) int <caret>field = 0;
}
@@ -0,0 +1,9 @@
import java.util.List;
class A<T> {
List<T> getKey(){return null;}
}
public class B extends A<S<caret>tring> {
List<String> getKey() {
return new List<String>();
}
}
@@ -0,0 +1,9 @@
import java.util.List;
class A<T> {
List<T> getKey(){return null;}
}
public class B extends A<Object> {
List<Object> getKey() {
return new List<>();
}
}
@@ -0,0 +1,12 @@
class Test {
interface A<T> {
void foo(T t);
}
class B implements A<Inte<caret>ger> {
Integer str;
public void foo(Integer s) {
str = s;
}
}
}
@@ -0,0 +1,12 @@
class Test {
interface A<T> {
void foo(T t);
}
class B implements A<String> {
String str;
public void foo(String s) {
str = s;
}
}
}
@@ -0,0 +1,16 @@
import java.util.List;
class A<T> {
T t;
List<T> list = new List<T>();
}
class B extends A<S<caret>tring> {
void foo() {
if (t == null) return;
if (list == null) return;
for (String s : list) {
//do nothing
}
}
}
@@ -0,0 +1,16 @@
import java.util.List;
class A<T> {
T t;
List<T> list = new List<T>();
}
class B extends A<Object> {
void foo() {
if (t == null) return;
if (list == null) return;
for (Object s : list) {
//do nothing
}
}
}
@@ -0,0 +1,17 @@
import java.util.*;
class A<T> {
protected T t;
protected List<T> list = new ArrayList<T>();
}
public class B extends A<S<caret>tring> {
void foo() {
if (t == null) return;
if (list == null) return;
System.out.println(t);
for (String s : list) {
//do nothing
}
}
}
@@ -0,0 +1,17 @@
import java.util.*;
class A<T> {
protected T t;
protected List<T> list = new ArrayList<T>();
}
public class B extends A<Object> {
void foo() {
if (t == null) return;
if (list == null) return;
System.out.println(t);
for (Object s : list) {
//do nothing
}
}
}
@@ -0,0 +1,4 @@
import java.util.List;
class ListTypeArguments implements List<I<caret>nteger> {
public boolean add(Integer o){return true;}
}
@@ -0,0 +1,4 @@
import java.util.List;
class ListTypeArguments implements List<Object> {
public boolean add(Object o){return true;}
}
@@ -0,0 +1,16 @@
class Test {
interface A<T> {
T foo();
}
class B implements A<Stri<caret>ng> {
public String foo() {
return null;
}
public void bar() {
String s = foo();
}
}
}
@@ -0,0 +1,16 @@
class Test {
interface A<T> {
T foo();
}
class B implements A<Integer> {
public Integer foo() {
return null;
}
public void bar() {
Integer s = foo();
}
}
}
@@ -0,0 +1,29 @@
import java.util.*;
class Test {
class C<T> {
List<T> l;
void bar(Map<T, T> t){}
void f(T t){}
}
class D extends C<Strin<caret>g> {
void foo(String s) {
f(s);
}
public void main() {
for (String integer : l) {
}
}
void bar(Map<String, String> t) {
super.bar(t);
}
}
}
@@ -0,0 +1,29 @@
import java.util.*;
class Test {
class C<T> {
List<T> l;
void bar(Map<T, T> t){}
void f(T t){}
}
class D extends C<Object> {
void foo(String s) {
f(s);
}
public void main() {
for (Object integer : l) {
}
}
void bar(Map<Object, Object> t) {
super.bar(t);
}
}
}
@@ -0,0 +1,29 @@
import java.util.*;
class Test {
class C<T> {
List<T> l;
void bar(Map<T, T> t){}
void f(T t){}
}
class D extends C<Strin<caret>g> {
void foo(String s) {
f(s);
}
public void main() {
for (String integer : l) {
}
}
void bar(Map<String, String> t) {
super.bar(t);
}
}
}
@@ -0,0 +1,29 @@
import java.util.*;
class Test {
class C<T> {
List<T> l;
void bar(Map<T, T> t){}
void f(T t){}
}
class D extends C<Integer> {
void foo(Integer s) {
f(s);
}
public void main() {
for (Integer integer : l) {
}
}
void bar(Map<Integer, Integer> t) {
super.bar(t);
}
}
}
@@ -0,0 +1,31 @@
import java.util.*;
class Test {
class C<T> {
List<T> l;
void bar(Map<T, T> t){
for (T t1 : t.keySet()) {}
}
void f(T t){}
}
class D extends C<Strin<caret>g> {
void foo(String s) {
f(s);
}
public void main() {
for (String integer : l) {
}
}
void bar(Map<String, String> t) {
super.bar(t);
}
}
}
@@ -0,0 +1,31 @@
import java.util.*;
class Test {
class C<T> {
List<T> l;
void bar(Map<T, T> t){
for (T t1 : t.keySet()) {}
}
void f(T t){}
}
class D extends C<Integer> {
void foo(Integer s) {
f(s);
}
public void main() {
for (Integer integer : l) {
}
}
void bar(Map<Integer, Integer> t) {
super.bar(t);
}
}
}
@@ -0,0 +1,16 @@
class A<T> {
void foo(T t){}
void bar(T t, int i){}
}
class B extends A<S<caret>tring>{
void foo(String t) {
super.foo(t);
}
void bar(String t, int i){
foo(t);
int k = i;
super.bar(t, k);
}
}
@@ -0,0 +1,16 @@
class A<T> {
void foo(T t){}
void bar(T t, int i){}
}
class B extends A<Object> {
void foo(Object t) {
super.foo(t);
}
void bar(Object t, int i){
foo(t);
int k = i;
super.bar(t, k);
}
}
@@ -0,0 +1,20 @@
class A<T> {
void foo(T t){}
void bar(T t, int i){}
}
class B extends A<S<caret>tring>{
void foo(String t) {
super.foo(t);
}
void bar(String t, int i){
foo(t);
int k = i;
super.bar(t, k);
}
void bar1(String s) {
foo(s);
}
}

Some files were not shown because too many files have changed in this diff Show More