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:
@@ -32,7 +32,6 @@ import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.wm.WindowManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.controlFlow.DefUseUtil;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.searches.ReferencesSearch;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
@@ -78,7 +77,7 @@ public class InlineLocalHandler extends JavaInlineActionHandler {
|
||||
|
||||
final String localName = local.getName();
|
||||
|
||||
final Query<PsiReference> query = ReferencesSearch.search(local, GlobalSearchScope.allScope(project), false);
|
||||
final Query<PsiReference> query = ReferencesSearch.search(local, local.getUseScope());
|
||||
if (query.findFirst() == null){
|
||||
LOG.assertTrue(refExpr == null);
|
||||
String message = RefactoringBundle.message("variable.is.never.used", localName);
|
||||
|
||||
+54
-54
@@ -42,8 +42,10 @@ import com.intellij.refactoring.util.classMembers.MemberInfoStorage;
|
||||
import com.intellij.usageView.UsageInfo;
|
||||
import com.intellij.usageView.UsageViewDescriptor;
|
||||
import com.intellij.util.ArrayUtilRt;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -171,25 +173,26 @@ public class InlineSuperClassRefactoringProcessor extends FixableUsagesRefactori
|
||||
final PsiMethod[] superConstructors = mySuperClass.getConstructors();
|
||||
for (PsiMethod constructor : targetClass.getConstructors()) {
|
||||
final PsiCodeBlock constrBody = constructor.getBody();
|
||||
LOG.assertTrue(constrBody != null);
|
||||
final PsiStatement[] statements = constrBody.getStatements();
|
||||
if (statements.length > 0) {
|
||||
final PsiStatement firstConstrStatement = statements[0];
|
||||
if (firstConstrStatement instanceof PsiExpressionStatement) {
|
||||
final PsiExpression expression = ((PsiExpressionStatement)firstConstrStatement).getExpression();
|
||||
if (expression instanceof PsiMethodCallExpression) {
|
||||
final PsiReferenceExpression methodExpression = ((PsiMethodCallExpression)expression).getMethodExpression();
|
||||
if (methodExpression.getText().equals(PsiKeyword.SUPER)) {
|
||||
final PsiMethod superConstructor = ((PsiMethodCallExpression)expression).resolveMethod();
|
||||
if (superConstructor != null && superConstructor.getBody() != null) {
|
||||
usages.add(new InlineSuperCallUsageInfo((PsiMethodCallExpression)expression));
|
||||
continue;
|
||||
if (constrBody != null) {
|
||||
final PsiStatement[] statements = constrBody.getStatements();
|
||||
if (statements.length > 0) {
|
||||
final PsiStatement firstConstrStatement = statements[0];
|
||||
if (firstConstrStatement instanceof PsiExpressionStatement) {
|
||||
final PsiExpression expression = ((PsiExpressionStatement)firstConstrStatement).getExpression();
|
||||
if (expression instanceof PsiMethodCallExpression) {
|
||||
final PsiReferenceExpression methodExpression = ((PsiMethodCallExpression)expression).getMethodExpression();
|
||||
if (methodExpression.getText().equals(PsiKeyword.SUPER)) {
|
||||
final PsiMethod superConstructor = ((PsiMethodCallExpression)expression).resolveMethod();
|
||||
if (superConstructor != null && superConstructor.getBody() != null) {
|
||||
usages.add(new InlineSuperCallUsageInfo((PsiMethodCallExpression)expression));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//insert implicit call to super
|
||||
for (PsiMethod superConstructor : superConstructors) {
|
||||
if (superConstructor.getParameterList().getParametersCount() == 0) {
|
||||
@@ -274,50 +277,44 @@ public class InlineSuperClassRefactoringProcessor extends FixableUsagesRefactori
|
||||
}
|
||||
|
||||
protected void performRefactoring(@NotNull final UsageInfo[] usages) {
|
||||
final DocCommentPolicy docPolicy = new DocCommentPolicy(myPolicy);
|
||||
new PushDownProcessor(mySuperClass, myMemberInfos, docPolicy) {
|
||||
//push down conflicts are already collected
|
||||
@Override
|
||||
protected boolean showConflicts(@NotNull MultiMap<PsiElement, String> conflicts, UsageInfo[] usages) {
|
||||
return true;
|
||||
}
|
||||
try {
|
||||
final UsageInfo[] infos = ContainerUtil.map2Array(myTargetClasses, UsageInfo.class, new Function<PsiClass, UsageInfo>() {
|
||||
@Override
|
||||
public UsageInfo fun(PsiClass psiClass) {
|
||||
return new UsageInfo(psiClass);
|
||||
}
|
||||
});
|
||||
new PushDownProcessor(mySuperClass, myMemberInfos, new DocCommentPolicy(myPolicy)).pushDownToClasses(infos);
|
||||
|
||||
@Override
|
||||
protected void performRefactoring(@NotNull UsageInfo[] pushDownUsages) {
|
||||
if (myCurrentInheritor != null) {
|
||||
pushDownToDedicatedClass(myCurrentInheritor);
|
||||
} else {
|
||||
super.performRefactoring(pushDownUsages);
|
||||
}
|
||||
CommonRefactoringUtil.sortDepthFirstRightLeftOrder(usages);
|
||||
for (UsageInfo usageInfo : usages) {
|
||||
if (!(usageInfo instanceof ReplaceExtendsListUsageInfo || usageInfo instanceof RemoveImportUsageInfo)) {
|
||||
try {
|
||||
((FixableUsageInfo)usageInfo).fixUsage();
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
LOG.info(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
replaceInnerTypeUsages();
|
||||
|
||||
//postpone broken hierarchy
|
||||
for (UsageInfo usage : usages) {
|
||||
if (usage instanceof ReplaceExtendsListUsageInfo || usage instanceof RemoveImportUsageInfo) {
|
||||
((FixableUsageInfo)usage).fixUsage();
|
||||
}
|
||||
}
|
||||
if (myCurrentInheritor == null) {
|
||||
CommonRefactoringUtil.sortDepthFirstRightLeftOrder(usages);
|
||||
for (UsageInfo usageInfo : usages) {
|
||||
if (!(usageInfo instanceof ReplaceExtendsListUsageInfo || usageInfo instanceof RemoveImportUsageInfo)) {
|
||||
try {
|
||||
mySuperClass.delete();
|
||||
((FixableUsageInfo)usageInfo).fixUsage();
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
LOG.error(e);
|
||||
LOG.info(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}.run();
|
||||
|
||||
replaceInnerTypeUsages();
|
||||
|
||||
//postpone broken hierarchy
|
||||
for (UsageInfo usage : usages) {
|
||||
if (usage instanceof ReplaceExtendsListUsageInfo || usage instanceof RemoveImportUsageInfo) {
|
||||
((FixableUsageInfo)usage).fixUsage();
|
||||
}
|
||||
}
|
||||
|
||||
//delete the class if all refs replaced
|
||||
if (myCurrentInheritor == null) {
|
||||
mySuperClass.delete();
|
||||
}
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -357,7 +354,7 @@ public class InlineSuperClassRefactoringProcessor extends FixableUsagesRefactori
|
||||
public void visitTypeElement(final PsiTypeElement typeElement) {
|
||||
super.visitTypeElement(typeElement);
|
||||
final PsiType superClassType = typeElement.getType();
|
||||
if (PsiUtil.resolveClassInType(superClassType) == mySuperClass) {
|
||||
if (PsiUtil.resolveClassInClassTypeOnly(superClassType) == mySuperClass) {
|
||||
PsiSubstitutor subst = getSuperClassSubstitutor(superClassType, targetClassType, resolveHelper, targetClass);
|
||||
replacementMap.put(new UsageInfo(typeElement), elementFactory.createTypeElement(elementFactory.createType(targetClass, subst)));
|
||||
}
|
||||
@@ -370,8 +367,11 @@ public class InlineSuperClassRefactoringProcessor extends FixableUsagesRefactori
|
||||
if (PsiUtil.resolveClassInType(superClassType) == mySuperClass) {
|
||||
PsiSubstitutor subst = getSuperClassSubstitutor(superClassType, targetClassType, resolveHelper, targetClass);
|
||||
try {
|
||||
replacementMap.put(new UsageInfo(expression), elementFactory.createExpressionFromText("new " + elementFactory.createType(
|
||||
targetClass, subst).getCanonicalText() + expression.getArgumentList().getText(), expression));
|
||||
final String typeCanonicalText = elementFactory.createType(targetClass, subst).getCanonicalText();
|
||||
final PsiJavaCodeReferenceElement classReference = expression.getClassOrAnonymousClassReference();
|
||||
if (classReference != null) {
|
||||
replacementMap.put(new UsageInfo(classReference), elementFactory.createReferenceFromText(typeCanonicalText, expression));
|
||||
}
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
LOG.error(e);
|
||||
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
class Test {
|
||||
public static Test[] getArray() {
|
||||
return new Test[0];
|
||||
}
|
||||
|
||||
public static Test[] getArrayWithInitializer() {
|
||||
return new Test[]{};
|
||||
}
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
class Super {
|
||||
public static Super[] getArray() {
|
||||
return new Super[0];
|
||||
}
|
||||
|
||||
public static Super[] getArrayWithInitializer() {
|
||||
return new Super[]{};
|
||||
}
|
||||
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
class Test extends Super {}
|
||||
+1
-1
@@ -2,6 +2,6 @@ class Test {
|
||||
private final String field;
|
||||
|
||||
Test(){
|
||||
field = "text";
|
||||
this.field = "text";
|
||||
}
|
||||
}
|
||||
@@ -71,6 +71,7 @@ public class InlineSuperClassTest extends MultiFileTestCase {
|
||||
public void testInterfaceHierarchyWithSubstitution() { doTest(); }
|
||||
public void testTypeParameterBound() { doTest();}
|
||||
public void testInlineInterfaceDoNotChangeConstructor() { doTest(); }
|
||||
public void testArrayTypeElements() { doTest(); }
|
||||
|
||||
private void doTest() {
|
||||
doTest(false, false);
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
package com.intellij.openapi.application;
|
||||
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -29,7 +28,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
* and process UI events in other ways: it's guaranteed that no one will be able to sneak in with an unexpected model change using
|
||||
* {@link javax.swing.SwingUtilities#invokeLater(Runnable)} or analogs.<p/>
|
||||
*
|
||||
* Transactions are run on UI thread. They have read access by default.<p/>
|
||||
* Transactions are run on UI thread. They have read access by default. All write actions should be performed inside a transaction.<p/>
|
||||
*
|
||||
* The recommended way to perform a transaction is to invoke {@link #submitTransaction(Runnable)}. It either runs the transaction immediately
|
||||
* (if on UI thread and there's no other transaction running) or queues it to invoke at some later moment, when it becomes possible.<p/>
|
||||
@@ -40,31 +39,43 @@ import org.jetbrains.annotations.NotNull;
|
||||
* the main transaction and executed immediately. Use {@link #acceptNestedTransactions(TransactionKind...)} for that. Inner transactions
|
||||
* should be given some kind in such circumstances: {@link #submitMergeableTransaction(TransactionKind, Runnable)}.
|
||||
*
|
||||
* <p><h1>FAQ</h1></p>
|
||||
*
|
||||
* Q: I've got <b>"Write access is allowed from model transactions only"</b> exception, what do I do?<br/>
|
||||
* A: Add a transaction somewhere into the call stack, to the outermost callee where having read/write model consistency is needed.
|
||||
* If it's a user action, transaction should be synchronous (see {@link #startSynchronousTransaction(TransactionKind)}. For AnAction
|
||||
* inheritors, {@link WrapInTransaction} annotation might be handy. Note that not all actions need to be wrapped into transactions, only
|
||||
* those that require the model to be consistent. For example, actions that display settings dialogs or VCS actions are most likely exempt.
|
||||
* <p/>
|
||||
*
|
||||
* If the exception occurs not inside a user action, it's probably from some kind of "invokeLater".
|
||||
* Then, replace "invokeLater" with {@link #submitTransaction(Runnable)} or
|
||||
* {@link #submitMergeableTransaction(TransactionKind, Runnable)} call.<p/>
|
||||
*
|
||||
* Q: I've got <b>"Nested transactions are not allowed"</b> exception, what do I do?<br/>
|
||||
* A: First, find the place in the stack where the outer transaction is started. Then, see if there is any Swing event pumping
|
||||
* in between two transactions (e.g. a dialog is shown). If not, one of two transactions is superfluous, remove it. If there
|
||||
* is event pumping, check if the client code (e.g. the one showing the dialog) is prepared to the nested model modifications
|
||||
* of the specified kinds. For example, refactoring dialogs might be prepared to {@link TransactionKind#TEXT_EDITING} kind
|
||||
* (for text field editing inside the dialogs) but not
|
||||
* other model changes, e.g. root changes. The outer transaction code might then specify which kinds it's prepared to (by using
|
||||
* {@link #acceptNestedTransactions(TransactionKind...)}), and the inner transaction code should have the very same transaction kind
|
||||
* (by using {@link #submitMergeableTransaction(TransactionKind, Runnable)} or {@link #startSynchronousTransaction(TransactionKind)}).
|
||||
* If the nested transaction is not expected by the outer code, it must be made asynchronous by using either {@link #submitTransaction(Runnable)}
|
||||
* or {@link #submitMergeableTransaction(TransactionKind, Runnable)}.
|
||||
* <p/>
|
||||
*
|
||||
* Q: What's the difference between transactions and read/write actions and commands ({@link com.intellij.openapi.command.CommandProcessor})?<br/>
|
||||
* A: Transactions are more abstract and can contain several write actions and even commands inside. Read/write actions guarantee that no
|
||||
* one else will modify the model, while transactions allow for some modification, but in a way controlled by transaction kinds. Commands
|
||||
* are used for tracking document changes for undo/redo functionality, so they're orthogonal to transactions.
|
||||
*
|
||||
* @see Application#runReadAction(Runnable)
|
||||
* @see Application#runWriteAction(Runnable)
|
||||
* @since 146.*
|
||||
* @author peter
|
||||
*/
|
||||
public abstract class TransactionGuard {
|
||||
/**
|
||||
* This kind represents document modifications via editor actions, code completion and document->PSI commit.
|
||||
* @see com.intellij.psi.PsiDocumentManager#commitDocument(Document)
|
||||
*/
|
||||
public static final TransactionKind TEXT_EDITING = new TransactionKind("TEXT_EDITING");
|
||||
/**
|
||||
* This kind represents any model modifications:
|
||||
* <li>PSI or document changes
|
||||
* <li>Virtual file system changes, e.g. files created/deleted/renamed/content-changed,
|
||||
* caused by refresh process or explicit operations.
|
||||
* <li>Project root set change
|
||||
* <li>Dumb mode (reindexing) start/finish, (see {@link com.intellij.openapi.project.DumbService}).
|
||||
*/
|
||||
public static final TransactionKind ANY_CHANGE = new TransactionKind("ANY_CHANGE");
|
||||
|
||||
/**
|
||||
* Transactions of this kind won't be merged into other transactions
|
||||
*/
|
||||
public static final TransactionKind NO_MERGE = new TransactionKind("NO_MERGE");
|
||||
|
||||
public static TransactionGuard getInstance() {
|
||||
return ServiceManager.getService(TransactionGuard.class);
|
||||
@@ -75,12 +86,12 @@ public abstract class TransactionGuard {
|
||||
* The code will be run on Swing thread immediately or after all other queued transactions (if any) have been completed.<p/>
|
||||
*
|
||||
* For more advanced version, see {@link #submitMergeableTransaction(TransactionKind, Runnable)}.
|
||||
* Transactions submitted via this method use {@link #NO_MERGE} kind.
|
||||
* Transactions submitted via this method use {@link TransactionKind#NO_MERGE} kind.
|
||||
*
|
||||
* @param transaction code to execute inside a transaction.
|
||||
*/
|
||||
public static void submitTransaction(@NotNull Runnable transaction) {
|
||||
getInstance().submitMergeableTransaction(NO_MERGE, transaction);
|
||||
getInstance().submitMergeableTransaction(TransactionKind.NO_MERGE, transaction);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -110,7 +121,7 @@ public abstract class TransactionGuard {
|
||||
* and executes the provided code immediately. Otherwise
|
||||
* adds the runnable to a queue. When all transactions scheduled before this one are finished, executes the given
|
||||
* runnable under a transaction.
|
||||
* @param kind a kind object to enable transaction merging or {@link #NO_MERGE}, if no merging is required.
|
||||
* @param kind a kind object to enable transaction merging or {@link TransactionKind#NO_MERGE}, if no merging is required.
|
||||
* @param transaction code to execute inside a transaction.
|
||||
*/
|
||||
public abstract void submitMergeableTransaction(@NotNull TransactionKind kind, @NotNull Runnable transaction);
|
||||
@@ -126,20 +137,4 @@ public abstract class TransactionGuard {
|
||||
*/
|
||||
@NotNull
|
||||
public abstract AccessToken acceptNestedTransactions(TransactionKind... kinds);
|
||||
|
||||
/**
|
||||
* A kind of transaction used in {@link #acceptNestedTransactions(TransactionKind...)}
|
||||
*/
|
||||
public static final class TransactionKind {
|
||||
private final String myName;
|
||||
|
||||
public TransactionKind(@NotNull String name) {
|
||||
myName = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return myName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2000-2016 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.
|
||||
*/
|
||||
package com.intellij.openapi.application;
|
||||
|
||||
import com.intellij.openapi.editor.Document;
|
||||
|
||||
/**
|
||||
* A kind of transaction used in {@link TransactionGuard#submitMergeableTransaction(TransactionKind, Runnable)}
|
||||
* and {@link TransactionGuard#acceptNestedTransactions(TransactionKind...)}.
|
||||
*/
|
||||
public interface TransactionKind {
|
||||
/**
|
||||
* Same as {@link Common#TEXT_EDITING}
|
||||
*/
|
||||
TransactionKind TEXT_EDITING = Common.TEXT_EDITING;
|
||||
|
||||
/**
|
||||
* Same as {@link Common#NO_MERGE}
|
||||
*/
|
||||
TransactionKind NO_MERGE = Common.NO_MERGE;
|
||||
|
||||
/**
|
||||
* Same as {@link Common#ANY_CHANGE}
|
||||
*/
|
||||
TransactionKind ANY_CHANGE = Common.ANY_CHANGE;
|
||||
|
||||
/**
|
||||
* An auxiliary enum to make it possible to use transaction kinds in annotations
|
||||
*/
|
||||
enum Common implements TransactionKind {
|
||||
|
||||
/**
|
||||
* This kind represents document modifications via editor actions, code completion and document->PSI commit.
|
||||
* @see com.intellij.psi.PsiDocumentManager#commitDocument(Document)
|
||||
*/
|
||||
TEXT_EDITING,
|
||||
|
||||
/**
|
||||
* This kind represents any model modifications:
|
||||
* <li>PSI or document changes
|
||||
* <li>Virtual file system changes, e.g. files created/deleted/renamed/content-changed,
|
||||
* caused by refresh process or explicit operations.
|
||||
* <li>Project root set change
|
||||
* <li>Dumb mode (reindexing) start/finish, (see {@link com.intellij.openapi.project.DumbService}).
|
||||
*/
|
||||
ANY_CHANGE,
|
||||
|
||||
/**
|
||||
* Transactions of this kind won't be merged into other transactions
|
||||
*/
|
||||
NO_MERGE
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.intellij.openapi.application;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* Add this annotation to actions (AnAction inheritors) to make them run inside a transaction.
|
||||
*
|
||||
* @see TransactionGuard
|
||||
* @since 146.*
|
||||
* @author peter
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Inherited
|
||||
public @interface WrapInTransaction {
|
||||
|
||||
/**
|
||||
* @return the kind of transaction to wrap the action into. By default, it's {@link TransactionKind#NO_MERGE}.
|
||||
*/
|
||||
TransactionKind.Common value() default TransactionKind.Common.NO_MERGE;
|
||||
}
|
||||
@@ -39,7 +39,7 @@ public class TransactionGuardImpl extends TransactionGuard {
|
||||
@NotNull
|
||||
public AccessToken startSynchronousTransaction(@NotNull TransactionKind kind) throws IllegalStateException {
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
if (kind != NO_MERGE && myMergeableKinds.contains(kind)) {
|
||||
if (kind != TransactionKind.NO_MERGE && myMergeableKinds.contains(kind)) {
|
||||
return AccessToken.EMPTY_ACCESS_TOKEN;
|
||||
}
|
||||
if (myInsideTransaction) {
|
||||
@@ -68,7 +68,7 @@ public class TransactionGuardImpl extends TransactionGuard {
|
||||
|
||||
Runnable next = myQueue.poll();
|
||||
if (next != null) {
|
||||
runSyncTransaction(NO_MERGE, next);
|
||||
runSyncTransaction(TransactionKind.NO_MERGE, next);
|
||||
}
|
||||
}
|
||||
}, app.getDisposed());
|
||||
@@ -95,7 +95,7 @@ public class TransactionGuardImpl extends TransactionGuard {
|
||||
Runnable runnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!myInsideTransaction || kind != NO_MERGE && myMergeableKinds.contains(kind)) {
|
||||
if (!myInsideTransaction || kind != TransactionKind.NO_MERGE && myMergeableKinds.contains(kind)) {
|
||||
runSyncTransaction(kind, transaction);
|
||||
}
|
||||
else {
|
||||
|
||||
+2
-1
@@ -35,6 +35,7 @@ import com.intellij.openapi.actionSystem.IdeActions;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.Result;
|
||||
import com.intellij.openapi.application.TransactionGuard;
|
||||
import com.intellij.openapi.application.TransactionKind;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
import com.intellij.openapi.command.WriteCommandAction;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
@@ -476,7 +477,7 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
|
||||
|
||||
void disposeIndicator() {
|
||||
// our offset map should be disposed under write action, so that duringCompletion (read action) won't access it after disposing
|
||||
TransactionGuard.getInstance().submitMergeableTransaction(TransactionGuard.TEXT_EDITING, () ->
|
||||
TransactionGuard.getInstance().submitMergeableTransaction(TransactionKind.TEXT_EDITING, () ->
|
||||
ApplicationManager.getApplication().runWriteAction(() -> Disposer.dispose(this)));
|
||||
}
|
||||
|
||||
|
||||
@@ -416,6 +416,8 @@ public class CtrlMouseHandler extends AbstractProjectComponent {
|
||||
public abstract DocInfo getInfo();
|
||||
|
||||
public abstract boolean isValid(@NotNull Document document);
|
||||
|
||||
public abstract boolean isNavigatable();
|
||||
|
||||
public abstract void showDocInfo(@NotNull DocumentationManager docManager);
|
||||
|
||||
@@ -467,11 +469,15 @@ public class CtrlMouseHandler extends AbstractProjectComponent {
|
||||
public boolean isValid(@NotNull Document document) {
|
||||
if (!myTargetElement.isValid()) return false;
|
||||
if (!myElementAtPointer.isValid()) return false;
|
||||
if (myTargetElement == myElementAtPointer) return false;
|
||||
|
||||
return rangesAreCorrect(document);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNavigatable() {
|
||||
return myTargetElement != myElementAtPointer && myTargetElement != myElementAtPointer.getParent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showDocInfo(@NotNull DocumentationManager docManager) {
|
||||
docManager.showJavaDocInfo(myTargetElement, myElementAtPointer, null);
|
||||
@@ -499,6 +505,11 @@ public class CtrlMouseHandler extends AbstractProjectComponent {
|
||||
return rangesAreCorrect(document);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNavigatable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showDocInfo(@NotNull DocumentationManager docManager) {
|
||||
// Do nothing
|
||||
@@ -612,6 +623,11 @@ public class CtrlMouseHandler extends AbstractProjectComponent {
|
||||
public boolean isValid(@NotNull Document document) {
|
||||
return element.isValid();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNavigatable() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -871,7 +887,9 @@ public class CtrlMouseHandler extends AbstractProjectComponent {
|
||||
}
|
||||
else {
|
||||
// highlighter already set
|
||||
internalComponent.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
|
||||
if (info.isNavigatable()) {
|
||||
internalComponent.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -960,11 +978,15 @@ public class CtrlMouseHandler extends AbstractProjectComponent {
|
||||
internalComponent.addKeyListener(myEditorKeyListener);
|
||||
editor.getScrollingModel().addVisibleAreaListener(myVisibleAreaListener);
|
||||
final Cursor cursor = internalComponent.getCursor();
|
||||
internalComponent.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
|
||||
if (info.isNavigatable()) {
|
||||
internalComponent.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
|
||||
}
|
||||
myFileEditorManager.addFileEditorManagerListener(myFileEditorManagerListener);
|
||||
|
||||
List<RangeHighlighter> highlighters = new ArrayList<RangeHighlighter>();
|
||||
TextAttributes attributes = myEditorColorsManager.getGlobalScheme().getAttributes(EditorColors.REFERENCE_HYPERLINK_COLOR);
|
||||
TextAttributes attributes = info.isNavigatable()
|
||||
? myEditorColorsManager.getGlobalScheme().getAttributes(EditorColors.REFERENCE_HYPERLINK_COLOR)
|
||||
: new TextAttributes(null, HintUtil.INFORMATION_COLOR, null, null, Font.PLAIN);
|
||||
for (TextRange range : info.getRanges()) {
|
||||
TextAttributes attr = NavigationUtil.patchAttributesColor(attributes, range, editor);
|
||||
final RangeHighlighter highlighter = editor.getMarkupModel().addRangeHighlighter(range.getStartOffset(), range.getEndOffset(),
|
||||
|
||||
@@ -225,6 +225,7 @@ public final class NavigationUtil {
|
||||
*/
|
||||
@SuppressWarnings("UseJBColor")
|
||||
public static TextAttributes patchAttributesColor(TextAttributes attributes, @NotNull TextRange range, @NotNull Editor editor) {
|
||||
if (attributes.getForegroundColor() == null && attributes.getEffectColor() == null) return attributes;
|
||||
MarkupModel model = DocumentMarkupModel.forDocument(editor.getDocument(), editor.getProject(), false);
|
||||
if (model != null) {
|
||||
if (!((MarkupModelEx)model).processRangeHighlightersOverlappingWith(range.getStartOffset(), range.getEndOffset(),
|
||||
|
||||
+20
-21
@@ -159,25 +159,7 @@ public abstract class AbstractPushDownProcessor extends BaseRefactoringProcessor
|
||||
@Override
|
||||
protected void performRefactoring(@NotNull UsageInfo[] usages) {
|
||||
try {
|
||||
myDelegate.prepareToPush(myPushDownData);
|
||||
final PsiElement sourceClass = myPushDownData.getSourceClass();
|
||||
if (mySubClassData != null) {
|
||||
final PsiElement subClass = myDelegate.createSubClass(sourceClass, mySubClassData);
|
||||
if (subClass != null) {
|
||||
myDelegate.pushDownToClass(subClass, myPushDownData);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (UsageInfo usage : usages) {
|
||||
final PsiElement element = usage.getElement();
|
||||
if (element != null) {
|
||||
final PushDownDelegate targetDelegate = PushDownDelegate.findDelegateForTarget(sourceClass, element);
|
||||
if (targetDelegate != null) {
|
||||
targetDelegate.pushDownToClass(element, myPushDownData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pushDownToClasses(usages);
|
||||
myDelegate.removeFromSourceClass(myPushDownData);
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
@@ -185,8 +167,25 @@ public abstract class AbstractPushDownProcessor extends BaseRefactoringProcessor
|
||||
}
|
||||
}
|
||||
|
||||
protected void pushDownToDedicatedClass(PsiElement currentInheritor) {
|
||||
public void pushDownToClasses(@NotNull UsageInfo[] usages) {
|
||||
myDelegate.prepareToPush(myPushDownData);
|
||||
myDelegate.pushDownToClass(currentInheritor, myPushDownData);
|
||||
final PsiElement sourceClass = myPushDownData.getSourceClass();
|
||||
if (mySubClassData != null) {
|
||||
final PsiElement subClass = myDelegate.createSubClass(sourceClass, mySubClassData);
|
||||
if (subClass != null) {
|
||||
myDelegate.pushDownToClass(subClass, myPushDownData);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (UsageInfo usage : usages) {
|
||||
final PsiElement element = usage.getElement();
|
||||
if (element != null) {
|
||||
final PushDownDelegate targetDelegate = PushDownDelegate.findDelegateForTarget(sourceClass, element);
|
||||
if (targetDelegate != null) {
|
||||
targetDelegate.pushDownToClass(element, myPushDownData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,10 +15,7 @@
|
||||
*/
|
||||
package com.intellij.notification;
|
||||
|
||||
import com.intellij.openapi.actionSystem.ActionPlaces;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.actionSystem.ex.ActionUtil;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -28,6 +25,7 @@ import com.intellij.openapi.ui.popup.LightweightWindowEvent;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.reference.SoftReference;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -41,6 +39,7 @@ import java.util.List;
|
||||
*/
|
||||
public class Notification {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.notification.Notification");
|
||||
private static final DataKey<Notification> KEY = DataKey.create("Notification");
|
||||
|
||||
private final String myGroupId;
|
||||
private Icon myIcon;
|
||||
@@ -195,8 +194,20 @@ public class Notification {
|
||||
return ContainerUtil.notNullize(myActions);
|
||||
}
|
||||
|
||||
public static void fire(@NotNull AnAction action) {
|
||||
AnActionEvent event = AnActionEvent.createFromAnAction(action, null, ActionPlaces.UNKNOWN, DataContext.EMPTY_CONTEXT);
|
||||
@NotNull
|
||||
public static Notification get(@NotNull AnActionEvent e) {
|
||||
//noinspection ConstantConditions
|
||||
return e.getData(KEY);
|
||||
}
|
||||
|
||||
public static void fire(@NotNull final Notification notification, @NotNull AnAction action) {
|
||||
AnActionEvent event = AnActionEvent.createFromAnAction(action, null, ActionPlaces.UNKNOWN, new DataContext() {
|
||||
@Nullable
|
||||
@Override
|
||||
public Object getData(@NonNls String dataId) {
|
||||
return KEY.getName().equals(dataId) ? notification : null;
|
||||
}
|
||||
});
|
||||
if (ActionUtil.lastUpdateAndCheckDumb(action, event, false)) {
|
||||
ActionUtil.performActionDumbAware(action, event);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2000-2016 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.
|
||||
*/
|
||||
package com.intellij.notification;
|
||||
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author Alexander Lobas
|
||||
*/
|
||||
public abstract class NotificationAction extends AnAction {
|
||||
public NotificationAction(@Nullable String text) {
|
||||
super(text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
actionPerformed(e, Notification.get(e));
|
||||
}
|
||||
|
||||
public abstract void actionPerformed(@NotNull AnActionEvent e, @NotNull Notification notification);
|
||||
}
|
||||
@@ -16,7 +16,10 @@
|
||||
package com.intellij.openapi.actionSystem.ex;
|
||||
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.application.AccessToken;
|
||||
import com.intellij.openapi.application.ApplicationNamesInfo;
|
||||
import com.intellij.openapi.application.TransactionGuard;
|
||||
import com.intellij.openapi.application.WrapInTransaction;
|
||||
import com.intellij.openapi.project.DumbService;
|
||||
import com.intellij.openapi.project.IndexNotReadyException;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -187,12 +190,18 @@ public class ActionUtil {
|
||||
}
|
||||
|
||||
public static void performActionDumbAware(AnAction action, AnActionEvent e) {
|
||||
WrapInTransaction annotation = action.getClass().getAnnotation(WrapInTransaction.class);
|
||||
AccessToken token = annotation == null ? AccessToken.EMPTY_ACCESS_TOKEN
|
||||
: TransactionGuard.getInstance().startSynchronousTransaction(annotation.value());
|
||||
try {
|
||||
action.actionPerformed(e);
|
||||
}
|
||||
catch (IndexNotReadyException e1) {
|
||||
showDumbModeWarning(e);
|
||||
}
|
||||
finally {
|
||||
token.finish();
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -134,7 +134,7 @@ public class EventLog {
|
||||
Notification n = new Notification("", "", ".", NotificationType.INFORMATION, new NotificationListener() {
|
||||
@Override
|
||||
public void hyperlinkUpdate(@NotNull Notification n, @NotNull HyperlinkEvent event) {
|
||||
Notification.fire(notification.getActions().get(Integer.parseInt(event.getDescription())));
|
||||
Notification.fire(notification, notification.getActions().get(Integer.parseInt(event.getDescription())));
|
||||
}
|
||||
});
|
||||
if (title.length() > 0 || content.length() > 0) {
|
||||
|
||||
+2
-2
@@ -729,7 +729,7 @@ public class NotificationsManagerImpl extends NotificationsManager {
|
||||
return balloon;
|
||||
}
|
||||
|
||||
private static void createActionPanel(@NotNull Notification notification, @NotNull JPanel centerPanel, int gap) {
|
||||
private static void createActionPanel(@NotNull final Notification notification, @NotNull JPanel centerPanel, int gap) {
|
||||
JPanel actionPanel = new NonOpaquePanel(new HorizontalLayout(gap, SwingConstants.CENTER));
|
||||
centerPanel.add(BorderLayout.SOUTH, actionPanel);
|
||||
|
||||
@@ -763,7 +763,7 @@ public class NotificationsManagerImpl extends NotificationsManager {
|
||||
new LinkLabel<AnAction>(presentation.getText(), presentation.getIcon(), new LinkListener<AnAction>() {
|
||||
@Override
|
||||
public void linkSelected(LinkLabel aSource, AnAction action) {
|
||||
Notification.fire(action);
|
||||
Notification.fire(notification, action);
|
||||
}
|
||||
}, action));
|
||||
}
|
||||
|
||||
+2
-4
@@ -23,9 +23,7 @@ import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.actionSystem.ex.ActionManagerEx;
|
||||
import com.intellij.openapi.actionSystem.ex.ActionUtil;
|
||||
import com.intellij.openapi.actionSystem.impl.PresentationFactory;
|
||||
import com.intellij.openapi.application.Application;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.application.*;
|
||||
import com.intellij.openapi.keymap.KeyMapBundle;
|
||||
import com.intellij.openapi.keymap.Keymap;
|
||||
import com.intellij.openapi.keymap.KeymapManager;
|
||||
@@ -592,7 +590,7 @@ public final class IdeKeyEventDispatcher implements Disposable {
|
||||
.showInBestPositionFor(ctx);
|
||||
}
|
||||
else {
|
||||
action.actionPerformed(actionEvent);
|
||||
ActionUtil.performActionDumbAware(action, actionEvent);
|
||||
}
|
||||
|
||||
if (Registry.is("actionSystem.fixLostTyping")) {
|
||||
|
||||
@@ -98,6 +98,7 @@ abstract class ShortcutDialog<T extends Shortcut> extends DialogWrapper {
|
||||
}
|
||||
}
|
||||
myConflictsPanel.revalidate();
|
||||
myConflictsPanel.repaint();
|
||||
}
|
||||
myConflictsPanel.setVisible(0 < myConflictsContainer.getComponentCount());
|
||||
}
|
||||
|
||||
@@ -858,7 +858,7 @@ public class PopupFactoryImpl extends JBPopupFactory {
|
||||
ActionManager.getInstance(), modifiers);
|
||||
event.setInjectedContext(action.isInInjectedContext());
|
||||
if (ActionUtil.lastUpdateAndCheckDumb(action, event, false)) {
|
||||
action.actionPerformed(event);
|
||||
ActionUtil.performActionDumbAware(action, event);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -139,7 +139,22 @@ public class Patches {
|
||||
/**
|
||||
* On Mac OS font ligatures are not supported for natively loaded fonts, font needs to be loaded explicitly by JDK.
|
||||
*/
|
||||
public static final boolean JDK_BUG_ID_7162125 = SystemInfo.isMac && !SystemInfo.isJavaVersionAtLeast("1.9");
|
||||
public static final boolean JDK_BUG_ID_7162125;
|
||||
static {
|
||||
boolean value;
|
||||
if (!SystemInfo.isMac || SystemInfo.isJavaVersionAtLeast("1.9")) value = false;
|
||||
else if (!SystemInfo.isJetbrainsJvm) value = true;
|
||||
else {
|
||||
try {
|
||||
Class.forName("sun.font.CCompositeFont");
|
||||
value = Boolean.getBoolean("disable.font.substitution");
|
||||
}
|
||||
catch (Throwable e) {
|
||||
value = true;
|
||||
}
|
||||
}
|
||||
JDK_BUG_ID_7162125 = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* XToolkit.getScreenInsets() may be very slow.
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
|
||||
<extensionPoints>
|
||||
<extensionPoint qualifiedName="Edu.CCLanguageManager" beanClass="com.intellij.lang.LanguageExtensionPoint">
|
||||
<with attribute="implementationClass" implements="com.jetbrains.edu.coursecreator.CCLanguageManager"/>
|
||||
</extensionPoint>
|
||||
</extensionPoints>
|
||||
|
||||
|
||||
@@ -30,8 +30,12 @@
|
||||
</project-components>
|
||||
|
||||
<extensionPoints>
|
||||
<extensionPoint qualifiedName="Edu.StudyExecutor" beanClass="com.intellij.lang.LanguageExtensionPoint"/>
|
||||
<extensionPoint qualifiedName="Edu.StudyLanguageManager" beanClass="com.intellij.lang.LanguageExtensionPoint"/>
|
||||
<extensionPoint qualifiedName="Edu.StudyExecutor" beanClass="com.intellij.lang.LanguageExtensionPoint">
|
||||
<with attribute="implementationClass" implements="com.jetbrains.edu.learning.checker.StudyExecutor"/>
|
||||
</extensionPoint>
|
||||
<extensionPoint qualifiedName="Edu.StudyLanguageManager" beanClass="com.intellij.lang.LanguageExtensionPoint">
|
||||
<with attribute="implementationClass" implements="com.jetbrains.edu.learning.StudyLanguageManager"/>
|
||||
</extensionPoint>
|
||||
<extensionPoint qualifiedName="Edu.studyToolWindowConfigurator" interface="com.jetbrains.edu.learning.StudyToolWindowConfigurator"/>
|
||||
</extensionPoints>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user