Skip to content

Commit

Permalink
fix write access
Browse files Browse the repository at this point in the history
  • Loading branch information
VISTALL committed Aug 11, 2024
1 parent 088e208 commit 621ecab
Showing 1 changed file with 138 additions and 153 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,8 @@
import com.intellij.java.language.impl.psi.impl.source.resolve.JavaResolveUtil;
import com.intellij.java.language.psi.*;
import com.intellij.java.language.psi.search.searches.SuperMethodsSearch;
import com.intellij.java.language.psi.util.MethodSignatureBackedByPsiMethod;
import com.siyeh.IntentionPowerPackBundle;
import consulo.application.AccessToken;
import consulo.application.WriteAction;
import consulo.application.util.function.Processor;
import consulo.application.util.query.Query;
import consulo.ide.impl.idea.openapi.util.io.FileUtil;
import consulo.language.editor.intention.LowPriorityAction;
Expand All @@ -49,170 +46,158 @@
*/
abstract class ModifierIntention extends Intention implements LowPriorityAction {

@Nonnull
@Override
protected final PsiElementPredicate getElementPredicate() {
return new ModifierPredicate(getModifier());
}
@Nonnull
@Override
protected final PsiElementPredicate getElementPredicate() {
return new ModifierPredicate(getModifier());
}

@Override
protected final void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException {
final PsiMember member = (PsiMember)element.getParent();
final PsiModifierList modifierList = member.getModifierList();
if (modifierList == null) {
return;
@Override
public boolean startInWriteAction() {
return false;
}
final MultiMap<PsiElement, String> conflicts = checkForConflicts(member);
final boolean conflictsDialogOK;
if (conflicts.isEmpty()) {
conflictsDialogOK = true;
} else {
final ConflictsDialog conflictsDialog = new ConflictsDialog(member.getProject(), conflicts, new Runnable() {
@Override
public void run() {
final AccessToken token = WriteAction.start();
try {
modifierList.setModifierProperty(getModifier(), true);
}
finally {
token.finish();
}

@Override
protected final void processIntention(@Nonnull PsiElement element) throws IncorrectOperationException {
final PsiMember member = (PsiMember) element.getParent();
final PsiModifierList modifierList = member.getModifierList();
if (modifierList == null) {
return;
}
final MultiMap<PsiElement, String> conflicts = checkForConflicts(member);
final boolean conflictsDialogOK;
if (conflicts.isEmpty()) {
conflictsDialogOK = true;
}
else {
final ConflictsDialog conflictsDialog = new ConflictsDialog(member.getProject(), conflicts, () -> {
WriteAction.run(() -> modifierList.setModifierProperty(getModifier(), true));
});
conflictsDialog.show();
conflictsDialogOK = conflictsDialog.isOK();
}
});
conflictsDialog.show();
conflictsDialogOK = conflictsDialog.isOK();
}
if (conflictsDialogOK) {
modifierList.setModifierProperty(getModifier(), true);
}
}

private MultiMap<PsiElement, String> checkForConflicts(@Nonnull final PsiMember member) {
if (member instanceof PsiClass && getModifier().equals(PsiModifier.PUBLIC)) {
final PsiClass aClass = (PsiClass)member;
final PsiElement parent = aClass.getParent();
if (!(parent instanceof PsiJavaFile)) {
return MultiMap.empty();
}
final PsiJavaFile javaFile = (PsiJavaFile)parent;
final String name = FileUtil.getNameWithoutExtension(javaFile.getName());
final String className = aClass.getName();
if (name.equals(className)) {
return MultiMap.empty();
}
final MultiMap<PsiElement, String> conflicts = new MultiMap();
conflicts.putValue(aClass, IntentionPowerPackBundle.message(
"0.is.declared.in.1.but.when.public.should.be.declared.in.a.file.named.2",
RefactoringUIUtil.getDescription(aClass, false),
RefactoringUIUtil.getDescription(javaFile, false),
CommonRefactoringUtil.htmlEmphasize(className + ".java")));
return conflicts;
}
final PsiModifierList modifierList = member.getModifierList();
if (modifierList == null || modifierList.hasModifierProperty(PsiModifier.PRIVATE)) {
return MultiMap.empty();
if (conflictsDialogOK) {
WriteAction.run(() -> modifierList.setModifierProperty(getModifier(), true));
}
}
final MultiMap<PsiElement, String> conflicts = new MultiMap();
if (member instanceof PsiMethod) {
final PsiMethod method = (PsiMethod)member;
SuperMethodsSearch.search(method, method.getContainingClass(), true, false).forEach(
new Processor<MethodSignatureBackedByPsiMethod>() {
@Override
public boolean process(MethodSignatureBackedByPsiMethod methodSignature) {
final PsiMethod superMethod = methodSignature.getMethod();
if (!hasCompatibleVisibility(superMethod, true)) {
conflicts.putValue(superMethod, IntentionPowerPackBundle.message(
"0.will.have.incompatible.access.privileges.with.super.1",
RefactoringUIUtil.getDescription(method, false),
RefactoringUIUtil.getDescription(superMethod, true)));

private MultiMap<PsiElement, String> checkForConflicts(@Nonnull final PsiMember member) {
if (member instanceof PsiClass && getModifier().equals(PsiModifier.PUBLIC)) {
final PsiClass aClass = (PsiClass) member;
final PsiElement parent = aClass.getParent();
if (!(parent instanceof PsiJavaFile)) {
return MultiMap.empty();
}
final PsiJavaFile javaFile = (PsiJavaFile) parent;
final String name = FileUtil.getNameWithoutExtension(javaFile.getName());
final String className = aClass.getName();
if (name.equals(className)) {
return MultiMap.empty();
}
final MultiMap<PsiElement, String> conflicts = new MultiMap();
conflicts.putValue(aClass, IntentionPowerPackBundle.message(
"0.is.declared.in.1.but.when.public.should.be.declared.in.a.file.named.2",
RefactoringUIUtil.getDescription(aClass, false),
RefactoringUIUtil.getDescription(javaFile, false),
CommonRefactoringUtil.htmlEmphasize(className + ".java")));
return conflicts;
}
final PsiModifierList modifierList = member.getModifierList();
if (modifierList == null || modifierList.hasModifierProperty(PsiModifier.PRIVATE)) {
return MultiMap.empty();
}
final MultiMap<PsiElement, String> conflicts = new MultiMap();
if (member instanceof PsiMethod) {
final PsiMethod method = (PsiMethod) member;
SuperMethodsSearch.search(method, method.getContainingClass(), true, false).forEach(methodSignature -> {
final PsiMethod superMethod = methodSignature.getMethod();
if (!hasCompatibleVisibility(superMethod, true)) {
conflicts.putValue(superMethod, IntentionPowerPackBundle.message(
"0.will.have.incompatible.access.privileges.with.super.1",
RefactoringUIUtil.getDescription(method, false),
RefactoringUIUtil.getDescription(superMethod, true)));
}
return true;
});
OverridingMethodsSearch.search(method).forEach(overridingMethod -> {
if (!isVisibleFromOverridingMethod(method, overridingMethod)) {
conflicts.putValue(overridingMethod, IntentionPowerPackBundle.message(
"0.will.no.longer.be.visible.from.overriding.1",
RefactoringUIUtil.getDescription(method, false),
RefactoringUIUtil.getDescription(overridingMethod, true)));
}
else if (!hasCompatibleVisibility(overridingMethod, false)) {
conflicts.putValue(overridingMethod, IntentionPowerPackBundle.message(
"0.will.have.incompatible.access.privileges.with.overriding.1",
RefactoringUIUtil.getDescription(method, false),
RefactoringUIUtil.getDescription(overridingMethod, true)));
}
return false;
});
}
final PsiModifierList modifierListCopy = (PsiModifierList) modifierList.copy();
modifierListCopy.setModifierProperty(getModifier(), true);
final Query<PsiReference> search = ReferencesSearch.search(member, member.getResolveScope());
search.forEach(reference -> {
final PsiElement element = reference.getElement();
if (JavaResolveUtil.isAccessible(member, member.getContainingClass(), modifierListCopy, element, null, null)) {
return true;
}
final PsiElement context = PsiTreeUtil.getParentOfType(element, PsiMethod.class, PsiField.class, PsiClass.class, PsiFile.class);
if (context == null) {
return true;
}
conflicts.putValue(
element,
RefactoringLocalize.zeroWith1VisibilityIsNotAccessibleFrom2(
RefactoringUIUtil.getDescription(member, false),
PsiBundle.visibilityPresentation(getModifier()),
RefactoringUIUtil.getDescription(context, true)
).get()
);
return true;
}
});
OverridingMethodsSearch.search(method).forEach(new Processor<PsiMethod>() {
@Override
public boolean process(PsiMethod overridingMethod) {
if (!isVisibleFromOverridingMethod(method, overridingMethod)) {
conflicts.putValue(overridingMethod, IntentionPowerPackBundle.message(
"0.will.no.longer.be.visible.from.overriding.1",
RefactoringUIUtil.getDescription(method, false),
RefactoringUIUtil.getDescription(overridingMethod, true)));
}
else if (!hasCompatibleVisibility(overridingMethod, false)) {
conflicts.putValue(overridingMethod, IntentionPowerPackBundle.message(
"0.will.have.incompatible.access.privileges.with.overriding.1",
RefactoringUIUtil.getDescription(method, false),
RefactoringUIUtil.getDescription(overridingMethod, true)));
}
return false;
}
});
return conflicts;
}
final PsiModifierList modifierListCopy = (PsiModifierList)modifierList.copy();
modifierListCopy.setModifierProperty(getModifier(), true);
final Query<PsiReference> search = ReferencesSearch.search(member, member.getResolveScope());
search.forEach(new Processor<PsiReference>() {

@Override
public boolean process(PsiReference reference) {
final PsiElement element = reference.getElement();
if (JavaResolveUtil.isAccessible(member, member.getContainingClass(), modifierListCopy, element, null, null)) {
return true;
private boolean hasCompatibleVisibility(PsiMethod method, boolean isSuper) {
if (getModifier().equals(PsiModifier.PRIVATE)) {
return false;
}
final PsiElement context = PsiTreeUtil.getParentOfType(element, PsiMethod.class, PsiField.class, PsiClass.class, PsiFile.class);
if (context == null) {
return true;
else if (getModifier().equals(PsiModifier.PACKAGE_LOCAL)) {
if (isSuper) {
return !(method.hasModifierProperty(PsiModifier.PUBLIC) || method.hasModifierProperty(PsiModifier.PROTECTED));
}
return true;
}
conflicts.putValue(
element,
RefactoringLocalize.zeroWith1VisibilityIsNotAccessibleFrom2(
RefactoringUIUtil.getDescription(member, false),
PsiBundle.visibilityPresentation(getModifier()),
RefactoringUIUtil.getDescription(context, true)
).get()
);
return true;
}
});
return conflicts;
}

private boolean hasCompatibleVisibility(PsiMethod method, boolean isSuper) {
if (getModifier().equals(PsiModifier.PRIVATE)) {
return false;
}
else if (getModifier().equals(PsiModifier.PACKAGE_LOCAL)) {
if (isSuper) {
return !(method.hasModifierProperty(PsiModifier.PUBLIC) || method.hasModifierProperty(PsiModifier.PROTECTED));
}
return true;
}
else if (getModifier().equals(PsiModifier.PROTECTED)) {
if (isSuper) {
return !method.hasModifierProperty(PsiModifier.PUBLIC);
}
else {
return method.hasModifierProperty(PsiModifier.PROTECTED) || method.hasModifierProperty(PsiModifier.PUBLIC);
}
}
else if (getModifier().equals(PsiModifier.PUBLIC)) {
if (!isSuper) {
return method.hasModifierProperty(PsiModifier.PUBLIC);
}
return true;
else if (getModifier().equals(PsiModifier.PROTECTED)) {
if (isSuper) {
return !method.hasModifierProperty(PsiModifier.PUBLIC);
}
else {
return method.hasModifierProperty(PsiModifier.PROTECTED) || method.hasModifierProperty(PsiModifier.PUBLIC);
}
}
else if (getModifier().equals(PsiModifier.PUBLIC)) {
if (!isSuper) {
return method.hasModifierProperty(PsiModifier.PUBLIC);
}
return true;
}
throw new AssertionError();
}
throw new AssertionError();
}

private boolean isVisibleFromOverridingMethod(PsiMethod method, PsiMethod overridingMethod) {
final PsiModifierList modifierListCopy = (PsiModifierList)method.getModifierList().copy();
modifierListCopy.setModifierProperty(getModifier(), true);
return JavaResolveUtil.isAccessible(method, method.getContainingClass(), modifierListCopy, overridingMethod, null, null);
}
private boolean isVisibleFromOverridingMethod(PsiMethod method, PsiMethod overridingMethod) {
final PsiModifierList modifierListCopy = (PsiModifierList) method.getModifierList().copy();
modifierListCopy.setModifierProperty(getModifier(), true);
return JavaResolveUtil.isAccessible(method, method.getContainingClass(), modifierListCopy, overridingMethod, null, null);
}

@VisibilityConstant
protected abstract String getModifier();
@VisibilityConstant
protected abstract String getModifier();

@MagicConstant(stringValues = {PsiModifier.PUBLIC, PsiModifier.PROTECTED, PsiModifier.PRIVATE, PsiModifier.PACKAGE_LOCAL})
@interface VisibilityConstant {}
@MagicConstant(stringValues = {PsiModifier.PUBLIC, PsiModifier.PROTECTED, PsiModifier.PRIVATE, PsiModifier.PACKAGE_LOCAL})
@interface VisibilityConstant {
}
}

0 comments on commit 621ecab

Please sign in to comment.