blob: 91497a30334f94196348ee241916eb03a01a24f6 [file] [log] [blame]
/*
* Copyright 2000-2009 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Created by IntelliJ IDEA.
* User: dsl
* Date: Apr 15, 2002
* Time: 1:25:37 PM
* To change template for new class use
* Code Style | Class Templates options (Tools | IDE Options).
*/
package com.intellij.refactoring.makeStatic;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.codeStyle.VariableKind;
import com.intellij.psi.search.searches.MethodReferencesSearch;
import com.intellij.refactoring.HelpID;
import com.intellij.refactoring.RefactoringActionHandler;
import com.intellij.refactoring.RefactoringBundle;
import com.intellij.refactoring.util.CommonRefactoringUtil;
import com.intellij.util.Processor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class MakeStaticHandler implements RefactoringActionHandler {
public static final String REFACTORING_NAME = RefactoringBundle.message("make.method.static.title");
private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.makeMethodStatic.MakeMethodStaticHandler");
public void invoke(@NotNull Project project, Editor editor, PsiFile file, DataContext dataContext) {
PsiElement element = CommonDataKeys.PSI_ELEMENT.getData(dataContext);
editor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE);
if (element == null) {
element = file.findElementAt(editor.getCaretModel().getOffset());
}
if (element == null) return;
if (element instanceof PsiIdentifier) element = element.getParent();
if(!(element instanceof PsiTypeParameterListOwner)) {
String message = RefactoringBundle.getCannotRefactorMessage(RefactoringBundle.message("error.wrong.caret.position.method.or.class.name"));
CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HelpID.MAKE_METHOD_STATIC);
return;
}
if(LOG.isDebugEnabled()) {
LOG.debug("MakeStaticHandler invoked");
}
invoke(project, new PsiElement[]{element}, dataContext);
}
public void invoke(@NotNull final Project project, @NotNull PsiElement[] elements, DataContext dataContext) {
if(elements.length != 1 || !(elements[0] instanceof PsiTypeParameterListOwner)) return;
final PsiTypeParameterListOwner member = (PsiTypeParameterListOwner)elements[0];
if (!CommonRefactoringUtil.checkReadOnlyStatus(project, member)) return;
String error = validateTarget(member);
if (error != null) {
Editor editor = CommonDataKeys.EDITOR.getData(dataContext);
CommonRefactoringUtil.showErrorHint(project, editor, error, REFACTORING_NAME, HelpID.MAKE_METHOD_STATIC);
return;
}
invoke(member);
}
public static void invoke(final PsiTypeParameterListOwner member) {
final Project project = member.getProject();
final InternalUsageInfo[] classRefsInMember = MakeStaticUtil.findClassRefsInMember(member, false);
/*
String classParameterName = "anObject";
ParameterTablePanel.VariableData[] fieldParameterData = null;
*/
AbstractMakeStaticDialog dialog;
if (!ApplicationManager.getApplication().isUnitTestMode()) {
final boolean[] hasMethodReferenceOnInstance = new boolean[] {false};
if (member instanceof PsiMethod) {
if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
@Override
public void run() {
hasMethodReferenceOnInstance[0] = !MethodReferencesSearch.search((PsiMethod)member).forEach(new Processor<PsiReference>() {
@Override
public boolean process(PsiReference reference) {
final PsiElement element = reference.getElement();
if (element instanceof PsiMethodReferenceExpression) {
return false;
}
return true;
}
});
}
}, "Search for method references", true, project)) return;
}
if (classRefsInMember.length > 0 || hasMethodReferenceOnInstance[0]) {
final PsiType type = JavaPsiFacade.getInstance(project).getElementFactory().createType(member.getContainingClass());
//TODO: callback
String[] nameSuggestions =
JavaCodeStyleManager.getInstance(project).suggestVariableName(VariableKind.PARAMETER, null, null, type).names;
dialog = new MakeParameterizedStaticDialog(project, member,
nameSuggestions,
classRefsInMember);
}
else {
dialog = new SimpleMakeStaticDialog(project, member);
}
dialog.show();
}
}
@Nullable
public static String validateTarget(final PsiTypeParameterListOwner member) {
final PsiClass containingClass = member.getContainingClass();
// Checking various preconditions
if(member instanceof PsiMethod && ((PsiMethod)member).isConstructor()) {
return RefactoringBundle.getCannotRefactorMessage(RefactoringBundle.message("constructor.cannot.be.made.static"));
}
if(member.getContainingClass() == null) {
return RefactoringBundle.getCannotRefactorMessage(RefactoringBundle.message("this.member.does.not.seem.to.belong.to.any.class"));
}
if(member.hasModifierProperty(PsiModifier.STATIC)) {
return RefactoringBundle.getCannotRefactorMessage(RefactoringBundle.message("member.is.already.static"));
}
if(member instanceof PsiMethod && member.hasModifierProperty(PsiModifier.ABSTRACT)) {
return RefactoringBundle.getCannotRefactorMessage(RefactoringBundle.message("cannot.make.abstract.method.static"));
}
if(containingClass instanceof PsiAnonymousClass ||
(containingClass.getContainingClass() != null && !containingClass.hasModifierProperty(PsiModifier.STATIC))) {
return RefactoringBundle.getCannotRefactorMessage(RefactoringBundle.message("inner.classes.cannot.have.static.members"));
}
return null;
}
}