mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
+28
-22
@@ -21,6 +21,7 @@ import com.intellij.codeInsight.daemon.GroupNames;
|
||||
import com.intellij.codeInsight.intention.QuickFixFactory;
|
||||
import com.intellij.codeInspection.BaseJavaBatchLocalInspectionTool;
|
||||
import com.intellij.codeInspection.InspectionsBundle;
|
||||
import com.intellij.codeInspection.LocalQuickFix;
|
||||
import com.intellij.codeInspection.ProblemsHolder;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.module.EffectiveLanguageLevelUtil;
|
||||
@@ -233,7 +234,8 @@ public class Java15APIUsageInspectionBase extends BaseJavaBatchLocalInspectionTo
|
||||
final Module module = ModuleUtilCore.findModuleForPsiElement(reference.getElement());
|
||||
if (module != null) {
|
||||
final LanguageLevel languageLevel = getEffectiveLanguageLevel(module);
|
||||
if (isForbiddenApiUsage((PsiMember)resolved, languageLevel)) {
|
||||
LanguageLevel sinceLanguageLevel = getLastIncompatibleLanguageLevel((PsiMember)resolved, languageLevel);
|
||||
if (sinceLanguageLevel != null) {
|
||||
PsiClass psiClass = null;
|
||||
final PsiElement qualifier = reference.getQualifier();
|
||||
if (qualifier != null) {
|
||||
@@ -250,7 +252,7 @@ public class Java15APIUsageInspectionBase extends BaseJavaBatchLocalInspectionTo
|
||||
if (isIgnored(superClass)) return;
|
||||
}
|
||||
}
|
||||
registerError(reference, languageLevel);
|
||||
registerError(reference, sinceLanguageLevel);
|
||||
} else if (resolved instanceof PsiClass && isInProject(reference)&& !languageLevel.isAtLeast(LanguageLevel.JDK_1_7)) {
|
||||
final PsiReferenceParameterList parameterList = reference.getParameterList();
|
||||
if (parameterList != null && parameterList.getTypeParameterElements().length > 0) {
|
||||
@@ -296,8 +298,9 @@ public class Java15APIUsageInspectionBase extends BaseJavaBatchLocalInspectionTo
|
||||
if (module != null) {
|
||||
final LanguageLevel languageLevel = getEffectiveLanguageLevel(module);
|
||||
if (constructor instanceof PsiCompiledElement) {
|
||||
if (isForbiddenApiUsage(constructor, languageLevel)) {
|
||||
registerError(expression.getClassReference(), languageLevel);
|
||||
LanguageLevel sinceLanguageLevel = getLastIncompatibleLanguageLevel(constructor, languageLevel);
|
||||
if (sinceLanguageLevel != null) {
|
||||
registerError(expression.getClassReference(), sinceLanguageLevel);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -309,12 +312,14 @@ public class Java15APIUsageInspectionBase extends BaseJavaBatchLocalInspectionTo
|
||||
PsiAnnotation annotation = !method.isConstructor() ? AnnotationUtil.findAnnotation(method, CommonClassNames.JAVA_LANG_OVERRIDE) : null;
|
||||
if (annotation != null) {
|
||||
final Module module = ModuleUtilCore.findModuleForPsiElement(annotation);
|
||||
LanguageLevel sinceLanguageLevel = null;
|
||||
if (module != null) {
|
||||
final LanguageLevel languageLevel = getEffectiveLanguageLevel(module);
|
||||
final PsiMethod[] methods = method.findSuperMethods();
|
||||
for (PsiMethod superMethod : methods) {
|
||||
if (superMethod instanceof PsiCompiledElement) {
|
||||
if (!isForbiddenApiUsage(superMethod, languageLevel)) {
|
||||
sinceLanguageLevel = getLastIncompatibleLanguageLevel(superMethod, languageLevel);
|
||||
if (sinceLanguageLevel == null) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -323,7 +328,7 @@ public class Java15APIUsageInspectionBase extends BaseJavaBatchLocalInspectionTo
|
||||
}
|
||||
}
|
||||
if (methods.length > 0) {
|
||||
registerError(annotation.getNameReferenceElement(), languageLevel);
|
||||
registerError(annotation.getNameReferenceElement(), sinceLanguageLevel);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -337,7 +342,9 @@ public class Java15APIUsageInspectionBase extends BaseJavaBatchLocalInspectionTo
|
||||
private void registerError(PsiJavaCodeReferenceElement reference, LanguageLevel api) {
|
||||
if (reference != null && isInProject(reference)) {
|
||||
//noinspection DialogTitleCapitalization
|
||||
myHolder.registerProblem(reference, InspectionsBundle.message("inspection.1.5.problem.descriptor", getShortName(api)));
|
||||
myHolder.registerProblem(reference,
|
||||
InspectionsBundle.message("inspection.1.5.problem.descriptor", getShortName(api)),
|
||||
myOnTheFly ? new LocalQuickFix[] {(LocalQuickFix)QuickFixFactory.getInstance().createIncreaseLanguageLevelFix(LanguageLevel.values()[api.ordinal() + 1])} : null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -347,33 +354,32 @@ public class Java15APIUsageInspectionBase extends BaseJavaBatchLocalInspectionTo
|
||||
return presentableText.substring(0, presentableText.indexOf(' '));
|
||||
}
|
||||
|
||||
public static boolean isForbiddenApiUsage(@NotNull PsiMember member, @NotNull LanguageLevel languageLevel) {
|
||||
if (member instanceof PsiAnonymousClass) return false;
|
||||
public static LanguageLevel getLastIncompatibleLanguageLevel(@NotNull PsiMember member, @NotNull LanguageLevel languageLevel) {
|
||||
if (member instanceof PsiAnonymousClass) return null;
|
||||
PsiClass containingClass = member.getContainingClass();
|
||||
if (containingClass instanceof PsiAnonymousClass) return false;
|
||||
if (member instanceof PsiClass && !(member.getParent() instanceof PsiClass || member.getParent() instanceof PsiFile)) return false;
|
||||
if (containingClass instanceof PsiAnonymousClass) return null;
|
||||
if (member instanceof PsiClass && !(member.getParent() instanceof PsiClass || member.getParent() instanceof PsiFile)) return null;
|
||||
|
||||
return isForbiddenSignature(member, languageLevel) ||
|
||||
containingClass != null && isForbiddenApiUsage(containingClass, languageLevel);
|
||||
|
||||
}
|
||||
|
||||
private static boolean isForbiddenSignature(@NotNull PsiMember member, @NotNull LanguageLevel languageLevel) {
|
||||
Set<String> forbiddenApi = getForbiddenApi(languageLevel);
|
||||
String signature = getSignature(member);
|
||||
return forbiddenApi != null && signature != null && isForbiddenSignature(signature, languageLevel, forbiddenApi);
|
||||
if (forbiddenApi != null && signature != null) {
|
||||
LanguageLevel lastIncompatibleLanguageLevel = getLastIncompatibleLanguageLevelForSignature(signature, languageLevel, forbiddenApi);
|
||||
if (lastIncompatibleLanguageLevel != null) return lastIncompatibleLanguageLevel;
|
||||
}
|
||||
return containingClass != null ? getLastIncompatibleLanguageLevel(containingClass, languageLevel) : null;
|
||||
|
||||
}
|
||||
|
||||
private static boolean isForbiddenSignature(@NotNull String signature, @NotNull LanguageLevel languageLevel, @NotNull Set<String> forbiddenApi) {
|
||||
private static LanguageLevel getLastIncompatibleLanguageLevelForSignature(@NotNull String signature, @NotNull LanguageLevel languageLevel, @NotNull Set<String> forbiddenApi) {
|
||||
if (forbiddenApi.contains(signature)) {
|
||||
return true;
|
||||
return languageLevel;
|
||||
}
|
||||
if (languageLevel.compareTo(ourHighestKnownLanguage) == 0) {
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
LanguageLevel nextLanguageLevel = LanguageLevel.values()[languageLevel.ordinal() + 1];
|
||||
Set<String> nextForbiddenApi = getForbiddenApi(nextLanguageLevel);
|
||||
return nextForbiddenApi != null && isForbiddenSignature(signature, nextLanguageLevel, nextForbiddenApi);
|
||||
return nextForbiddenApi != null ? getLastIncompatibleLanguageLevelForSignature(signature, nextLanguageLevel, nextForbiddenApi) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -144,7 +144,7 @@ public class FunctionalInterfaceSuggester {
|
||||
final Project project = element.getProject();
|
||||
final Set<PsiType> types = new HashSet<>();
|
||||
final Processor<PsiMember> consumer = member -> {
|
||||
if (member instanceof PsiClass && !Java15APIUsageInspectionBase.isForbiddenApiUsage(member, PsiUtil.getLanguageLevel(element))) {
|
||||
if (member instanceof PsiClass && Java15APIUsageInspectionBase.getLastIncompatibleLanguageLevel(member, PsiUtil.getLanguageLevel(element)) == null) {
|
||||
if (!JavaResolveUtil.isAccessible(member, null, member.getModifierList(), element, null, null)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -481,7 +481,7 @@ public class JavaCompletionUtil {
|
||||
|
||||
private static boolean shouldMarkRed(@NotNull Object object, @NotNull PsiElement place) {
|
||||
if (!(object instanceof PsiMember)) return false;
|
||||
if (Java15APIUsageInspectionBase.isForbiddenApiUsage((PsiMember)object, PsiUtil.getLanguageLevel(place))) return true;
|
||||
if (Java15APIUsageInspectionBase.getLastIncompatibleLanguageLevel((PsiMember)object, PsiUtil.getLanguageLevel(place)) != null) return true;
|
||||
|
||||
if (object instanceof PsiEnumConstant) {
|
||||
return findConstantsUsedInSwitch(place).contains(CompletionUtil.getOriginalOrSelf((PsiEnumConstant)object));
|
||||
|
||||
+18
-4
@@ -17,6 +17,8 @@ package com.intellij.codeInsight.daemon.impl.analysis;
|
||||
|
||||
import com.intellij.codeInsight.CodeInsightBundle;
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.codeInspection.LocalQuickFix;
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.module.Module;
|
||||
@@ -29,13 +31,14 @@ import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author cdr
|
||||
*/
|
||||
public class IncreaseLanguageLevelFix implements IntentionAction {
|
||||
public class IncreaseLanguageLevelFix implements IntentionAction, LocalQuickFix {
|
||||
private static final Logger LOG = Logger.getInstance("#" + IncreaseLanguageLevelFix.class.getName());
|
||||
|
||||
private final LanguageLevel myLevel;
|
||||
@@ -50,12 +53,25 @@ public class IncreaseLanguageLevelFix implements IntentionAction {
|
||||
return CodeInsightBundle.message("set.language.level.to.0", myLevel.getPresentableText());
|
||||
}
|
||||
|
||||
@Nls
|
||||
@NotNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return getText();
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getFamilyName() {
|
||||
return CodeInsightBundle.message("set.language.level");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
|
||||
PsiElement element = descriptor.getPsiElement();
|
||||
invoke(project, null, element.getContainingFile());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable(@NotNull final Project project, final Editor editor, final PsiFile file) {
|
||||
final VirtualFile virtualFile = file.getVirtualFile();
|
||||
@@ -67,9 +83,7 @@ public class IncreaseLanguageLevelFix implements IntentionAction {
|
||||
|
||||
@Override
|
||||
public void invoke(@NotNull final Project project, final Editor editor, final PsiFile file) throws IncorrectOperationException {
|
||||
final VirtualFile virtualFile = file.getVirtualFile();
|
||||
LOG.assertTrue(virtualFile != null);
|
||||
final Module module = ModuleUtilCore.findModuleForFile(virtualFile, project);
|
||||
final Module module = ModuleUtilCore.findModuleForPsiElement(file);
|
||||
if (module == null) return;
|
||||
|
||||
JavaProjectModelModificationService.getInstance(project).changeLanguageLevel(module, myLevel);
|
||||
|
||||
+4
-1
@@ -575,7 +575,10 @@ public class CreateFromUsageUtils {
|
||||
PsiElement parent = expr.getParent();
|
||||
|
||||
if (!(parent instanceof PsiReferenceExpression)) {
|
||||
ExpectedTypeInfo[] someExpectedTypes = ExpectedTypesProvider.getExpectedTypes(expr, PsiUtil.skipParenthesizedExprUp(parent) instanceof PsiExpressionList);
|
||||
boolean isAssignmentToFunctionalExpression = PsiUtil.isOnAssignmentLeftHand(expr) &&
|
||||
((PsiAssignmentExpression)PsiUtil.skipParenthesizedExprUp(parent)).getRExpression() instanceof PsiFunctionalExpression;
|
||||
boolean forCompletion = PsiUtil.skipParenthesizedExprUp(isAssignmentToFunctionalExpression ? parent.getParent() : parent) instanceof PsiExpressionList;
|
||||
ExpectedTypeInfo[] someExpectedTypes = ExpectedTypesProvider.getExpectedTypes(expr, forCompletion);
|
||||
if (someExpectedTypes.length > 0) {
|
||||
Arrays.sort(someExpectedTypes, (o1, o2) -> compareExpectedTypes(o1, o2, expression));
|
||||
types.add(someExpectedTypes);
|
||||
|
||||
+6
-6
@@ -102,7 +102,7 @@ public class InvertIfConditionAction extends PsiElementBaseIntentionAction {
|
||||
|
||||
final CodeStyleManager codeStyle = CodeStyleManager.getInstance(project);
|
||||
|
||||
PsiBlockStatement codeBlock = (PsiBlockStatement)factory.createStatementFromText("{}", null);
|
||||
PsiBlockStatement codeBlock = (PsiBlockStatement)factory.createStatementFromText("{}", ifStatement);
|
||||
codeBlock = (PsiBlockStatement)codeStyle.reformat(codeBlock);
|
||||
|
||||
ifStatement.getThenBranch().replace(codeBlock);
|
||||
@@ -182,7 +182,7 @@ public class InvertIfConditionAction extends PsiElementBaseIntentionAction {
|
||||
final CodeStyleManager codeStyle = CodeStyleManager.getInstance(project);
|
||||
if (flow.getSize() == 0) {
|
||||
ifStatement.setElseBranch(thenBranch);
|
||||
PsiStatement statement = factory.createStatementFromText("{}", null);
|
||||
PsiStatement statement = factory.createStatementFromText("{}", ifStatement);
|
||||
statement = (PsiStatement) codeStyle.reformat(statement);
|
||||
statement = (PsiStatement) ifStatement.getThenBranch().replace(statement);
|
||||
codeStyle.reformat(statement);
|
||||
@@ -194,7 +194,7 @@ public class InvertIfConditionAction extends PsiElementBaseIntentionAction {
|
||||
LOG.assertTrue(endOffset >= 0);
|
||||
|
||||
if (endOffset >= flow.getSize()) {
|
||||
PsiStatement statement = factory.createStatementFromText("return;", null);
|
||||
PsiStatement statement = factory.createStatementFromText("return;", ifStatement);
|
||||
statement = (PsiStatement) codeStyle.reformat(statement);
|
||||
if (thenBranch instanceof PsiBlockStatement) {
|
||||
PsiStatement[] statements = ((PsiBlockStatement) thenBranch).getCodeBlock().getStatements();
|
||||
@@ -219,7 +219,7 @@ public class InvertIfConditionAction extends PsiElementBaseIntentionAction {
|
||||
if (element != null && element.getParent() instanceof PsiForStatement && ((PsiForStatement)element.getParent()).getUpdate() == element ||
|
||||
element instanceof PsiWhileStatement && flow.getStartOffset(element) == endOffset ||
|
||||
element instanceof PsiForeachStatement && flow.getStartOffset(element) + 1 == endOffset) {
|
||||
PsiStatement statement = factory.createStatementFromText("continue;", null);
|
||||
PsiStatement statement = factory.createStatementFromText("continue;", ifStatement);
|
||||
statement = (PsiStatement)codeStyle.reformat(statement);
|
||||
ifStatement = addAfterWithinCodeBlock(ifStatement, thenBranch);
|
||||
ifStatement.getThenBranch().replace(statement);
|
||||
@@ -267,7 +267,7 @@ public class InvertIfConditionAction extends PsiElementBaseIntentionAction {
|
||||
last = last.getPrevSibling();
|
||||
|
||||
|
||||
PsiBlockStatement codeBlock = (PsiBlockStatement) factory.createStatementFromText("{}", null);
|
||||
PsiBlockStatement codeBlock = (PsiBlockStatement) factory.createStatementFromText("{}", ifStatement);
|
||||
codeBlock.getCodeBlock().addRange(first, last);
|
||||
first.getParent().deleteChildRange(first, last);
|
||||
ifStatement.getThenBranch().replace(codeBlock);
|
||||
@@ -277,7 +277,7 @@ public class InvertIfConditionAction extends PsiElementBaseIntentionAction {
|
||||
}
|
||||
|
||||
setElseBranch(ifStatement, thenBranch, flow);
|
||||
PsiStatement statement = factory.createStatementFromText("{}", null);
|
||||
PsiStatement statement = factory.createStatementFromText("{}", ifStatement);
|
||||
statement = (PsiStatement) codeStyle.reformat(statement);
|
||||
statement = (PsiStatement) ifStatement.getThenBranch().replace(statement);
|
||||
codeStyle.reformat(statement);
|
||||
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
// "Create local variable 'lf'" "true"
|
||||
import java.util.function.Function;
|
||||
|
||||
class Main2 {
|
||||
void f(Function<String, String> g) {}
|
||||
{
|
||||
Function<String, String> lf;
|
||||
f(lf = c -> c);
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// "Create local variable 'lf'" "true"
|
||||
import java.util.function.Function;
|
||||
|
||||
class Main2 {
|
||||
void f(Function<String, String> g) {}
|
||||
{
|
||||
f(l<caret>f = c -> c);
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
// "Invert 'if' condition" "true"
|
||||
class Main2 {
|
||||
private static class Process { }
|
||||
|
||||
public static void main(String[] args) {
|
||||
List<Process> processList = null;
|
||||
if (processList != null) {
|
||||
for (Process process : processList) {
|
||||
System.out.println("process = " + process);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
// "Invert 'if' condition" "true"
|
||||
class Main2 {
|
||||
private static class Process { }
|
||||
|
||||
public static void main(String[] args) {
|
||||
List<Process> processList = null;
|
||||
i<caret>f (processList == null) {
|
||||
return;
|
||||
}
|
||||
for (Process process : processList) {
|
||||
System.out.println("process = " + process);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
<file>Test.java</file>
|
||||
<line>4</line>
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Usages of API documented as @since 1.5 (1.6|1.7)</problem_class>
|
||||
<description>Usage of API documented as @since 1.7+</description>
|
||||
<description>Usage of API documented as @since 1.8+</description>
|
||||
</problem>
|
||||
|
||||
</problems>
|
||||
@@ -122,6 +122,13 @@ public abstract class TransactionGuard {
|
||||
guard.submitTransaction(parentDisposable, guard.getContextTransaction(), transaction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs an error if the given modality state was created in a write-unsafe context. For modalities created in write-safe contexts,
|
||||
* {@link Application#invokeLater(Runnable, ModalityState)} and similar calls will be guaranteed to also run in a write-safe context.
|
||||
* {@link ModalityState#NON_MODAL} is always write-safe, {@link ModalityState#any()} is always write-unsafe.
|
||||
*/
|
||||
public abstract void assertWriteSafeContext(@NotNull ModalityState modality);
|
||||
|
||||
/**
|
||||
* Schedules a given runnable to be executed inside a transaction later on Swing thread.
|
||||
* Same as {@link #submitTransaction(Disposable, Runnable)}, but the runnable is never executed immediately.
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
package com.intellij.core;
|
||||
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.application.TransactionId;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiFile;
|
||||
@@ -35,6 +35,6 @@ class MockDocumentCommitProcessor implements DocumentCommitProcessor {
|
||||
public void commitAsynchronously(@NotNull Project project,
|
||||
@NotNull Document document,
|
||||
@NonNls @NotNull Object reason,
|
||||
@NotNull ModalityState currentModalityState) {
|
||||
@NotNull TransactionId context) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,17 +226,28 @@ public class TransactionGuardImpl extends TransactionGuard {
|
||||
public void assertWriteActionAllowed() {
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
if (areAssertionsEnabled() && !myWritingAllowed && !myErrorReported) {
|
||||
String message = "Write access is allowed from write-safe contexts only. " +
|
||||
"Please ensure you're using invokeLater/invokeAndWait with a correct modality state (not \"any\"). " +
|
||||
"See TransactionGuard documentation for details." +
|
||||
"\n current modality=" + ModalityState.current() +
|
||||
"\n known modalities=" + myWriteSafeModalities;
|
||||
// please assign exceptions here to Peter
|
||||
LOG.error(message);
|
||||
LOG.error(reportWriteUnsafeContext(ModalityState.current()));
|
||||
myErrorReported = true;
|
||||
}
|
||||
}
|
||||
|
||||
private String reportWriteUnsafeContext(@NotNull ModalityState modality) {
|
||||
return "Write-unsafe context! Model changes are allowed from write-safe contexts only. " +
|
||||
"Please ensure you're using invokeLater/invokeAndWait with a correct modality state (not \"any\"). " +
|
||||
"See TransactionGuard documentation for details." +
|
||||
"\n current modality=" + modality +
|
||||
"\n known modalities=" + myWriteSafeModalities;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void assertWriteSafeContext(@NotNull ModalityState modality) {
|
||||
if (!isWriteSafeModality(modality) && areAssertionsEnabled()) {
|
||||
// please assign exceptions here to Peter
|
||||
LOG.error(reportWriteUnsafeContext(modality));
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean areAssertionsEnabled() {
|
||||
Application app = ApplicationManager.getApplication();
|
||||
if (app.isUnitTestMode() && !ourTestingTransactions) {
|
||||
|
||||
@@ -15,17 +15,18 @@
|
||||
*/
|
||||
package com.intellij.psi.impl;
|
||||
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.application.TransactionId;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface DocumentCommitProcessor {
|
||||
void commitSynchronously(@NotNull Document document, @NotNull Project project, @NotNull PsiFile psiFile);
|
||||
void commitAsynchronously(@NotNull final Project project,
|
||||
@NotNull final Document document,
|
||||
@NonNls @NotNull Object reason,
|
||||
@NotNull ModalityState currentModalityState);
|
||||
@NotNull final Document document,
|
||||
@NonNls @NotNull Object reason,
|
||||
@Nullable TransactionId context);
|
||||
}
|
||||
|
||||
@@ -152,25 +152,25 @@ public class DocumentCommitThread implements Runnable, Disposable, DocumentCommi
|
||||
public void commitAsynchronously(@NotNull final Project project,
|
||||
@NotNull final Document document,
|
||||
@NonNls @NotNull Object reason,
|
||||
@NotNull ModalityState currentModalityState) {
|
||||
@Nullable TransactionId context) {
|
||||
assert !isDisposed : "already disposed";
|
||||
|
||||
if (!project.isInitialized()) return;
|
||||
PsiFile psiFile = PsiDocumentManager.getInstance(project).getCachedPsiFile(document);
|
||||
if (psiFile == null) return;
|
||||
doQueue(project, document, getAllFileNodes(psiFile), reason, currentModalityState,
|
||||
doQueue(project, document, getAllFileNodes(psiFile), reason, context,
|
||||
PsiDocumentManager.getInstance(project).getLastCommittedText(document));
|
||||
}
|
||||
|
||||
private void doQueue(@NotNull Project project,
|
||||
@NotNull Document document,
|
||||
@NotNull List<Pair<PsiFileImpl, FileASTNode>> oldFileNodes,
|
||||
@NotNull Object reason,
|
||||
@NotNull ModalityState currentModalityState,
|
||||
@NotNull CharSequence lastCommittedText) {
|
||||
@NotNull Document document,
|
||||
@NotNull List<Pair<PsiFileImpl, FileASTNode>> oldFileNodes,
|
||||
@NotNull Object reason,
|
||||
@Nullable TransactionId context,
|
||||
@NotNull CharSequence lastCommittedText) {
|
||||
synchronized (lock) {
|
||||
if (!project.isInitialized()) return; // check the project is disposed under lock.
|
||||
CommitTask newTask = createNewTaskAndCancelSimilar(project, document, oldFileNodes, reason, currentModalityState,
|
||||
CommitTask newTask = createNewTaskAndCancelSimilar(project, document, oldFileNodes, reason, context,
|
||||
lastCommittedText);
|
||||
|
||||
documentsToCommit.offer(newTask);
|
||||
@@ -185,13 +185,13 @@ public class DocumentCommitThread implements Runnable, Disposable, DocumentCommi
|
||||
@NotNull Document document,
|
||||
@NotNull List<Pair<PsiFileImpl, FileASTNode>> oldFileNodes,
|
||||
@NotNull Object reason,
|
||||
@NotNull ModalityState currentModalityState,
|
||||
@Nullable TransactionId context,
|
||||
@NotNull CharSequence lastCommittedText) {
|
||||
synchronized (lock) {
|
||||
for (Pair<PsiFileImpl, FileASTNode> pair : oldFileNodes) {
|
||||
assert pair.first.getProject() == project;
|
||||
}
|
||||
CommitTask newTask = new CommitTask(project, document, oldFileNodes, createProgressIndicator(), reason, currentModalityState,
|
||||
CommitTask newTask = new CommitTask(project, document, oldFileNodes, createProgressIndicator(), reason, context,
|
||||
lastCommittedText);
|
||||
cancelAndRemoveFromDocsToCommit(newTask, reason);
|
||||
cancelAndRemoveCurrentTask(newTask, reason);
|
||||
@@ -380,7 +380,7 @@ public class DocumentCommitThread implements Runnable, Disposable, DocumentCommi
|
||||
if (success) {
|
||||
assert !myApplication.isDispatchThread();
|
||||
TransactionGuardImpl guard = (TransactionGuardImpl)TransactionGuard.getInstance();
|
||||
guard.submitTransaction(project, guard.getModalityTransaction(task.myCreationModalityState), finishRunnable);
|
||||
guard.submitTransaction(project, task.myCreationContext, finishRunnable);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -408,7 +408,7 @@ public class DocumentCommitThread implements Runnable, Disposable, DocumentCommi
|
||||
List<Pair<PsiFileImpl, FileASTNode>> oldFileNodes = file == null ? null : getAllFileNodes(file);
|
||||
if (oldFileNodes != null) {
|
||||
doQueue(finalProject, finalDocument, oldFileNodes, "re-added on failure: " + finalFailureReason,
|
||||
finalTask.myCreationModalityState,
|
||||
finalTask.myCreationContext,
|
||||
lastCommittedText);
|
||||
}
|
||||
});
|
||||
@@ -442,7 +442,7 @@ public class DocumentCommitThread implements Runnable, Disposable, DocumentCommi
|
||||
CommitTask task;
|
||||
synchronized (lock) {
|
||||
// synchronized to ensure no new similar tasks can start before we hold the document's lock
|
||||
task = createNewTaskAndCancelSimilar(project, document, allFileNodes, SYNC_COMMIT_REASON, ModalityState.current(),
|
||||
task = createNewTaskAndCancelSimilar(project, document, allFileNodes, SYNC_COMMIT_REASON, TransactionGuard.getInstance().getContextTransaction(),
|
||||
PsiDocumentManager.getInstance(project).getLastCommittedText(document));
|
||||
documentLock.lock();
|
||||
}
|
||||
@@ -541,7 +541,7 @@ public class DocumentCommitThread implements Runnable, Disposable, DocumentCommi
|
||||
throw new PsiInvalidElementAccessException(file, "File " + file + " invalidated during sync commit");
|
||||
}
|
||||
commitAsynchronously(project, document, "File " + file + " invalidated during background commit; task: "+task,
|
||||
task.myCreationModalityState);
|
||||
task.myCreationContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -605,7 +605,7 @@ public class DocumentCommitThread implements Runnable, Disposable, DocumentCommi
|
||||
}
|
||||
else {
|
||||
// add document back to the queue
|
||||
commitAsynchronously(project, document, "Re-added back", task.myCreationModalityState);
|
||||
commitAsynchronously(project, document, "Re-added back", task.myCreationContext);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -655,7 +655,7 @@ public class DocumentCommitThread implements Runnable, Disposable, DocumentCommi
|
||||
// when failed it's canceled
|
||||
@NotNull final ProgressIndicator indicator; // progress to commit this doc under.
|
||||
@NotNull final Object reason;
|
||||
@NotNull final ModalityState myCreationModalityState;
|
||||
@Nullable final TransactionId myCreationContext;
|
||||
private final CharSequence myLastCommittedText;
|
||||
@NotNull final List<Pair<PsiFileImpl, FileASTNode>> myOldFileNodes;
|
||||
|
||||
@@ -664,13 +664,13 @@ public class DocumentCommitThread implements Runnable, Disposable, DocumentCommi
|
||||
@NotNull final List<Pair<PsiFileImpl, FileASTNode>> oldFileNodes,
|
||||
@NotNull ProgressIndicator indicator,
|
||||
@NotNull Object reason,
|
||||
@NotNull ModalityState currentModalityState,
|
||||
@Nullable TransactionId context,
|
||||
@NotNull CharSequence lastCommittedText) {
|
||||
this.document = document;
|
||||
this.project = project;
|
||||
this.indicator = indicator;
|
||||
this.reason = reason;
|
||||
myCreationModalityState = currentModalityState;
|
||||
myCreationContext = context;
|
||||
myLastCommittedText = lastCommittedText;
|
||||
myOldFileNodes = oldFileNodes;
|
||||
modificationSequence = ((DocumentEx)document).getModificationSequence();
|
||||
|
||||
@@ -544,7 +544,7 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen
|
||||
}
|
||||
actions.add(action);
|
||||
|
||||
ModalityState current = ModalityState.current();
|
||||
TransactionId current = TransactionGuard.getInstance().getContextTransaction();
|
||||
if (current != ModalityState.NON_MODAL) {
|
||||
// re-add all uncommitted documents into the queue with this new modality
|
||||
// because this client obviously expects them to commit even inside modal dialog
|
||||
@@ -846,7 +846,7 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen
|
||||
commitDocument(document);
|
||||
}
|
||||
else if (!((DocumentEx)document).isInBulkUpdate() && myPerformBackgroundCommit) {
|
||||
myDocumentCommitProcessor.commitAsynchronously(myProject, document, event, ApplicationManager.getApplication().getCurrentModalityState());
|
||||
myDocumentCommitProcessor.commitAsynchronously(myProject, document, event, TransactionGuard.getInstance().getContextTransaction());
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
+2
-3
@@ -17,9 +17,7 @@ package com.intellij.openapi.externalSystem.util;
|
||||
|
||||
import com.intellij.execution.rmi.RemoteUtil;
|
||||
import com.intellij.ide.util.PropertiesComponent;
|
||||
import com.intellij.openapi.application.Application;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.openapi.application.*;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.externalSystem.ExternalSystemAutoImportAware;
|
||||
import com.intellij.openapi.externalSystem.ExternalSystemManager;
|
||||
@@ -455,6 +453,7 @@ public class ExternalSystemApiUtil {
|
||||
}
|
||||
|
||||
public static void executeProjectChangeAction(boolean synchronous, @NotNull final DisposeAwareProjectChange task) {
|
||||
TransactionGuard.getInstance().assertWriteSafeContext(ModalityState.defaultModalityState());
|
||||
executeOnEdt(synchronous, () -> ApplicationManager.getApplication().runWriteAction(() -> task.run()));
|
||||
}
|
||||
|
||||
|
||||
+5
-1
@@ -309,5 +309,9 @@ public class ProjectSettingsStepBase extends AbstractActionWithPanel implements
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {}
|
||||
public void dispose() {
|
||||
if (myProjectGenerator instanceof WebProjectTemplate) {
|
||||
((WebProjectTemplate)myProjectGenerator).reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-1
@@ -91,7 +91,9 @@ public class ProjectRootManagerComponent extends ProjectRootManagerImpl implemen
|
||||
}
|
||||
}, project);
|
||||
|
||||
startupManager.registerStartupActivity(() -> myStartupActivityPerformed = true);
|
||||
if (!myProject.isDefault()) {
|
||||
startupManager.registerStartupActivity(() -> myStartupActivityPerformed = true);
|
||||
}
|
||||
|
||||
myHandler = new BatchUpdateListener() {
|
||||
@Override
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.intellij.injected.editor.DocumentWindowImpl;
|
||||
import com.intellij.injected.editor.EditorWindowImpl;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ReadAction;
|
||||
import com.intellij.openapi.application.TransactionGuard;
|
||||
import com.intellij.openapi.components.SettingsSavingComponent;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.EditorFactory;
|
||||
@@ -78,7 +79,7 @@ public class PsiDocumentManagerImpl extends PsiDocumentManagerBase implements Se
|
||||
connection.subscribe(DocumentBulkUpdateListener.TOPIC, new DocumentBulkUpdateListener.Adapter() {
|
||||
@Override
|
||||
public void updateFinished(@NotNull Document doc) {
|
||||
documentCommitThread.commitAsynchronously(project, doc, "Bulk update finished", ApplicationManager.getApplication().getDefaultModalityState());
|
||||
documentCommitThread.commitAsynchronously(project, doc, "Bulk update finished", TransactionGuard.getInstance().getContextTransaction());
|
||||
}
|
||||
});
|
||||
Disposer.register(project, () -> ((DocumentCommitThread)myDocumentCommitThread).cancelTasksOnProjectDispose(project));
|
||||
|
||||
@@ -77,20 +77,27 @@ public class StartupManagerImpl extends StartupManagerEx {
|
||||
myProject = project;
|
||||
}
|
||||
|
||||
private void checkNonDefaultProject() {
|
||||
LOG.assertTrue(!myProject.isDefault(), "Please don't register startup activities for the default project: they won't ever be run");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerPreStartupActivity(@NotNull Runnable runnable) {
|
||||
checkNonDefaultProject();
|
||||
LOG.assertTrue(!myPreStartupActivitiesPassed, "Registering pre startup activity that will never be run");
|
||||
myPreStartupActivities.add(runnable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerStartupActivity(@NotNull Runnable runnable) {
|
||||
checkNonDefaultProject();
|
||||
LOG.assertTrue(!myStartupActivitiesPassed, "Registering startup activity that will never be run");
|
||||
myStartupActivities.add(runnable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void registerPostStartupActivity(@NotNull Runnable runnable) {
|
||||
checkNonDefaultProject();
|
||||
LOG.assertTrue(!myPostStartupActivitiesPassed, "Registering post-startup activity that will never be run:" +
|
||||
" disposed=" + myProject.isDisposed() + "; open=" + myProject.isOpen() + "; passed=" + myStartupActivitiesPassed);
|
||||
(DumbService.isDumbAware(runnable) ? myDumbAwarePostStartupActivities : myNotDumbAwarePostStartupActivities).add(runnable);
|
||||
@@ -372,7 +379,7 @@ public class StartupManagerImpl extends StartupManagerEx {
|
||||
synchronized (this) {
|
||||
// in tests which simulate project opening, post-startup activities could have been run already.
|
||||
// Then we should act as if the project was initialized
|
||||
boolean initialized = myProject.isInitialized() || application.isUnitTestMode() && myPostStartupActivitiesPassed;
|
||||
boolean initialized = myProject.isInitialized() || myProject.isDefault() || application.isUnitTestMode() && myPostStartupActivitiesPassed;
|
||||
if (!initialized) {
|
||||
registerPostStartupActivity(action);
|
||||
return;
|
||||
|
||||
@@ -62,7 +62,6 @@ import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
public class DumbServiceImpl extends DumbService implements Disposable, ModificationTracker {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.project.DumbServiceImpl");
|
||||
private static Throwable ourForcedTrace;
|
||||
private final AtomicReference<State> myState = new AtomicReference<>(State.SMART);
|
||||
private volatile Throwable myDumbStart;
|
||||
private volatile TransactionId myDumbStartTransaction;
|
||||
@@ -169,8 +168,9 @@ public class DumbServiceImpl extends DumbService implements Disposable, Modifica
|
||||
}
|
||||
|
||||
@Override
|
||||
public void queueTask(@NotNull final DumbModeTask task) {
|
||||
public void queueTask(@NotNull DumbModeTask task) {
|
||||
if (LOG.isDebugEnabled()) LOG.debug("Scheduling task " + task);
|
||||
LOG.assertTrue(!myProject.isDefault(), "No indexing tasks should be created for default project: " + task);
|
||||
final Application application = ApplicationManager.getApplication();
|
||||
|
||||
if (application.isUnitTestMode() || application.isHeadlessEnvironment()) {
|
||||
@@ -196,7 +196,7 @@ public class DumbServiceImpl extends DumbService implements Disposable, Modifica
|
||||
|
||||
@VisibleForTesting
|
||||
void queueAsynchronousTask(@NotNull DumbModeTask task) {
|
||||
Throwable trace = ourForcedTrace != null ? ourForcedTrace : new Throwable(); // please report exceptions here to peter
|
||||
Throwable trace = new Throwable(); // please report exceptions here to peter
|
||||
TransactionId contextTransaction = TransactionGuard.getInstance().getContextTransaction();
|
||||
Runnable runnable = () -> queueTaskOnEdt(task, contextTransaction, trace);
|
||||
if (ApplicationManager.getApplication().isDispatchThread()) {
|
||||
@@ -252,20 +252,6 @@ public class DumbServiceImpl extends DumbService implements Disposable, Modifica
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static AccessToken forceDumbModeStartTrace(@NotNull Throwable trace) {
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
final Throwable prev = ourForcedTrace;
|
||||
ourForcedTrace = trace;
|
||||
return new AccessToken() {
|
||||
@Override
|
||||
public void finish() {
|
||||
//noinspection AssignmentToStaticFieldFromInstanceMethod
|
||||
ourForcedTrace = prev;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void queueUpdateFinished() {
|
||||
if (myState.compareAndSet(State.RUNNING_DUMB_TASKS, State.WAITING_FOR_FINISH)) {
|
||||
StartupManager.getInstance(myProject).runWhenProjectIsInitialized(
|
||||
|
||||
@@ -106,6 +106,8 @@ public class FileStatusManagerImpl extends FileStatusManager implements ProjectC
|
||||
}
|
||||
});
|
||||
|
||||
if (project.isDefault()) return;
|
||||
|
||||
startupManager.registerPreStartupActivity(() -> {
|
||||
DocumentAdapter documentListener = new DocumentAdapter() {
|
||||
@Override
|
||||
@@ -123,12 +125,7 @@ public class FileStatusManagerImpl extends FileStatusManager implements ProjectC
|
||||
factory.getEventMulticaster().addDocumentListener(documentListener, myProject);
|
||||
}
|
||||
});
|
||||
startupManager.registerPostStartupActivity(new DumbAwareRunnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
fileStatusesChanged();
|
||||
}
|
||||
});
|
||||
startupManager.registerPostStartupActivity((DumbAwareRunnable)() -> fileStatusesChanged());
|
||||
}
|
||||
|
||||
public void setFileStatusProvider(final FileStatusProvider fileStatusProvider) {
|
||||
|
||||
@@ -46,7 +46,7 @@ public class RefreshQueueImpl extends RefreshQueue implements Disposable {
|
||||
|
||||
public void execute(@NotNull RefreshSessionImpl session) {
|
||||
if (session.isAsynchronous()) {
|
||||
queueSession(session, session.getModalityState(), session.getTransaction());
|
||||
queueSession(session, session.getTransaction());
|
||||
}
|
||||
else {
|
||||
Application app = ApplicationManager.getApplication();
|
||||
@@ -61,13 +61,13 @@ public class RefreshQueueImpl extends RefreshQueue implements Disposable {
|
||||
"this will cause a deadlock if there are any events to fire.");
|
||||
return;
|
||||
}
|
||||
queueSession(session, ModalityState.defaultModalityState(), TransactionGuard.getInstance().getContextTransaction());
|
||||
queueSession(session, TransactionGuard.getInstance().getContextTransaction());
|
||||
session.waitFor();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void queueSession(@NotNull final RefreshSessionImpl session, @NotNull final ModalityState modality, @Nullable TransactionId transaction) {
|
||||
private void queueSession(@NotNull RefreshSessionImpl session, @Nullable TransactionId transaction) {
|
||||
myQueue.submit(() -> {
|
||||
myRefreshIndicator.start();
|
||||
try (AccessToken ignored = HeavyProcessLatch.INSTANCE.processStarted("Doing file refresh. " + session)) {
|
||||
@@ -75,11 +75,7 @@ public class RefreshQueueImpl extends RefreshQueue implements Disposable {
|
||||
}
|
||||
finally {
|
||||
myRefreshIndicator.stop();
|
||||
Application app = ApplicationManager.getApplication();
|
||||
// invokeLater might be not necessary once transactions are enforced
|
||||
app.invokeLater(
|
||||
() -> TransactionGuard.getInstance().submitTransaction(app, transaction, session::fireEvents),
|
||||
modality);
|
||||
TransactionGuard.getInstance().submitTransaction(ApplicationManager.getApplication(), transaction, session::fireEvents);
|
||||
}
|
||||
});
|
||||
myEventCounter.eventHappened(session);
|
||||
@@ -123,7 +119,7 @@ public class RefreshQueueImpl extends RefreshQueue implements Disposable {
|
||||
@NotNull
|
||||
@Override
|
||||
public RefreshSession createSession(boolean async, boolean recursively, @Nullable Runnable finishRunnable, @NotNull ModalityState state) {
|
||||
return new RefreshSessionImpl(async, recursively, finishRunnable, state);
|
||||
return new RefreshSessionImpl(async, recursively, finishRunnable, ((TransactionGuardImpl)TransactionGuard.getInstance()).getModalityTransaction(state));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+11
-16
@@ -16,9 +16,11 @@
|
||||
package com.intellij.openapi.vfs.newvfs;
|
||||
|
||||
import com.intellij.codeInsight.daemon.impl.FileStatusMap;
|
||||
import com.intellij.openapi.application.*;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.application.TransactionId;
|
||||
import com.intellij.openapi.application.WriteAction;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.DumbServiceImpl;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileManager;
|
||||
@@ -46,7 +48,6 @@ public class RefreshSessionImpl extends RefreshSession {
|
||||
private final boolean myIsAsync;
|
||||
private final boolean myIsRecursive;
|
||||
private final Runnable myFinishRunnable;
|
||||
private final ModalityState myModalityState;
|
||||
private final Throwable myStartTrace;
|
||||
private final Semaphore mySemaphore = new Semaphore();
|
||||
|
||||
@@ -57,13 +58,12 @@ public class RefreshSessionImpl extends RefreshSession {
|
||||
private volatile boolean myCancelled;
|
||||
private final TransactionId myTransaction;
|
||||
|
||||
public RefreshSessionImpl(boolean async, boolean recursive, @Nullable Runnable finishRunnable, @NotNull ModalityState modalityState) {
|
||||
RefreshSessionImpl(boolean async, boolean recursive, @Nullable Runnable finishRunnable, @Nullable TransactionId context) {
|
||||
myIsAsync = async;
|
||||
myIsRecursive = recursive;
|
||||
myFinishRunnable = finishRunnable;
|
||||
myModalityState = modalityState;
|
||||
myTransaction = ((TransactionGuardImpl)TransactionGuard.getInstance()).getModalityTransaction(modalityState);
|
||||
LOG.assertTrue(modalityState == ModalityState.NON_MODAL || modalityState != ModalityState.any(), "Refresh session should have a specific modality");
|
||||
myTransaction = context;
|
||||
LOG.assertTrue(context == ModalityState.NON_MODAL || context != ModalityState.any(), "Refresh session should have a specific modality");
|
||||
myStartTrace = rememberStartTrace();
|
||||
}
|
||||
|
||||
@@ -72,11 +72,11 @@ public class RefreshSessionImpl extends RefreshSession {
|
||||
(myIsAsync || !ApplicationManager.getApplication().isDispatchThread())) {
|
||||
return new Throwable();
|
||||
}
|
||||
return myModalityState == ModalityState.NON_MODAL ? null : new Throwable();
|
||||
return null;
|
||||
}
|
||||
|
||||
public RefreshSessionImpl(@NotNull List<VFileEvent> events) {
|
||||
this(false, false, null, ModalityState.NON_MODAL);
|
||||
RefreshSessionImpl(@NotNull List<VFileEvent> events) {
|
||||
this(false, false, null, null);
|
||||
myEvents.addAll(events);
|
||||
}
|
||||
|
||||
@@ -178,7 +178,7 @@ public class RefreshSessionImpl extends RefreshSession {
|
||||
return;
|
||||
}
|
||||
|
||||
try (AccessToken ignore = myStartTrace == null ? null : DumbServiceImpl.forceDumbModeStartTrace(myStartTrace)) {
|
||||
try {
|
||||
if (LOG.isDebugEnabled()) LOG.debug("events are about to fire: " + myEvents);
|
||||
WriteAction.run(this::fireEventsInWriteAction);
|
||||
}
|
||||
@@ -226,11 +226,6 @@ public class RefreshSessionImpl extends RefreshSession {
|
||||
return events;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
ModalityState getModalityState() {
|
||||
return myModalityState;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
TransactionId getTransaction() {
|
||||
return myTransaction;
|
||||
|
||||
@@ -21,6 +21,7 @@ import com.intellij.mock.MockDocument;
|
||||
import com.intellij.mock.MockPsiFile;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.application.TransactionGuard;
|
||||
import com.intellij.openapi.application.impl.LaterInvocator;
|
||||
import com.intellij.openapi.command.WriteCommandAction;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
@@ -563,6 +564,24 @@ public class PsiDocumentManagerImplTest extends PlatformTestCase {
|
||||
assertTrue(getPsiDocumentManager().isCommitted(document));
|
||||
}
|
||||
|
||||
public void testBackgroundCommitInDialogInTransaction() throws IOException {
|
||||
VirtualFile vFile = getVirtualFile(createTempFile("a.txt", "abc"));
|
||||
PsiFile psiFile = findFile(vFile);
|
||||
Document document = getDocument(psiFile);
|
||||
|
||||
TransactionGuard.submitTransaction(myProject, () -> {
|
||||
WriteCommandAction.runWriteCommandAction(myProject, () -> {
|
||||
document.insertString(0, "x");
|
||||
LaterInvocator.enterModal(new Object());
|
||||
assertFalse(getPsiDocumentManager().isCommitted(document));
|
||||
});
|
||||
|
||||
waitTenSecondsForCommit(document);
|
||||
assertTrue(getPsiDocumentManager().isCommitted(document));
|
||||
});
|
||||
UIUtil.dispatchAllInvocationEvents();
|
||||
}
|
||||
|
||||
public void testChangeDocumentThenEnterModalDialogThenCallPerformWhenAllCommittedShouldFireWhileInsideModal() throws IOException {
|
||||
VirtualFile vFile = getVirtualFile(createTempFile("a.txt", "abc"));
|
||||
PsiFile psiFile = findFile(vFile);
|
||||
|
||||
@@ -43,7 +43,7 @@ public class VcsInitialization implements Disposable {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vcs.impl.VcsInitialization");
|
||||
|
||||
private final List<Pair<VcsInitObject, Runnable>> myList = new ArrayList<>();
|
||||
private final Object myLock;
|
||||
private final Object myLock = new Object();
|
||||
@NotNull private final Project myProject;
|
||||
|
||||
// the initialization lifecycle: IDLE -(on startup completion)-> RUNNING -(on all tasks executed or project canceled)-> FINISHED
|
||||
@@ -55,7 +55,7 @@ public class VcsInitialization implements Disposable {
|
||||
|
||||
VcsInitialization(@NotNull final Project project) {
|
||||
myProject = project;
|
||||
myLock = new Object();
|
||||
if (project.isDefault()) return;
|
||||
|
||||
StartupManager.getInstance(project).registerPostStartupActivity((DumbAwareRunnable)() -> {
|
||||
if (project.isDisposed()) return;
|
||||
|
||||
@@ -18,6 +18,8 @@ package git4idea.merge;
|
||||
import com.intellij.notification.Notification;
|
||||
import com.intellij.notification.NotificationListener;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.application.TransactionGuard;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
@@ -231,6 +233,7 @@ public class GitConflictResolver {
|
||||
}
|
||||
|
||||
private void showMergeDialog(@NotNull final Collection<VirtualFile> initiallyUnmergedFiles) {
|
||||
TransactionGuard.getInstance().assertWriteSafeContext(ModalityState.defaultModalityState());
|
||||
ApplicationManager.getApplication().invokeAndWait(() -> {
|
||||
MergeProvider mergeProvider = new GitMergeProvider(myProject, myParams.reverse);
|
||||
myVcsHelper.showMergeDialog(new ArrayList<>(initiallyUnmergedFiles), mergeProvider, myParams.myMergeDialogCustomizer);
|
||||
|
||||
+1
-1
@@ -58,7 +58,7 @@ public class Java15FormInspection extends BaseFormInspection {
|
||||
final PsiMethod getter = PropertyUtil.findPropertyGetter(aClass, prop.getName(), false, true);
|
||||
if (getter == null) continue;
|
||||
final LanguageLevel languageLevel = LanguageLevelUtil.getEffectiveLanguageLevel(module);
|
||||
if (Java15APIUsageInspection.isForbiddenApiUsage(getter, languageLevel)) {
|
||||
if (Java15APIUsageInspection.getLastIncompatibleLanguageLevel(getter, languageLevel) != null) {
|
||||
registerError(component, collector, prop, "@since " + Java15APIUsageInspection.getShortName(languageLevel));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.jetbrains.python.codeInsight.typing
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.application.PathManager
|
||||
import com.intellij.openapi.projectRoots.Sdk
|
||||
import com.intellij.openapi.vfs.StandardFileSystems
|
||||
@@ -58,6 +59,9 @@ object PyTypeShed {
|
||||
return true
|
||||
}
|
||||
if (isInThirdPartyLibraries(root)) {
|
||||
if (ApplicationManager.getApplication().isUnitTestMode) {
|
||||
return true
|
||||
}
|
||||
val pyPIPackage = PyPIPackageUtil.PACKAGES_TOPLEVEL[topLevelPackage] ?: topLevelPackage
|
||||
val packages = PyPackageManagers.getInstance().forSdk(sdk).packages ?: return true
|
||||
return PyPackageUtil.findPackage(packages, pyPIPackage) != null
|
||||
|
||||
@@ -19,10 +19,7 @@ import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.intellij.execution.ExecutionException;
|
||||
import com.intellij.openapi.application.Application;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.openapi.application.*;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleManager;
|
||||
@@ -426,6 +423,7 @@ public class PythonSdkUpdater implements StartupActivity {
|
||||
final SdkModificator modificatorToGetRoots = sdkModificator != null ? sdkModificator : sdk.getSdkModificator();
|
||||
final List<VirtualFile> currentSdkPaths = Arrays.asList(modificatorToGetRoots.getRoots(OrderRootType.CLASSES));
|
||||
if (forceCommit || !Sets.newHashSet(sdkPaths).equals(Sets.newHashSet(currentSdkPaths))) {
|
||||
TransactionGuard.getInstance().assertWriteSafeContext(ModalityState.defaultModalityState());
|
||||
ApplicationManager.getApplication().invokeAndWait(() -> {
|
||||
final Sdk sdkInsideInvoke = PythonSdkType.findSdkByKey(key);
|
||||
final SdkModificator modificatorToCommit = sdkModificator != null ? sdkModificator :
|
||||
|
||||
@@ -54,6 +54,7 @@ class PyUniversalTestLegacyInteropInitializer {
|
||||
// Delegate to project initialization
|
||||
ApplicationManager.getApplication().messageBus.connect().subscribe(ProjectLifecycleListener.TOPIC, object : ProjectLifecycleListener {
|
||||
override fun projectComponentsInitialized(project: Project) {
|
||||
if (project.isDefault) return
|
||||
if (project.isInitialized) {
|
||||
projectInitialized(project)
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user