| /* |
| * Copyright 2003-2011 Dave Griffith, Bas Leijdekkers |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package com.siyeh.ig.encapsulation; |
| |
| import com.intellij.codeInspection.ProblemDescriptor; |
| import com.intellij.openapi.project.Project; |
| import com.intellij.psi.*; |
| import com.intellij.psi.codeStyle.JavaCodeStyleManager; |
| import com.intellij.psi.util.InheritanceUtil; |
| import com.intellij.psi.util.PsiTreeUtil; |
| import com.intellij.util.IncorrectOperationException; |
| import com.siyeh.InspectionGadgetsBundle; |
| import com.siyeh.ig.InspectionGadgetsFix; |
| import com.siyeh.ig.PsiReplacementUtil; |
| import com.siyeh.ig.psiutils.HighlightUtils; |
| import com.siyeh.ig.psiutils.TypeUtils; |
| import org.jetbrains.annotations.NonNls; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| |
| public class ReturnOfCollectionFieldInspection extends ReturnOfCollectionFieldInspectionBase { |
| |
| @Override |
| @Nullable |
| protected InspectionGadgetsFix buildFix(Object... infos) { |
| final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)infos[1]; |
| final String text = referenceExpression.getText(); |
| if (TypeUtils.expressionHasTypeOrSubtype(referenceExpression, CommonClassNames.JAVA_UTIL_MAP)) { |
| if (TypeUtils.expressionHasTypeOrSubtype(referenceExpression, "java.util.SortedMap")) { |
| return new ReturnOfCollectionFieldFix("java.util.Collections.unmodifiableSortedMap(" + text + ')', "java.util.SortedMap"); |
| } |
| return new ReturnOfCollectionFieldFix("java.util.Collections.unmodifiableMap(" + text + ')', CommonClassNames.JAVA_UTIL_MAP); |
| } |
| else if (TypeUtils.expressionHasTypeOrSubtype(referenceExpression, CommonClassNames.JAVA_UTIL_COLLECTION)) { |
| if (TypeUtils.expressionHasTypeOrSubtype(referenceExpression, CommonClassNames.JAVA_UTIL_SET)) { |
| if (TypeUtils.expressionHasTypeOrSubtype(referenceExpression, "java.util.SortedSet")) { |
| return new ReturnOfCollectionFieldFix("java.util.Collections.unmodifiableSortedSet(" + text + ')', "java.util.SortedSet"); |
| } |
| return new ReturnOfCollectionFieldFix("java.util.Collections.unmodifiableSet(" + text + ')', CommonClassNames.JAVA_UTIL_SET); |
| } |
| else if (TypeUtils.expressionHasTypeOrSubtype(referenceExpression, CommonClassNames.JAVA_UTIL_LIST)) { |
| return new ReturnOfCollectionFieldFix("java.util.Collections.unmodifiableList(" + text + ')', CommonClassNames.JAVA_UTIL_LIST); |
| } |
| return new ReturnOfCollectionFieldFix("java.util.Collections.unmodifiableCollection(" + text + ')', "java.util.Collection"); |
| } |
| return null; |
| } |
| |
| private static class ReturnOfCollectionFieldFix extends InspectionGadgetsFix { |
| |
| private final String myReplacementText; |
| private final String myQualifiedClassName; |
| |
| ReturnOfCollectionFieldFix(@NonNls String replacementText, String qualifiedClassName) { |
| myReplacementText = replacementText; |
| myQualifiedClassName = qualifiedClassName; |
| } |
| |
| @NotNull |
| @Override |
| public String getFamilyName() { |
| return "Make return collection 'unmodifiable'"; |
| } |
| |
| @Override |
| @NotNull |
| public String getName() { |
| return InspectionGadgetsBundle.message( |
| "return.of.collection.field.quickfix", myReplacementText); |
| } |
| |
| @Override |
| protected void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException { |
| final PsiElement element = descriptor.getPsiElement(); |
| if (!(element instanceof PsiReferenceExpression)) { |
| return; |
| } |
| final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)element; |
| fixContainingMethodReturnType(referenceExpression); |
| PsiReplacementUtil.replaceExpressionAndShorten(referenceExpression, myReplacementText); |
| } |
| |
| private void fixContainingMethodReturnType(PsiReferenceExpression referenceExpression) { |
| final PsiMethod method = PsiTreeUtil.getParentOfType(referenceExpression, PsiMethod.class, true); |
| if (method == null) { |
| return; |
| } |
| final PsiTypeElement returnTypeElement = method.getReturnTypeElement(); |
| if (returnTypeElement == null) { |
| return; |
| } |
| final PsiType type = returnTypeElement.getType(); |
| if (!InheritanceUtil.isInheritor(type, myQualifiedClassName)) { |
| return; |
| } |
| if (!(type instanceof PsiClassType)) { |
| return; |
| } |
| final Project project = referenceExpression.getProject(); |
| final PsiClassType classType = (PsiClassType)type; |
| final PsiClass aClass = classType.resolve(); |
| if (aClass == null || myQualifiedClassName.equals(aClass.getQualifiedName())) { |
| return; |
| } |
| final PsiType[] parameters = classType.getParameters(); |
| final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project); |
| final String typeText; |
| if (parameters.length > 0) { |
| final StringBuilder builder = new StringBuilder(myQualifiedClassName); |
| builder.append('<'); |
| boolean comma = false; |
| for (PsiType parameter : parameters) { |
| if (comma) { |
| builder.append(','); |
| } else { |
| comma = true; |
| } |
| builder.append(parameter.getCanonicalText()); |
| } |
| builder.append('>'); |
| typeText = builder.toString(); |
| } else { |
| typeText = myQualifiedClassName; |
| } |
| final PsiTypeElement newTypeElement = factory.createTypeElementFromText(typeText, referenceExpression); |
| final PsiElement replacement = returnTypeElement.replace(newTypeElement); |
| final JavaCodeStyleManager javaCodeStyleManager = JavaCodeStyleManager.getInstance(project); |
| javaCodeStyleManager.shortenClassReferences(replacement); |
| HighlightUtils.highlightElement(replacement); |
| } |
| } |
| } |