diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java index b8e3d0218e0a..5de1e5611046 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java @@ -1521,6 +1521,9 @@ public class HighlightUtil extends HighlightUtilBase { } else { aClass = PsiTreeUtil.getParentOfType(expr, PsiClass.class); + if (aClass instanceof PsiAnonymousClass && PsiTreeUtil.isAncestor(((PsiAnonymousClass)aClass).getArgumentList(), expr, false)) { + aClass = PsiTreeUtil.getParentOfType(aClass, PsiClass.class, true); + } } if (aClass == null) return null; diff --git a/java/java-impl/src/com/intellij/codeInspection/varScopeCanBeNarrowed/ParameterCanBeLocalInspection.java b/java/java-impl/src/com/intellij/codeInspection/varScopeCanBeNarrowed/ParameterCanBeLocalInspection.java index e7986b515d71..8aefca5e0dc6 100644 --- a/java/java-impl/src/com/intellij/codeInspection/varScopeCanBeNarrowed/ParameterCanBeLocalInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/varScopeCanBeNarrowed/ParameterCanBeLocalInspection.java @@ -19,10 +19,14 @@ import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.openapi.project.Project; import com.intellij.psi.*; import com.intellij.refactoring.changeSignature.ChangeSignatureProcessor; +import com.intellij.refactoring.changeSignature.JavaChangeInfo; +import com.intellij.refactoring.changeSignature.JavaChangeInfoImpl; import com.intellij.refactoring.changeSignature.ParameterInfoImpl; +import com.intellij.refactoring.util.CanonicalTypes; import com.intellij.usageView.UsageInfo; import com.intellij.util.NotNullFunction; import com.intellij.util.VisibilityUtil; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -66,8 +70,11 @@ public class ParameterCanBeLocalInspection extends ParameterCanBeLocalInspection } final ParameterInfoImpl[] newParams = info.toArray(new ParameterInfoImpl[info.size()]); final String visibilityModifier = VisibilityUtil.getVisibilityModifier(method.getModifierList()); - final ChangeSignatureProcessor cp = new ChangeSignatureProcessor(project, method, false, visibilityModifier, - method.getName(), method.getReturnType(), newParams) { + final PsiType returnType = method.getReturnType(); + final JavaChangeInfo changeInfo = new JavaChangeInfoImpl(visibilityModifier, method, method.getName(), + returnType != null ? CanonicalTypes.createTypeWrapper(returnType) : null, + newParams, null, false, ContainerUtil.newHashSet(), ContainerUtil.newHashSet()); + final ChangeSignatureProcessor cp = new ChangeSignatureProcessor(project, changeInfo) { @Override protected void performRefactoring(@NotNull UsageInfo[] usages) { final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project); diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/AbstractJavaBlock.java b/java/java-impl/src/com/intellij/psi/formatter/java/AbstractJavaBlock.java index 4a9691f0d2e4..7f6a002c2ebf 100644 --- a/java/java-impl/src/com/intellij/psi/formatter/java/AbstractJavaBlock.java +++ b/java/java-impl/src/com/intellij/psi/formatter/java/AbstractJavaBlock.java @@ -19,8 +19,6 @@ import com.intellij.formatting.*; import com.intellij.formatting.alignment.AlignmentStrategy; import com.intellij.lang.ASTNode; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.editor.Document; -import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; @@ -1282,37 +1280,4 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo result.setChildAttributes(new ChildAttributes(getCodeBlockInternalIndent(childrenIndent), null)); return result; } - - @Nullable - @Override - public ExtraReformatRanges getExtraRangesToFormat(FormatTextRanges ranges) { - if (ranges.isInsertedBlock(this) && myNode.textContains('\n')) { - List extra = calculateExtraRanges(myNode); - return new ExtraReformatRanges(extra); - } - - return null; - } - - @NotNull - private List calculateExtraRanges(@NotNull ASTNode node) { - Document document = retrieveDocument(node, getProject(node)); - if (document != null) { - TextRange ranges = node.getTextRange(); - return new IndentRangesCalculator(document, ranges).calcIndentRanges(); - } - - return ContainerUtil.newArrayList(myNode.getTextRange()); - } - - - private static Document retrieveDocument(@NotNull ASTNode node, @NotNull Project project) { - PsiFile file = node.getPsi().getContainingFile(); - return PsiDocumentManager.getInstance(project).getDocument(file); - } - - @NotNull - private static Project getProject(@NotNull ASTNode node) { - return node.getPsi().getProject(); - } } diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureProcessor.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureProcessor.java index d6570b0d00f3..07cf95e0d6c6 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureProcessor.java @@ -121,7 +121,7 @@ public class ChangeSignatureProcessor extends ChangeSignatureProcessorBase { final JavaChangeInfoImpl javaChangeInfo = new JavaChangeInfoImpl(newVisibility, method, newName, newType, parameterInfo, thrownExceptions, generateDelegate, propagateParametersMethods, propagateExceptionsMethods); - javaChangeInfo.setRefactoringId(REFACTORING_ID); + javaChangeInfo.setCheckUnusedParameter(); return javaChangeInfo; } diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeInfo.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeInfo.java index 6466f8302385..961cce2ca1d8 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeInfo.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeInfo.java @@ -68,4 +68,9 @@ public interface JavaChangeInfo extends ChangeInfo { void updateMethod(PsiMethod psiMethod); Collection getMethodsToPropagateParameters(); + + default boolean checkUnusedParameter() { + return false; + } + } diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeInfoImpl.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeInfoImpl.java index 426d89e238b4..f03137162608 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeInfoImpl.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeInfoImpl.java @@ -69,7 +69,7 @@ public class JavaChangeInfoImpl extends UserDataHolderBase implements JavaChange final Set propagateParametersMethods; final Set propagateExceptionsMethods; - private String myRefactoringId = null; + private boolean myCheckUnusedParameter = false; /** * @param newExceptions null if not changed @@ -203,12 +203,13 @@ public class JavaChangeInfoImpl extends UserDataHolderBase implements JavaChange } } - public String getRefactoringId() { - return myRefactoringId; + @Override + public boolean checkUnusedParameter() { + return myCheckUnusedParameter; } - public void setRefactoringId(String refactoringId) { - myRefactoringId = refactoringId; + public void setCheckUnusedParameter() { + myCheckUnusedParameter = true; } protected void fillOldParams(PsiMethod method) { diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java index 4319acf3baf0..188d386dce5c 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java @@ -1004,10 +1004,9 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr } final boolean[] toRemove = myChangeInfo.toRemoveParm(); - final String refactoringId = ((JavaChangeInfoImpl)myChangeInfo).getRefactoringId(); //introduce parameter object deletes parameters but replaces their usages with generated code - final boolean simpleChangeSignature = ChangeSignatureProcessorBase.REFACTORING_ID.equals(refactoringId); - if (simpleChangeSignature) { + final boolean checkUnusedParameter = myChangeInfo.checkUnusedParameter(); + if (checkUnusedParameter) { checkParametersToDelete(myChangeInfo.getMethod(), toRemove, conflictDescriptions); } checkContract(conflictDescriptions, myChangeInfo.getMethod()); @@ -1025,7 +1024,7 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr } else if (prototype != null && baseMethod == myChangeInfo.getMethod()) { ConflictsUtil.checkMethodConflicts(method.getContainingClass(), method, prototype, conflictDescriptions); - if (simpleChangeSignature) { + if (checkUnusedParameter) { checkParametersToDelete(method, toRemove, conflictDescriptions); } } diff --git a/java/java-indexing-api/src/com/intellij/psi/search/searches/FunctionalExpressionSearch.java b/java/java-indexing-api/src/com/intellij/psi/search/searches/FunctionalExpressionSearch.java index 4dcc889233c2..f6028eefec8b 100644 --- a/java/java-indexing-api/src/com/intellij/psi/search/searches/FunctionalExpressionSearch.java +++ b/java/java-indexing-api/src/com/intellij/psi/search/searches/FunctionalExpressionSearch.java @@ -32,7 +32,6 @@ import com.intellij.util.QueryExecutor; import org.jetbrains.annotations.NotNull; public class FunctionalExpressionSearch extends ExtensibleQueryFactory { - public static final ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.functionalInterfaceSearch"); public static final FunctionalExpressionSearch INSTANCE = new FunctionalExpressionSearch(); public static class SearchParameters { diff --git a/java/java-psi-api/src/com/intellij/codeInsight/daemon/impl/analysis/JavaGenericsUtil.java b/java/java-psi-api/src/com/intellij/codeInsight/daemon/impl/analysis/JavaGenericsUtil.java index e01eb710d73d..379d9072927d 100644 --- a/java/java-psi-api/src/com/intellij/codeInsight/daemon/impl/analysis/JavaGenericsUtil.java +++ b/java/java-psi-api/src/com/intellij/codeInsight/daemon/impl/analysis/JavaGenericsUtil.java @@ -74,6 +74,10 @@ public class JavaGenericsUtil { return true; } + if (type instanceof PsiCapturedWildcardType) { + return isReifiableType(((PsiCapturedWildcardType)type).getUpperBound()); + } + return false; } @@ -127,6 +131,9 @@ public class JavaGenericsUtil { if (castType instanceof PsiClassType) { final PsiClassType castClassType = (PsiClassType)castType; operandType = operandType.getDeepComponentType(); + if (operandType instanceof PsiCapturedWildcardType) { + operandType = ((PsiCapturedWildcardType)operandType).getUpperBound(); + } if (!(operandType instanceof PsiClassType)) return false; final PsiClassType operandClassType = (PsiClassType)operandType; diff --git a/java/java-tests/testData/actions/reformatFileInEditor/formatOptimizeRearrangeVcsChanges_after.java b/java/java-tests/testData/actions/reformatFileInEditor/formatOptimizeRearrangeVcsChanges_after.java index e33d32fd1c1b..ddcdfe9ab7a8 100644 --- a/java/java-tests/testData/actions/reformatFileInEditor/formatOptimizeRearrangeVcsChanges_after.java +++ b/java/java-tests/testData/actions/reformatFileInEditor/formatOptimizeRearrangeVcsChanges_after.java @@ -5,6 +5,6 @@ public class Main { protected Object obj = null; private long e = 4; - public static void main(String[] args) { + public static void main(String[] args) { } } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/ThisInInterface.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/ThisInInterface.java index ed86aac1e7af..2a5eb2dc8806 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/ThisInInterface.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/ThisInInterface.java @@ -4,7 +4,7 @@ class C implements A { interface A { A a = new C(this); - A a1 = new C(this){}; + A a1 = new C(this){}; class B { A foo() { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting6/ThisInArgListOfAnonymous.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting6/ThisInArgListOfAnonymous.java new file mode 100644 index 000000000000..f0c5fe366d97 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting6/ThisInArgListOfAnonymous.java @@ -0,0 +1,17 @@ +class A { + public A(Object o) { + } +} + +class B {} + +class C extends B { + static { + A a = new A(this) {}; + A a1 = new A(super.clone()) {}; + } + + { + A a = new A(this); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/ReifiableCapturedWildcards.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/ReifiableCapturedWildcards.java new file mode 100644 index 000000000000..ca772c9ee3ab --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/ReifiableCapturedWildcards.java @@ -0,0 +1,9 @@ +import java.util.List; + +class Test { + public void bar(List list) { + foo(list.get(0)); + } + + private final void foo(K... k) {} +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/UncheckedCastWithCapturedWildcards.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/UncheckedCastWithCapturedWildcards.java new file mode 100644 index 000000000000..ead8b1eee73b --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/UncheckedCastWithCapturedWildcards.java @@ -0,0 +1,8 @@ +import java.util.List; + +class Test { + public void foo(List list, List list2) { + Comparable c1 = (Comparable)list.get(0); + Comparable c2 = (Comparable)list2.get(0); + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/actions/ReformatCodeActionInEditorTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/actions/ReformatCodeActionInEditorTest.java index 4ba5471b93a0..0f1022bbc38b 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/actions/ReformatCodeActionInEditorTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/actions/ReformatCodeActionInEditorTest.java @@ -31,8 +31,12 @@ public class ReformatCodeActionInEditorTest extends LightPlatformCodeInsightFixt @Override public void tearDown() throws Exception { - myFixture.getFile().putUserData(FormatChangedTextUtil.TEST_REVISION_CONTENT, null); - super.tearDown(); + try { + myFixture.getFile().putUserData(FormatChangedTextUtil.TEST_REVISION_CONTENT, null); + } + finally { + super.tearDown(); + } } public void doTest(LayoutCodeOptions options) { diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk6Test.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk6Test.java index 96adb6afc01b..1d52f336b2f7 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk6Test.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk6Test.java @@ -75,4 +75,7 @@ public class LightAdvHighlightingJdk6Test extends LightDaemonAnalyzerTestCase { public void testVariableUsedBeforeAssignmentWithParenthesis() { doTest(false, false); } + public void testThisInArgListOfAnonymous() { + doTest(false, false); + } } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GenericsHighlighting8Test.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GenericsHighlighting8Test.java index 0c929899f9bc..82d2f2e7151f 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GenericsHighlighting8Test.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GenericsHighlighting8Test.java @@ -998,4 +998,12 @@ public class GenericsHighlighting8Test extends LightDaemonAnalyzerTestCase { public void testErasureOfReturnTypeOfNonGenericMethod() throws Exception { doTest(); } + + public void testUncheckedCastWithCapturedWildcards() throws Exception { + doTest(true); + } + + public void testReifiableCapturedWildcards() throws Exception { + doTest(true); + } } diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/OfflineInspectionResultViewTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/OfflineInspectionResultViewTest.java index 436f3f6552ad..d350cbb28ecd 100644 --- a/java/java-tests/testSrc/com/intellij/codeInspection/OfflineInspectionResultViewTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInspection/OfflineInspectionResultViewTest.java @@ -152,7 +152,7 @@ public class OfflineInspectionResultViewTest extends TestSourceBasedTestCase { " -\n" + " -Test\n" + " -m()\n" + - " Identical qualifier and argument to 'equals()' call\n" + + " 'equals()' called on itself\n" + " -null\n" + " Identical qualifier and argument to equals() call\n" + " -" + myUnusedToolWrapper + "\n" @@ -190,10 +190,10 @@ public class OfflineInspectionResultViewTest extends TestSourceBasedTestCase { " -\n" + " -Test\n" + " -m()\n" + - " Identical qualifier and argument to 'equals()' call\n" + + " 'equals()' called on itself\n" + " -Test2\n" + " -m123()\n" + - " Identical qualifier and argument to 'equals()' call\n" + " 'equals()' called on itself\n" + " -" + myUnusedToolWrapper + "\n" + " -" + getModule().toString() + "\n" + " -\n" @@ -218,9 +218,9 @@ public class OfflineInspectionResultViewTest extends TestSourceBasedTestCase { + " -Probable bugs\n" + " -" + myDataFlowToolWrapper + "\n" + " -Test\n" + - " Identical qualifier and argument to 'equals()' call\n" + + " 'equals()' called on itself\n" + " -Test2\n" + - " Identical qualifier and argument to 'equals()' call\n" + " 'equals()' called on itself\n" + " -" + myUnusedToolWrapper + "\n" + " -Test\n" + " " + varMessage("j") + "\n" @@ -248,9 +248,9 @@ public class OfflineInspectionResultViewTest extends TestSourceBasedTestCase { + " -Probable bugs\n" + " -" + myDataFlowToolWrapper + "\n" + " -Test\n" + - " Identical qualifier and argument to 'equals()' call\n" + + " 'equals()' called on itself\n" + " -Test2\n" + - " Identical qualifier and argument to 'equals()' call\n" + " 'equals()' called on itself\n" + " -" + myUnusedToolWrapper + "\n" + " -Test\n" + " " + varMessage("j") + "\n" diff --git a/java/java-tests/testSrc/com/intellij/psi/formatter/java/IndentRangesCalculatorTest.kt b/java/java-tests/testSrc/com/intellij/psi/formatter/java/IndentRangesCalculatorTest.kt index 50eed0444926..87f4f40472bb 100644 --- a/java/java-tests/testSrc/com/intellij/psi/formatter/java/IndentRangesCalculatorTest.kt +++ b/java/java-tests/testSrc/com/intellij/psi/formatter/java/IndentRangesCalculatorTest.kt @@ -16,6 +16,7 @@ package com.intellij.psi.formatter.java import com.intellij.openapi.util.TextRange +import com.intellij.psi.formatter.IndentRangesCalculator import com.intellij.testFramework.LightPlatformCodeInsightTestCase import org.assertj.core.api.Assertions.assertThat diff --git a/platform/core-api/src/org/jetbrains/concurrency/AsyncPromise.java b/platform/core-api/src/org/jetbrains/concurrency/AsyncPromise.java deleted file mode 100644 index 91aba820be77..000000000000 --- a/platform/core-api/src/org/jetbrains/concurrency/AsyncPromise.java +++ /dev/null @@ -1,363 +0,0 @@ -/* - * 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 org.jetbrains.concurrency; - -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.util.Getter; -import com.intellij.util.Consumer; -import com.intellij.util.Function; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; -import java.util.List; - -public class AsyncPromise extends Promise implements Getter { - private static final Logger LOG = Logger.getInstance(AsyncPromise.class); - - public static final RuntimeException OBSOLETE_ERROR = Promise.createError("Obsolete"); - - private volatile Consumer done; - private volatile Consumer rejected; - - protected volatile State state = State.PENDING; - // result object or error message - private volatile Object result; - - @NotNull - @Override - public State getState() { - return state; - } - - @NotNull - @Override - public Promise done(@NotNull Consumer done) { - if (isObsolete(done)) { - return this; - } - - switch (state) { - case PENDING: - break; - case FULFILLED: - //noinspection unchecked - done.consume((T)result); - return this; - case REJECTED: - return this; - } - - this.done = setHandler(this.done, done); - return this; - } - - @NotNull - @Override - public Promise rejected(@NotNull Consumer rejected) { - if (isObsolete(rejected)) { - return this; - } - - switch (state) { - case PENDING: - break; - case FULFILLED: - return this; - case REJECTED: - rejected.consume((Throwable)result); - return this; - } - - this.rejected = setHandler(this.rejected, rejected); - return this; - } - - @Override - public T get() { - //noinspection unchecked - return state == State.FULFILLED ? (T)result : null; - } - - @SuppressWarnings("SynchronizeOnThis") - private static final class CompoundConsumer implements Consumer { - private List> consumers = new ArrayList>(); - - public CompoundConsumer(@NotNull Consumer c1, @NotNull Consumer c2) { - synchronized (this) { - consumers.add(c1); - consumers.add(c2); - } - } - - @Override - public void consume(T t) { - List> list; - synchronized (this) { - list = consumers; - consumers = null; - } - - if (list != null) { - for (Consumer consumer : list) { - if (!isObsolete(consumer)) { - consumer.consume(t); - } - } - } - } - - public void add(@NotNull Consumer consumer) { - synchronized (this) { - if (consumers != null) { - consumers.add(consumer); - } - } - } - } - - @Override - @NotNull - public Promise then(@NotNull final Function fulfilled) { - switch (state) { - case PENDING: - break; - case FULFILLED: - //noinspection unchecked - return new DonePromise(fulfilled.fun((T)result)); - case REJECTED: - return new RejectedPromise((Throwable)result); - } - - final AsyncPromise promise = new AsyncPromise(); - addHandlers(new Consumer() { - @Override - public void consume(T result) { - try { - if (fulfilled instanceof Obsolescent && ((Obsolescent)fulfilled).isObsolete()) { - promise.setError(OBSOLETE_ERROR); - } - else { - promise.setResult(fulfilled.fun(result)); - } - } - catch (Throwable e) { - promise.setError(e); - } - } - }, new Consumer() { - @Override - public void consume(Throwable error) { - promise.setError(error); - } - }); - return promise; - } - - @Override - public void notify(@NotNull final AsyncPromise child) { - LOG.assertTrue(child != this); - - switch (state) { - case PENDING: - break; - case FULFILLED: - //noinspection unchecked - child.setResult((T)result); - return; - case REJECTED: - child.setError((Throwable)result); - return; - } - - addHandlers(new Consumer() { - @Override - public void consume(T result) { - try { - child.setResult(result); - } - catch (Throwable e) { - child.setError(e); - } - } - }, new Consumer() { - @Override - public void consume(Throwable error) { - child.setError(error); - } - }); - } - - @Override - @NotNull - public Promise thenAsync(@NotNull final Function> fulfilled) { - switch (state) { - case PENDING: - break; - case FULFILLED: - //noinspection unchecked - return fulfilled.fun((T)result); - case REJECTED: - return Promise.reject((Throwable)result); - } - - final AsyncPromise promise = new AsyncPromise(); - final Consumer rejectedHandler = new Consumer() { - @Override - public void consume(Throwable error) { - promise.setError(error); - } - }; - addHandlers(new Consumer() { - @Override - public void consume(T result) { - try { - fulfilled.fun(result) - .done(new Consumer() { - @Override - public void consume(SUB_RESULT result) { - try { - promise.setResult(result); - } - catch (Throwable e) { - promise.setError(e); - } - } - }) - .rejected(rejectedHandler); - } - catch (Throwable e) { - promise.setError(e); - } - } - }, rejectedHandler); - return promise; - } - - @Override - @NotNull - public Promise processed(@NotNull final AsyncPromise fulfilled) { - switch (state) { - case PENDING: - break; - case FULFILLED: - //noinspection unchecked - fulfilled.setResult((T)result); - return this; - case REJECTED: - fulfilled.setError((Throwable)result); - return this; - } - - addHandlers(new Consumer() { - @Override - public void consume(T result) { - try { - fulfilled.setResult(result); - } - catch (Throwable e) { - fulfilled.setError(e); - } - } - }, new Consumer() { - @Override - public void consume(Throwable error) { - fulfilled.setError(error); - } - }); - return this; - } - - private void addHandlers(@NotNull Consumer done, @NotNull Consumer rejected) { - this.done = setHandler(this.done, done); - this.rejected = setHandler(this.rejected, rejected); - } - - @NotNull - private static Consumer setHandler(@Nullable Consumer oldConsumer, @NotNull Consumer newConsumer) { - if (oldConsumer == null) { - return newConsumer; - } - else if (oldConsumer instanceof CompoundConsumer) { - ((CompoundConsumer)oldConsumer).add(newConsumer); - return oldConsumer; - } - else { - return new CompoundConsumer(oldConsumer, newConsumer); - } - } - - public void setResult(T result) { - if (state != State.PENDING) { - return; - } - - this.result = result; - state = State.FULFILLED; - - Consumer done = this.done; - clearHandlers(); - if (done != null && !isObsolete(done)) { - done.consume(result); - } - } - - static boolean isObsolete(@Nullable Consumer consumer) { - return consumer instanceof Obsolescent && ((Obsolescent)consumer).isObsolete(); - } - - public boolean setError(@NotNull String error) { - return setError(Promise.createError(error)); - } - - public boolean setError(@NotNull Throwable error) { - if (state != State.PENDING) { - return false; - } - - result = error; - state = State.REJECTED; - - Consumer rejected = this.rejected; - clearHandlers(); - if (rejected != null) { - if (!isObsolete(rejected)) { - rejected.consume(error); - } - } - else { - Promise.logError(LOG, error); - } - return true; - } - - private void clearHandlers() { - done = null; - rejected = null; - } - - @Override - public Promise processed(@NotNull final Consumer processed) { - done(processed); - rejected(new Consumer() { - @Override - public void consume(Throwable error) { - processed.consume(null); - } - }); - return this; - } -} \ No newline at end of file diff --git a/platform/core-api/src/org/jetbrains/concurrency/ConsumerRunnable.java b/platform/core-api/src/org/jetbrains/concurrency/ConsumerRunnable.java deleted file mode 100644 index f10f67e53bf0..000000000000 --- a/platform/core-api/src/org/jetbrains/concurrency/ConsumerRunnable.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2000-2015 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 org.jetbrains.concurrency; - -import com.intellij.util.Consumer; - -public abstract class ConsumerRunnable implements Consumer, Runnable { - @Override - public final void consume(Void aVoid) { - run(); - } - - @Override - public abstract void run(); -} diff --git a/platform/core-impl/src/com/intellij/openapi/vfs/impl/http/RemoteFileInfo.java b/platform/core-impl/src/com/intellij/openapi/vfs/impl/http/RemoteFileInfo.java index 338666b3c341..9b6a94df3918 100644 --- a/platform/core-impl/src/com/intellij/openapi/vfs/impl/http/RemoteFileInfo.java +++ b/platform/core-impl/src/com/intellij/openapi/vfs/impl/http/RemoteFileInfo.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -17,7 +17,6 @@ package com.intellij.openapi.vfs.impl.http; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; -import org.jetbrains.concurrency.Promise; public interface RemoteFileInfo { void addDownloadingListener(@NotNull FileDownloadingListener listener); @@ -35,7 +34,4 @@ public interface RemoteFileInfo { RemoteFileState getState(); void cancelDownloading(); - - @NotNull - Promise download(); } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/IntentionListStep.java b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/IntentionListStep.java index 3a613776b2af..e1a199dd79b8 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/IntentionListStep.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/IntentionListStep.java @@ -16,6 +16,7 @@ package com.intellij.codeInsight.intention.impl; +import com.google.common.annotations.VisibleForTesting; import com.intellij.codeInsight.daemon.impl.HighlightInfo; import com.intellij.codeInsight.daemon.impl.ShowIntentionsPass; import com.intellij.codeInsight.hint.HintManager; @@ -195,10 +196,20 @@ public class IntentionListStep implements ListPopupStep options = descriptor.getOptions(element, containingEditor); if (options == null) return cachedAction; for (IntentionAction option : options) { - if (!option.isAvailable(myProject, containingEditor, containingFile)) { - // if option is not applicable in injected fragment, check in host file context - if (containingEditor == myEditor || !option.isAvailable(myProject, myEditor, myFile)) { - continue; + if (containingFile != null && containingEditor != null && myEditor != null) { + if (!ShowIntentionActionsHandler.availableFor(containingFile, containingEditor, option)) { + //if option is not applicable in injected fragment, check in host file context + if (containingEditor == myEditor || !ShowIntentionActionsHandler.availableFor(myFile, myEditor, option)) { + continue; + } + } + } + else { + if (!option.isAvailable(myProject, containingEditor, containingFile)) { + // if option is not applicable in injected fragment, check in host file context + if (containingEditor == myEditor || !option.isAvailable(myProject, myEditor, myFile)) { + continue; + } } } IntentionActionWithTextCaching textCaching = new IntentionActionWithTextCaching(option); @@ -291,6 +302,16 @@ public class IntentionListStep implements ListPopupStep> getActionsWithSubActions() { + Map> result = ContainerUtil.newLinkedHashMap(); + for (IntentionActionWithTextCaching action : getValues()) { + List subActions = getSubStep(action, action.getToolName()).getValues(); + result.put(action.getAction(), ContainerUtil.map(subActions, IntentionActionWithTextCaching::getAction)); + } + return result; + } + @Override public boolean hasSubstep(final IntentionActionWithTextCaching action) { return action.getOptionIntentions().size() + action.getOptionErrorFixes().size() > 0; diff --git a/platform/lang-impl/src/com/intellij/codeInspection/actions/RunInspectionAction.java b/platform/lang-impl/src/com/intellij/codeInspection/actions/RunInspectionAction.java index b0153cafb946..b286b8c01374 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/actions/RunInspectionAction.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/actions/RunInspectionAction.java @@ -40,26 +40,18 @@ import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleUtilCore; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; -import com.intellij.openapi.ui.LabeledComponent; import com.intellij.openapi.util.InvalidDataException; -import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.profile.Profile; -import com.intellij.profile.codeInspection.InspectionProfileManager; import com.intellij.profile.codeInspection.InspectionProjectProfileManager; -import com.intellij.profile.codeInspection.ui.header.ProfilesComboBox; import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.ui.TitledSeparator; -import com.intellij.util.containers.FactoryMap; -import com.intellij.util.ui.JBUI; import org.jdom.Element; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; -import java.awt.*; import java.awt.event.ActionEvent; import java.util.ArrayList; import java.util.Arrays; @@ -148,7 +140,7 @@ public class RunInspectionAction extends GotoActionBase { project, analysisScope, module != null ? module.getName() : null, true, options, psiElement) { - private InheritOptionsForToolPanel myToolOptionsPanel; + private InspectionToolWrapper myUpdatedSettingsToolWrapper; @Nullable @Override @@ -158,8 +150,9 @@ public class RunInspectionAction extends GotoActionBase { JPanel additionPanel = new JPanel(); additionPanel.setLayout(new BoxLayout(additionPanel, BoxLayout.Y_AXIS)); additionPanel.add(fileFilter); - myToolOptionsPanel = new InheritOptionsForToolPanel((InspectionProfileImpl)currentProfile, toolWrapper.getShortName(), project); - additionPanel.add(myToolOptionsPanel); + myUpdatedSettingsToolWrapper = copyToolWithSettings(toolWrapper);//new InheritOptionsForToolPanel(toolWrapper.getShortName(), project); + additionPanel.add(new TitledSeparator(IdeBundle.message("goto.inspection.action.choose.inherit.settings.from"))); + additionPanel.add(myUpdatedSettingsToolWrapper.getTool().createOptionsPanel()); return additionPanel; } else { return fileFilter; @@ -186,7 +179,7 @@ public class RunInspectionAction extends GotoActionBase { } private InspectionToolWrapper getToolWrapper() { - return myToolOptionsPanel == null ? toolWrapper : myToolOptionsPanel.getSelectedWrapper(); + return myUpdatedSettingsToolWrapper == null ? toolWrapper : myUpdatedSettingsToolWrapper; } @NotNull @@ -228,69 +221,16 @@ public class RunInspectionAction extends GotoActionBase { dialog.showAndGet(); } - private static class InheritOptionsForToolPanel extends JPanel { - private final ProfilesComboBox myProfilesComboBox; - @SuppressWarnings("MismatchedQueryAndUpdateOfCollection") - private final FactoryMap> myProfile2ModifiedWrapper; - - public InheritOptionsForToolPanel(final InspectionProfileImpl initial, final String toolShortName, final Project project) { - myProfile2ModifiedWrapper = new FactoryMap>() { - @Nullable - @Override - protected Pair create(InspectionProfile profile) { - InspectionToolWrapper tool = profile.getInspectionTool(toolShortName, project); - LOGGER.assertTrue(tool != null); - final Element options = new Element("copy"); - tool.getTool().writeSettings(options); - tool = tool.createCopy(); - try { - tool.getTool().readSettings(options); - } - catch (InvalidDataException e) { - throw new RuntimeException(e); - } - return Pair.create(tool, tool.getTool().createOptionsPanel()); - } - }; - JPanel settingsAnchor = new JPanel(new BorderLayout()); - myProfilesComboBox = new ProfilesComboBox() { - @Override - protected void onProfileChosen(InspectionProfileImpl inspectionProfile) { - settingsAnchor.removeAll(); - settingsAnchor.add(myProfile2ModifiedWrapper.get(inspectionProfile).getSecond(), BorderLayout.CENTER); - settingsAnchor.invalidate(); - settingsAnchor.validate(); - settingsAnchor.repaint(); - } - - @Override - protected boolean isProjectLevel(InspectionProfileImpl p) { - return p.isProjectLevel(); - } - - @NotNull - @Override - protected String getProfileName(InspectionProfileImpl p) { - return p.getName(); - } - }; - - setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); - add(new TitledSeparator(IdeBundle.message("goto.inspection.action.choose.inherit.settings.from"))); - add(LabeledComponent.create(myProfilesComboBox, "Profile:", BorderLayout.WEST)); - add(Box.createVerticalStrut(JBUI.scale(10))); - add(settingsAnchor); - - final List profiles = new ArrayList<>(); - profiles.addAll(InspectionProfileManager.getInstance().getProfiles()); - profiles.addAll(InspectionProjectProfileManager.getInstance(project).getProfiles()); - myProfilesComboBox.reset(profiles); - myProfilesComboBox.selectProfile(initial); + private static InspectionToolWrapper copyToolWithSettings(@NotNull final InspectionToolWrapper tool) { + final Element options = new Element("copy"); + tool.getTool().writeSettings(options); + final InspectionToolWrapper copiedTool = tool.createCopy(); + try { + copiedTool.getTool().readSettings(options); } - - @NotNull - public InspectionToolWrapper getSelectedWrapper() { - return myProfile2ModifiedWrapper.get((InspectionProfileImpl)myProfilesComboBox.getSelectedItem()).getFirst(); + catch (InvalidDataException e) { + throw new RuntimeException(e); } + return copiedTool; } } diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionResultsView.java b/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionResultsView.java index bf950aed295d..089dfe821ace 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionResultsView.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionResultsView.java @@ -163,6 +163,11 @@ public class InspectionResultsView extends JPanel implements Disposable, Occuren }); add(mySplitter, BorderLayout.CENTER); myExclusionHandler = new ExclusionHandler() { + @Override + public boolean isNodeExclusionAvailable(@NotNull InspectionTreeNode node) { + return true; + } + @Override public boolean isNodeExcluded(@NotNull InspectionTreeNode node) { return node.isExcluded(myExcludedInspectionTreeNodesManager); diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/IndentRangesCalculator.kt b/platform/lang-impl/src/com/intellij/psi/formatter/IndentRangesCalculator.kt similarity index 93% rename from java/java-impl/src/com/intellij/psi/formatter/java/IndentRangesCalculator.kt rename to platform/lang-impl/src/com/intellij/psi/formatter/IndentRangesCalculator.kt index 7d0268db0804..6fad905b9a18 100644 --- a/java/java-impl/src/com/intellij/psi/formatter/java/IndentRangesCalculator.kt +++ b/platform/lang-impl/src/com/intellij/psi/formatter/IndentRangesCalculator.kt @@ -13,13 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.psi.formatter.java +package com.intellij.psi.formatter import com.intellij.openapi.editor.Document import com.intellij.openapi.util.TextRange import com.intellij.util.text.CharArrayUtil -class IndentRangesCalculator(private val document: Document, +class IndentRangesCalculator(private val document: Document, private val textRange: TextRange) { private val startOffset = textRange.startOffset diff --git a/platform/lang-impl/src/com/intellij/psi/formatter/common/AbstractBlock.java b/platform/lang-impl/src/com/intellij/psi/formatter/common/AbstractBlock.java index 91853339741a..2ca0874b6afd 100644 --- a/platform/lang-impl/src/com/intellij/psi/formatter/common/AbstractBlock.java +++ b/platform/lang-impl/src/com/intellij/psi/formatter/common/AbstractBlock.java @@ -19,12 +19,16 @@ package com.intellij.psi.formatter.common; import com.intellij.formatting.*; import com.intellij.injected.editor.DocumentWindow; import com.intellij.lang.ASTNode; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.formatter.FormatterUtil; +import com.intellij.psi.formatter.IndentRangesCalculator; import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.ContainerUtilRt; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -184,7 +188,34 @@ public abstract class AbstractBlock implements ASTBlock { */ @Nullable public ExtraReformatRanges getExtraRangesToFormat(FormatTextRanges ranges) { + if (ranges.isInsertedBlock(this) && myNode.textContains('\n')) { + List extra = calculateExtraRanges(myNode); + return new ExtraReformatRanges(extra); + } + return null; } + + @NotNull + private List calculateExtraRanges(@NotNull ASTNode node) { + Document document = retrieveDocument(node, getProject(node)); + if (document != null) { + TextRange ranges = node.getTextRange(); + return new IndentRangesCalculator(document, ranges).calcIndentRanges(); + } + + return ContainerUtil.newArrayList(myNode.getTextRange()); + } + + + private static Document retrieveDocument(@NotNull ASTNode node, @NotNull Project project) { + PsiFile file = node.getPsi().getContainingFile(); + return PsiDocumentManager.getInstance(project).getDocument(file); + } + + @NotNull + private static Project getProject(@NotNull ASTNode node) { + return node.getPsi().getProject(); + } } diff --git a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java index 85e96b269405..ce59608b632b 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java @@ -1174,6 +1174,7 @@ public class FileBasedIndexImpl extends FileBasedIndex { } void clearIndicesIfNecessary() { + waitUntilIndicesAreInitialized(); for (ID indexId : getState().getIndexIDs()) { try { RebuildStatus.clearIndexIfNecessary(indexId, getIndex(indexId)::clear); diff --git a/platform/platform-api/src/com/intellij/ide/actions/exclusion/ExclusionHandler.java b/platform/platform-api/src/com/intellij/ide/actions/exclusion/ExclusionHandler.java index d208e93daef0..102a1e492e2f 100644 --- a/platform/platform-api/src/com/intellij/ide/actions/exclusion/ExclusionHandler.java +++ b/platform/platform-api/src/com/intellij/ide/actions/exclusion/ExclusionHandler.java @@ -26,6 +26,8 @@ import javax.swing.tree.MutableTreeNode; public interface ExclusionHandler { DataKey EXCLUSION_HANDLER = DataKey.create("tree.exclusion.handler"); + boolean isNodeExclusionAvailable(@NotNull T node); + boolean isNodeExcluded(@NotNull T node); void excludeNode(@NotNull T node); diff --git a/platform/platform-api/src/com/intellij/ide/actions/exclusion/TreeNodeExclusionAction.java b/platform/platform-api/src/com/intellij/ide/actions/exclusion/TreeNodeExclusionAction.java index a5f2443f710d..62986773d869 100644 --- a/platform/platform-api/src/com/intellij/ide/actions/exclusion/TreeNodeExclusionAction.java +++ b/platform/platform-api/src/com/intellij/ide/actions/exclusion/TreeNodeExclusionAction.java @@ -63,6 +63,7 @@ abstract class TreeNodeExclusionAction extends AnActi for (TreePath path : selection) { final T node = (T)path.getLastPathComponent(); TreeUtil.traverse(node, n -> { + if (!exclusionProcessor.isNodeExclusionAvailable((T)n)) return true; final Boolean isNodeExcluded = exclusionProcessor.isNodeExcluded((T)n); if (myIsExclude != isNodeExcluded) { isEnabled[0] = true; diff --git a/platform/platform-api/src/com/intellij/util/io/HttpRequests.java b/platform/platform-api/src/com/intellij/util/io/HttpRequests.java index ff5ead262efa..567cf4d68501 100644 --- a/platform/platform-api/src/com/intellij/util/io/HttpRequests.java +++ b/platform/platform-api/src/com/intellij/util/io/HttpRequests.java @@ -356,7 +356,9 @@ public final class HttpRequests { } private static T process(RequestBuilderImpl builder, RequestProcessor processor) throws IOException { - LOG.assertTrue(ApplicationManager.getApplication() == null || !ApplicationManager.getApplication().isReadAccessAllowed(), + LOG.assertTrue(ApplicationManager.getApplication() == null || + ApplicationManager.getApplication().isUnitTestMode() || + !ApplicationManager.getApplication().isReadAccessAllowed(), "Network shouldn't be accessed in EDT or inside read action"); ClassLoader contextLoader = Thread.currentThread().getContextClassLoader(); diff --git a/platform/platform-api/src/org/jetbrains/concurrency/AsyncPromise.kt b/platform/platform-api/src/org/jetbrains/concurrency/AsyncPromise.kt new file mode 100644 index 000000000000..91f13db02c96 --- /dev/null +++ b/platform/platform-api/src/org/jetbrains/concurrency/AsyncPromise.kt @@ -0,0 +1,284 @@ +/* + * 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 org.jetbrains.concurrency + +import com.intellij.openapi.diagnostic.Logger +import com.intellij.openapi.util.Getter +import com.intellij.util.Consumer +import com.intellij.util.Function +import java.util.* + +private val LOG = Logger.getInstance(AsyncPromise::class.java) + +@SuppressWarnings("ThrowableResultOfMethodCallIgnored") +private val OBSOLETE_ERROR = Promise.createError("Obsolete") + +open class AsyncPromise : Promise(), Getter { + @Volatile private var done: Consumer? = null + @Volatile private var rejected: Consumer? = null + + @Volatile private var state: Promise.State = Promise.State.PENDING + + // result object or error message + @Volatile private var result: Any? = null + + override fun getState() = state + + override fun done(done: Consumer): Promise { + if (isObsolete(done)) { + return this + } + + when (state) { + Promise.State.PENDING -> { + } + Promise.State.FULFILLED -> { + @Suppress("UNCHECKED_CAST") + done.consume(result as T?) + return this + } + Promise.State.REJECTED -> return this + } + + this.done = setHandler(this.done, done) + return this + } + + override fun rejected(rejected: Consumer): Promise { + if (isObsolete(rejected)) { + return this + } + + when (state) { + Promise.State.PENDING -> { + } + Promise.State.FULFILLED -> return this + Promise.State.REJECTED -> { + rejected.consume(result as Throwable?) + return this + } + } + + this.rejected = setHandler(this.rejected, rejected) + return this + } + + @Suppress("UNCHECKED_CAST") + override fun get() = if (state == Promise.State.FULFILLED) result as T? else null + + override fun then(fulfilled: Function): Promise { + @Suppress("UNCHECKED_CAST") + when (state) { + Promise.State.PENDING -> { + } + Promise.State.FULFILLED -> return DonePromise(fulfilled.`fun`(result as T?)) + Promise.State.REJECTED -> return rejectedPromise(result as Throwable) + } + + val promise = AsyncPromise() + addHandlers(Consumer({ result -> + promise.catchError { + if (fulfilled is Obsolescent && fulfilled.isObsolete) { + promise.cancel() + } + else { + promise.setResult(fulfilled.`fun`(result)) + } + } + }), Consumer({ promise.setError(it) })) + return promise + } + + override fun notify(child: AsyncPromise) { + LOG.assertTrue(child !== this) + + when (state) { + Promise.State.PENDING -> { + } + Promise.State.FULFILLED -> { + @Suppress("UNCHECKED_CAST") + child.setResult(result as T) + return + } + Promise.State.REJECTED -> { + child.setError((result as Throwable?)!!) + return + } + } + + addHandlers(Consumer({ child.catchError { child.setResult(it) } }), Consumer({ child.setError(it) })) + } + + override fun thenAsync(fulfilled: Function>): Promise { + @Suppress("UNCHECKED_CAST") + when (state) { + Promise.State.PENDING -> { + } + Promise.State.FULFILLED -> return fulfilled.`fun`(result as T?) + Promise.State.REJECTED -> return rejectedPromise(result as Throwable) + } + + val promise = AsyncPromise() + val rejectedHandler = Consumer({ promise.setError(it) }) + addHandlers(Consumer({ + promise.catchError { + fulfilled.`fun`(it) + .done { promise.catchError { promise.setResult(it) } } + .rejected(rejectedHandler) + } + }), rejectedHandler) + return promise + } + + override fun processed(fulfilled: AsyncPromise): Promise { + when (state) { + Promise.State.PENDING -> { + } + Promise.State.FULFILLED -> { + @Suppress("UNCHECKED_CAST") + fulfilled.setResult(result as T) + return this + } + Promise.State.REJECTED -> { + fulfilled.setError((result as Throwable?)!!) + return this + } + } + + addHandlers(Consumer({ result -> fulfilled.catchError { fulfilled.setResult(result) } }), Consumer({ fulfilled.setError(it) })) + return this + } + + private fun addHandlers(done: Consumer, rejected: Consumer) { + this.done = setHandler(this.done, done) + this.rejected = setHandler(this.rejected, rejected) + } + + fun setResult(result: T?) { + if (state != Promise.State.PENDING) { + return + } + + this.result = result + state = Promise.State.FULFILLED + + val done = this.done + clearHandlers() + if (done != null && !isObsolete(done)) { + done.consume(result) + } + } + + fun setError(error: String): Boolean { + return setError(Promise.createError(error)) + } + + fun cancel() { + setError(OBSOLETE_ERROR) + } + + open fun setError(error: Throwable): Boolean { + if (state != Promise.State.PENDING) { + return false + } + + result = error + state = Promise.State.REJECTED + + val rejected = this.rejected + clearHandlers() + if (rejected == null) { + Promise.logError(LOG, error) + } + else if (!isObsolete(rejected)) { + rejected.consume(error) + } + return true + } + + private fun clearHandlers() { + done = null + rejected = null + } + + override fun processed(processed: Consumer): Promise { + done(processed) + rejected({ error -> processed.consume(null) }) + return this + } +} + +private class CompoundConsumer(c1: Consumer, c2: Consumer) : Consumer { + private var consumers: MutableList>? = ArrayList() + + init { + synchronized(this) { + consumers!!.add(c1) + consumers!!.add(c2) + } + } + + override fun consume(t: T) { + val list = synchronized(this) { + val list = consumers + consumers = null + list + } ?: return + + for (consumer in list) { + if (!isObsolete(consumer)) { + consumer.consume(t) + } + } + } + + fun add(consumer: Consumer) { + synchronized(this) { + if (consumers != null) { + consumers!!.add(consumer) + } + } + } +} + +private fun setHandler(oldConsumer: Consumer?, newConsumer: Consumer) = when (oldConsumer) { + null -> newConsumer + is CompoundConsumer<*> -> { + @Suppress("UNCHECKED_CAST") + (oldConsumer as CompoundConsumer).add(newConsumer) + oldConsumer + } + else -> CompoundConsumer(oldConsumer, newConsumer) +} + +internal fun isObsolete(consumer: Consumer<*>?) = consumer is Obsolescent && consumer.isObsolete + +inline fun AsyncPromise<*>.catchError(runnable: () -> T): T? { + try { + return runnable() + } + catch (e: Throwable) { + setError(e) + return null + } +} + +private val cancelledPromise = RejectedPromise(OBSOLETE_ERROR) + +@Suppress("CAST_NEVER_SUCCEEDS") +fun cancelledPromise(): Promise = cancelledPromise as Promise + +fun rejectedPromise(error: Throwable): Promise = Promise.reject(error) \ No newline at end of file diff --git a/platform/core-api/src/org/jetbrains/concurrency/DonePromise.java b/platform/platform-api/src/org/jetbrains/concurrency/DonePromise.java similarity index 98% rename from platform/core-api/src/org/jetbrains/concurrency/DonePromise.java rename to platform/platform-api/src/org/jetbrains/concurrency/DonePromise.java index 599bc44b54c3..ebcefdae4dd3 100644 --- a/platform/core-api/src/org/jetbrains/concurrency/DonePromise.java +++ b/platform/platform-api/src/org/jetbrains/concurrency/DonePromise.java @@ -30,7 +30,7 @@ class DonePromise extends Promise implements Getter { @NotNull @Override public Promise done(@NotNull Consumer done) { - if (!AsyncPromise.isObsolete(done)) { + if (!AsyncPromiseKt.isObsolete(done)) { done.consume(result); } return this; diff --git a/platform/core-api/src/org/jetbrains/concurrency/Obsolescent.java b/platform/platform-api/src/org/jetbrains/concurrency/Obsolescent.java similarity index 95% rename from platform/core-api/src/org/jetbrains/concurrency/Obsolescent.java rename to platform/platform-api/src/org/jetbrains/concurrency/Obsolescent.java index 44d280b86013..a8e60bab6072 100644 --- a/platform/core-api/src/org/jetbrains/concurrency/Obsolescent.java +++ b/platform/platform-api/src/org/jetbrains/concurrency/Obsolescent.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. diff --git a/platform/core-api/src/org/jetbrains/concurrency/Promise.java b/platform/platform-api/src/org/jetbrains/concurrency/Promise.java similarity index 72% rename from platform/core-api/src/org/jetbrains/concurrency/Promise.java rename to platform/platform-api/src/org/jetbrains/concurrency/Promise.java index e331b50d0c2a..ffeb4d5d9142 100644 --- a/platform/core-api/src/org/jetbrains/concurrency/Promise.java +++ b/platform/platform-api/src/org/jetbrains/concurrency/Promise.java @@ -23,12 +23,9 @@ import com.intellij.openapi.util.AsyncResult; import com.intellij.util.Consumer; import com.intellij.util.Function; import com.intellij.util.ThreeState; -import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Collection; - public abstract class Promise { public static final Promise DONE = new DonePromise(null); public static final Promise REJECTED = new RejectedPromise(createError("rejected")); @@ -69,54 +66,11 @@ public abstract class Promise { } } - public static Promise any(@NotNull final Collection> promises, @NotNull final String totalError) { - if (promises.isEmpty()) { - //noinspection unchecked - return (Promise)DONE; - } - else if (promises.size() == 1) { - return ContainerUtil.getFirstItem(promises); - } - - final AsyncPromise totalPromise = new AsyncPromise(); - Consumer done = new Consumer() { - @Override - public void consume(T result) { - totalPromise.setResult(result); - } - }; - Consumer rejected = new Consumer() { - private volatile int toConsume = promises.size(); - - @Override - public void consume(Throwable throwable) { - if (--toConsume <= 0) { - totalPromise.setError(totalError); - } - } - }; - - for (Promise promise : promises) { - promise.done(done); - promise.rejected(rejected); - } - return totalPromise; - } - @NotNull public static Promise wrapAsVoid(@NotNull ActionCallback asyncResult) { final AsyncPromise promise = new AsyncPromise(); - asyncResult.doWhenDone(new Runnable() { - @Override - public void run() { - promise.setResult(null); - } - }).doWhenRejected(new Consumer() { - @Override - public void consume(String error) { - promise.setError(createError(error == null ? "Internal error" : error)); - } - }); + asyncResult.doWhenDone(() -> promise.setResult(null)).doWhenRejected( + error -> promise.setError(createError(error == null ? "Internal error" : error))); return promise; } @@ -128,12 +82,7 @@ public abstract class Promise { public void consume(T result) { promise.setResult(result); } - }).doWhenRejected(new Consumer() { - @Override - public void consume(String error) { - promise.setError(error); - } - }); + }).doWhenRejected(promise::setError); return promise; } @@ -183,16 +132,20 @@ public abstract class Promise { /** * Log error if not message error */ - public static void logError(@NotNull Logger logger, @NotNull Throwable e) { + public static boolean logError(@NotNull Logger logger, @NotNull Throwable e) { if (e instanceof MessageError) { ThreeState log = ((MessageError)e).log; if (log == ThreeState.YES || (log == ThreeState.UNSURE && ApplicationManager.getApplication().isUnitTestMode())) { logger.error(e); + return true; } } else if (!(e instanceof ProcessCanceledException)) { logger.error(e); + return true; } + + return false; } public abstract void notify(@NotNull AsyncPromise child); diff --git a/platform/core-api/src/org/jetbrains/concurrency/RejectedPromise.java b/platform/platform-api/src/org/jetbrains/concurrency/RejectedPromise.java similarity index 97% rename from platform/core-api/src/org/jetbrains/concurrency/RejectedPromise.java rename to platform/platform-api/src/org/jetbrains/concurrency/RejectedPromise.java index c45f0c57b6e7..af8d09d0746c 100644 --- a/platform/core-api/src/org/jetbrains/concurrency/RejectedPromise.java +++ b/platform/platform-api/src/org/jetbrains/concurrency/RejectedPromise.java @@ -42,7 +42,7 @@ class RejectedPromise extends Promise { @NotNull @Override public Promise rejected(@NotNull Consumer rejected) { - if (!AsyncPromise.isObsolete(rejected)) { + if (!AsyncPromiseKt.isObsolete(rejected)) { rejected.consume(error); } return this; diff --git a/platform/platform-api/src/com/intellij/util/concurrency/promise-ex.kt b/platform/platform-api/src/org/jetbrains/concurrency/promise-ex.kt similarity index 70% rename from platform/platform-api/src/com/intellij/util/concurrency/promise-ex.kt rename to platform/platform-api/src/org/jetbrains/concurrency/promise-ex.kt index f508fd8b030b..e923bcdba6d6 100644 --- a/platform/platform-api/src/com/intellij/util/concurrency/promise-ex.kt +++ b/platform/platform-api/src/org/jetbrains/concurrency/promise-ex.kt @@ -46,4 +46,31 @@ private class CountDownConsumer(@Volatile private var countDown: Int, private promise.setResult(totalResult) } } +} + +fun any(promises: Collection>, totalError: String): Promise { + if (promises.isEmpty()) { + return resolvedPromise(null) + } + else if (promises.size == 1) { + return promises.first() + } + + val totalPromise = AsyncPromise() + val done = Consumer { result -> totalPromise.setResult(result) } + val rejected = object : Consumer { + @Volatile private var toConsume = promises.size + + override fun consume(throwable: Throwable) { + if (--toConsume <= 0) { + totalPromise.setError(totalError) + } + } + } + + for (promise in promises) { + promise.done(done) + promise.rejected(rejected) + } + return totalPromise } \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/http/HttpFileEditor.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/http/HttpFileEditor.java index 5948768fe571..b3ffe9d3eb3e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/http/HttpFileEditor.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/http/HttpFileEditor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -19,10 +19,8 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.fileEditor.TextEditor; import com.intellij.openapi.fileEditor.impl.BaseRemoteFileEditor; import com.intellij.openapi.project.Project; -import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.impl.http.HttpVirtualFile; -import com.intellij.openapi.vfs.impl.http.RemoteFileInfo; -import com.intellij.util.Consumer; +import com.intellij.openapi.vfs.impl.http.RemoteFileInfoImpl; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -38,7 +36,7 @@ class HttpFileEditor extends BaseRemoteFileEditor { super(project); myPanel = new RemoteFilePanel(project, virtualFile, this); - RemoteFileInfo fileInfo = virtualFile.getFileInfo(); + RemoteFileInfoImpl fileInfo = (RemoteFileInfoImpl)virtualFile.getFileInfo(); assert fileInfo != null; fileInfo.download() .done(file -> ApplicationManager.getApplication().invokeLater(() -> contentLoaded(), myProject.getDisposed())) diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/RemoteFileInfoImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/RemoteFileInfoImpl.java index 4ed1b015e1d9..dd2af837a7ad 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/RemoteFileInfoImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/RemoteFileInfoImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -292,7 +292,6 @@ public class RemoteFileInfoImpl implements RemoteContentProvider.DownloadingCall } @NotNull - @Override public Promise download() { synchronized (myLock) { switch (getState()) { diff --git a/platform/platform-impl/src/org/jetbrains/concurrency/promise.kt b/platform/platform-impl/src/org/jetbrains/concurrency/promise.kt index 6219bfb59c6f..0e14060afe04 100644 --- a/platform/platform-impl/src/org/jetbrains/concurrency/promise.kt +++ b/platform/platform-impl/src/org/jetbrains/concurrency/promise.kt @@ -82,8 +82,6 @@ inline fun Promise<*>.rejected(node: Obsolescent, crossinline handler: (Throwabl fun rejectedPromise(error: String): Promise = Promise.reject(error) -fun rejectedPromise(error: Throwable): Promise = Promise.reject(error) - @Suppress("UNCHECKED_CAST") fun rejectedPromise(): Promise = rejectedPromise as Promise @@ -96,16 +94,6 @@ val Promise<*>.isPending: Boolean val Promise<*>.isFulfilled: Boolean get() = state == Promise.State.FULFILLED -inline fun AsyncPromise<*>.catchError(runnable: () -> T): T? { - try { - return runnable() - } - catch (e: Throwable) { - setError(e) - return null - } -} - fun collectResults(promises: List>): Promise> { if (promises.isEmpty()) { return resolvedPromise(emptyList()) diff --git a/platform/platform-resources-en/src/messages/IdeBundle.properties b/platform/platform-resources-en/src/messages/IdeBundle.properties index 26abc44aad72..3f541db2606e 100644 --- a/platform/platform-resources-en/src/messages/IdeBundle.properties +++ b/platform/platform-resources-en/src/messages/IdeBundle.properties @@ -1136,7 +1136,7 @@ low.disk.space.message=Low disk space on a {0} system directory partition prompt.goto.inspection.enter.name=Enter inspection name: goto.inspection.action.text=&Run Inspection by Name... -goto.inspection.action.choose.inherit.settings.from=Inherit inspection options from +goto.inspection.action.choose.inherit.settings.from=Inspection options label.no.inspections.found=No inspections found #Scripting library management diff --git a/platform/platform-tests/testSrc/com/intellij/util/containers/TreeTraverserTest.java b/platform/platform-tests/testSrc/com/intellij/util/containers/TreeTraverserTest.java index 3c216266a644..7fc6b3c55135 100644 --- a/platform/platform-tests/testSrc/com/intellij/util/containers/TreeTraverserTest.java +++ b/platform/platform-tests/testSrc/com/intellij/util/containers/TreeTraverserTest.java @@ -18,7 +18,10 @@ package com.intellij.util.containers; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Conditions; -import com.intellij.util.*; +import com.intellij.util.Function; +import com.intellij.util.Functions; +import com.intellij.util.PairFunction; +import com.intellij.util.Processor; import junit.framework.TestCase; import org.jetbrains.annotations.NotNull; @@ -425,21 +428,16 @@ public class TreeTraverserTest extends TestCase { // GuidedTraversal ---------------------------------------------- @NotNull - private static Function.Mono> initGuide(@NotNull final TreeTraversal traversal) { - return new Function.Mono>() { - @Override - public TreeTraversal.GuidedIt fun(TreeTraversal.GuidedIt it) { - return it.setGuide(it1 -> { - if (traversal == TreeTraversal.PRE_ORDER_DFS) { - it1.queueNext(it1.curChild).result(it1.curChild); - } - else if (traversal == TreeTraversal.POST_ORDER_DFS) { - it1.queueNext(it1.curChild).result(it1.curChild == null ? it1.curParent : null); - } - else if (traversal == TreeTraversal.PLAIN_BFS) { - it1.queueLast(it1.curChild).result(it1.curChild); - } - }); + private static TreeTraversal.GuidedIt.Guide newGuide(@NotNull final TreeTraversal traversal) { + return it -> { + if (traversal == TreeTraversal.PRE_ORDER_DFS) { + it.queueNext(it.curChild).result(it.curChild); + } + else if (traversal == TreeTraversal.POST_ORDER_DFS) { + it.queueNext(it.curChild).result(it.curChild == null ? it.curParent : null); + } + else if (traversal == TreeTraversal.PLAIN_BFS) { + it.queueLast(it.curChild).result(it.curChild); } }; } @@ -451,7 +449,7 @@ public class TreeTraverserTest extends TestCase { } private static void verifyGuidedTraversal(TreeTraversal traversal) { - assertEquals(numTraverser2(TreeTraversal.GUIDED_TRAVERSAL).fun(1).intercept(initGuide(traversal)).toList(), + assertEquals(numTraverser2(TreeTraversal.GUIDED_TRAVERSAL(newGuide(traversal))).fun(1).toList(), numTraverser2(traversal).fun(1).toList()); } diff --git a/platform/script-debugger/backend/src/DeclarativeScope.kt b/platform/script-debugger/backend/src/DeclarativeScope.kt index db1e206776a3..ed6523dd66d5 100644 --- a/platform/script-debugger/backend/src/DeclarativeScope.kt +++ b/platform/script-debugger/backend/src/DeclarativeScope.kt @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -15,8 +15,8 @@ */ package org.jetbrains.debugger -import com.intellij.util.Consumer import org.jetbrains.concurrency.Promise +import org.jetbrains.concurrency.cancelledPromise import org.jetbrains.debugger.values.ObjectValue import org.jetbrains.debugger.values.ValueManager @@ -25,14 +25,10 @@ abstract class DeclarativeScope(type: Scope.Type, protected fun loadScopeObjectProperties(value: ObjectValue): Promise> { if (childrenManager.valueManager.isObsolete) { - return ValueManager.reject() + return cancelledPromise() } - return value.properties.done(object : Consumer> { - override fun consume(variables: List) { - childrenManager.updateCacheStamp() - } - }) + return value.properties.done { childrenManager.updateCacheStamp() } } override fun getVariablesHost() = childrenManager diff --git a/platform/script-debugger/backend/src/org/jetbrains/debugger/VariablesHost.java b/platform/script-debugger/backend/src/org/jetbrains/debugger/VariablesHost.java index 746016d690cf..f83f8010a2c4 100644 --- a/platform/script-debugger/backend/src/org/jetbrains/debugger/VariablesHost.java +++ b/platform/script-debugger/backend/src/org/jetbrains/debugger/VariablesHost.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -17,6 +17,7 @@ package org.jetbrains.debugger; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.concurrency.AsyncPromiseKt; import org.jetbrains.concurrency.Promise; import org.jetbrains.concurrency.PromiseManager; import org.jetbrains.debugger.values.ValueManager; @@ -35,7 +36,7 @@ public abstract class VariablesHost { @NotNull @Override public Promise load(@NotNull VariablesHost host) { - return host.valueManager.isObsolete() ? ValueManager.Companion.reject() : host.load(); + return host.valueManager.isObsolete() ? AsyncPromiseKt.cancelledPromise() : host.load(); } }; diff --git a/platform/script-debugger/backend/src/org/jetbrains/debugger/values/ValueManager.kt b/platform/script-debugger/backend/src/org/jetbrains/debugger/values/ValueManager.kt index 9d41c63f939c..f1d1ee5740c3 100644 --- a/platform/script-debugger/backend/src/org/jetbrains/debugger/values/ValueManager.kt +++ b/platform/script-debugger/backend/src/org/jetbrains/debugger/values/ValueManager.kt @@ -15,10 +15,7 @@ */ package org.jetbrains.debugger.values -import org.jetbrains.concurrency.AsyncPromise import org.jetbrains.concurrency.Obsolescent -import org.jetbrains.concurrency.Promise -import org.jetbrains.concurrency.rejectedPromise import java.util.concurrent.atomic.AtomicInteger /** @@ -43,11 +40,4 @@ abstract class ValueManager() : Obsolescent { fun markObsolete() { obsolete = true } - - companion object { - val OBSOLETE_CONTEXT_PROMISE = rejectedPromise(AsyncPromise.OBSOLETE_ERROR) - - @Suppress("CAST_NEVER_SUCCEEDS") - fun reject() = OBSOLETE_CONTEXT_PROMISE as Promise - } } \ No newline at end of file diff --git a/platform/script-debugger/backend/src/org/jetbrains/rpc/CommandProcessor.kt b/platform/script-debugger/backend/src/org/jetbrains/rpc/CommandProcessor.kt index 880b2b45ff2d..cd144974068b 100644 --- a/platform/script-debugger/backend/src/org/jetbrains/rpc/CommandProcessor.kt +++ b/platform/script-debugger/backend/src/org/jetbrains/rpc/CommandProcessor.kt @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -54,7 +54,7 @@ fun requestToByteBuf(message: Request<*>, isDebugEnabled: Boolean = LOG.isDebugE return content } -interface ResultReader { +interface ResultReader { fun readResult(readMethodName: String, successResponse: RESPONSE): RESULT? } diff --git a/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/RejectErrorReporter.java b/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/RejectErrorReporter.java deleted file mode 100644 index 337ec586106e..000000000000 --- a/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/RejectErrorReporter.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2000-2015 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 org.jetbrains.debugger; - -import com.intellij.util.Consumer; -import com.intellij.xdebugger.XDebugSession; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.concurrency.AsyncPromise; -import org.jetbrains.concurrency.Promise; -import org.jetbrains.rpc.CommandProcessorKt; - -public final class RejectErrorReporter implements Consumer { - private final XDebugSession session; - private final String description; - - public RejectErrorReporter(@NotNull XDebugSession session) { - this(session, null); - } - - public RejectErrorReporter(@NotNull XDebugSession session, @Nullable String description) { - this.session = session; - this.description = description; - } - - @Override - public void consume(Throwable error) { - Promise.logError(CommandProcessorKt.getLOG(), error); - if (error != AsyncPromise.OBSOLETE_ERROR) { - session.reportError((description == null ? "" : description + ": ") + error.getMessage()); - } - } -} \ No newline at end of file diff --git a/platform/script-debugger/debugger-ui/src/util.kt b/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/RejectErrorReporter.kt similarity index 60% rename from platform/script-debugger/debugger-ui/src/util.kt rename to platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/RejectErrorReporter.kt index 6bb7d71f1ad0..9a2b08606ce5 100644 --- a/platform/script-debugger/debugger-ui/src/util.kt +++ b/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/RejectErrorReporter.kt @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * 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. @@ -13,17 +13,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.xdebugger.util +package org.jetbrains.debugger +import com.intellij.util.Consumer import com.intellij.xdebugger.XDebugSession -import org.jetbrains.concurrency.AsyncPromise import org.jetbrains.concurrency.Promise import org.jetbrains.rpc.LOG -// have to use package "com.intellij.xdebugger.util" to avoid package clash -fun XDebugSession.rejectedErrorReporter(description: String? = null): (Throwable) -> Unit = { - Promise.logError(LOG, it) - if (it != AsyncPromise.OBSOLETE_ERROR) { - reportError("${if (description == null) "" else description + ": "}${it.message}") +class RejectErrorReporter @JvmOverloads constructor(private val session: XDebugSession, private val description: String? = null) : Consumer { + override fun consume(error: Throwable) { + if (Promise.logError(LOG, error)) { + session.reportError("${if (description == null) "" else "$description: "}${error.message}") + } } } \ No newline at end of file diff --git a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/OutMessage.kt b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/OutMessage.kt index 4e04af8cb877..63a17b083aa4 100644 --- a/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/OutMessage.kt +++ b/platform/script-debugger/protocol/protocol-reader-runtime/src/org/jetbrains/jsonProtocol/OutMessage.kt @@ -201,7 +201,7 @@ open class OutMessage() { fun writeNullableString(name: String, value: CharSequence?) { beginArguments() - writer.name(name).value(value!!.toString()) + writer.name(name).value(value?.toString() ?: null) } companion object { diff --git a/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java b/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java index 07dc98d4578f..364d75814091 100644 --- a/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java +++ b/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java @@ -708,12 +708,8 @@ public abstract class PlatformTestCase extends UsefulTestCase implements DataPro } } - protected boolean isRunInEdt() { - return true; - } - protected void runBareRunnable(ThrowableRunnable runnable) throws Throwable { - if (isRunInEdt()) { + if (runInDispatchThread()) { EdtTestUtil.runInEdtAndWait(runnable); } else { diff --git a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java index 7d48e82d6143..2bd3161e69e7 100644 --- a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java +++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java @@ -27,6 +27,7 @@ import com.intellij.codeInsight.daemon.impl.*; import com.intellij.codeInsight.folding.CodeFoldingManager; import com.intellij.codeInsight.highlighting.actions.HighlightUsagesAction; import com.intellij.codeInsight.intention.IntentionAction; +import com.intellij.codeInsight.intention.impl.IntentionListStep; import com.intellij.codeInsight.intention.impl.ShowIntentionActionsHandler; import com.intellij.codeInsight.lookup.Lookup; import com.intellij.codeInsight.lookup.LookupElement; @@ -296,56 +297,26 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig private static List doGetAvailableIntentions(@NotNull Editor editor, @NotNull PsiFile file) { ShowIntentionsPass.IntentionsInfo intentions = new ShowIntentionsPass.IntentionsInfo(); ShowIntentionsPass.getActionsToShow(editor, file, intentions, -1); - List descriptors = new ArrayList(); - descriptors.addAll(intentions.intentionsToShow); - descriptors.addAll(intentions.errorFixesToShow); - descriptors.addAll(intentions.inspectionFixesToShow); - descriptors.addAll(intentions.guttersToShow); - - final int fileOffset = editor.getCaretModel().getOffset(); - PsiElement hostElement = file.getViewProvider().findElementAt(fileOffset, file.getLanguage()); - PsiElement injectedElement = InjectedLanguageUtil.findElementAtNoCommit(file, fileOffset); - - PsiFile injectedFile = injectedElement != null ? injectedElement.getContainingFile() : null; - Editor injectedEditor = InjectedLanguageUtil.getInjectedEditorForInjectedFile(editor, injectedFile); List result = new ArrayList(); + IntentionListStep intentionListStep = new IntentionListStep(null, intentions, editor, file, file.getProject()); + for (Map.Entry> entry : intentionListStep.getActionsWithSubActions().entrySet()) { + result.add(entry.getKey()); + result.addAll(entry.getValue()); + } List infos = DaemonCodeAnalyzerEx.getInstanceEx(file.getProject()).getFileLevelHighlights(file.getProject(), file); for (HighlightInfo info : infos) { for (Pair pair : info.quickFixActionRanges) { HighlightInfo.IntentionActionDescriptor actionInGroup = pair.first; - final IntentionAction action = actionInGroup.getAction(); - - if (ShowIntentionActionsHandler.availableFor(file, editor, action) - || - injectedElement != null && hostElement != injectedElement && ShowIntentionActionsHandler.availableFor(injectedFile, injectedEditor, action)) { - descriptors.add(actionInGroup); - } - } - } - - // add all intention options for simplicity - for (HighlightInfo.IntentionActionDescriptor descriptor : descriptors) { - result.add(descriptor.getAction()); - - if (injectedElement != null && injectedElement != hostElement) { - List options = descriptor.getOptions(injectedElement, injectedEditor); - if (options != null) { - for (IntentionAction option : options) { - if (ShowIntentionActionsHandler.availableFor(injectedFile, injectedEditor, option)) { - result.add(option); - } - } - } - } - - if (hostElement != null) { - List options = descriptor.getOptions(hostElement, editor); - if (options != null) { - for (IntentionAction option : options) { - if (ShowIntentionActionsHandler.availableFor(file, editor, option)) { - result.add(option); + if (actionInGroup.getAction().isAvailable(file.getProject(), editor, file)) { + result.add(actionInGroup.getAction()); + List options = actionInGroup.getOptions(file, editor); + if (options != null) { + for (IntentionAction subAction : options) { + if (subAction.isAvailable(file.getProject(), editor, file)) { + result.add(subAction); + } } } } @@ -1315,7 +1286,7 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig PlatformTestCase.synchronizeTempDirVfs(tempDir); myPsiManager = (PsiManagerImpl)PsiManager.getInstance(getProject()); - configureInspections(LocalInspectionTool.EMPTY_ARRAY, getProject(), Collections.emptyList(), getTestRootDisposable()); + configureInspections(LocalInspectionTool.EMPTY_ARRAY, getProject(), Collections.emptyList(), getTestRootDisposable()); DaemonCodeAnalyzerImpl daemonCodeAnalyzer = (DaemonCodeAnalyzerImpl)DaemonCodeAnalyzer.getInstance(getProject()); daemonCodeAnalyzer.prepareForTest(); diff --git a/platform/usageView/src/com/intellij/usages/impl/UsageViewImpl.java b/platform/usageView/src/com/intellij/usages/impl/UsageViewImpl.java index 0c279e77df35..fd580538a454 100644 --- a/platform/usageView/src/com/intellij/usages/impl/UsageViewImpl.java +++ b/platform/usageView/src/com/intellij/usages/impl/UsageViewImpl.java @@ -106,7 +106,7 @@ public class UsageViewImpl implements UsageView, UsageModelTracker.UsageModelTra private final ExporterToTextFile myTextFileExporter = new ExporterToTextFile(this); private final Alarm myUpdateAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD); - private final ExclusionHandler myExclusionHandler; + private final ExclusionHandler myExclusionHandler; private final UsageModelTracker myModelTracker; private final Map myUsageNodes = new ConcurrentHashMap(); public static final UsageNode NULL_NODE = new UsageNode(NullUsage.INSTANCE, new UsageViewTreeModelBuilder(new UsageViewPresentation(), UsageTarget.EMPTY_ARRAY)); @@ -253,21 +253,26 @@ public class UsageViewImpl implements UsageView, UsageModelTracker.UsageModelTra runnable.run(); return true; }, o -> isDisposed || project.isDisposed(), 200); - myExclusionHandler = new ExclusionHandler() { + myExclusionHandler = new ExclusionHandler() { @Override - public boolean isNodeExcluded(@NotNull Node node) { - return node.isDataExcluded(); + public boolean isNodeExclusionAvailable(@NotNull DefaultMutableTreeNode node) { + return node instanceof UsageNode; } @Override - public void excludeNode(@NotNull Node node) { + public boolean isNodeExcluded(@NotNull DefaultMutableTreeNode node) { + return ((UsageNode)node).isDataExcluded(); + } + + @Override + public void excludeNode(@NotNull DefaultMutableTreeNode node) { final HashSet usages = new HashSet<>(); collectUsages(node, usages); excludeUsages(usages.toArray(new Usage[usages.size()])); } @Override - public void includeNode(@NotNull Node node) { + public void includeNode(@NotNull DefaultMutableTreeNode node) { final HashSet usages = new HashSet<>(); collectUsages(node, usages); includeUsages(usages.toArray(new Usage[usages.size()])); diff --git a/platform/util/src/com/intellij/util/containers/FilteredTraverserBase.java b/platform/util/src/com/intellij/util/containers/FilteredTraverserBase.java index 3c4f3312fef8..4b92ff3fd5d4 100644 --- a/platform/util/src/com/intellij/util/containers/FilteredTraverserBase.java +++ b/platform/util/src/com/intellij/util/containers/FilteredTraverserBase.java @@ -17,7 +17,6 @@ package com.intellij.util.containers; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Conditions; -import com.intellij.util.Consumer; import com.intellij.util.Function; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -63,7 +62,7 @@ public abstract class FilteredTraverserBase(roots, traversal, expand, regard, this.filter, forceIgnore, forceDisregard.append(c)); } - Function.Mono> createChildrenGuide(final T parent) { - final Condition expand = buildExpandConditionForChildren(parent); - class G implements Consumer>, Function.Mono> { - + TreeTraversal.GuidedIt.Guide createChildrenGuide(final T parent) { + return new TreeTraversal.GuidedIt.Guide() { + final Condition expand = buildExpandConditionForChildren(parent); @Override - public TreeTraversal.GuidedIt fun(TreeTraversal.GuidedIt it) { - return it.setGuide(this); + public void guide(TreeTraversal.GuidedIt guidedIt) { + doPerformChildrenGuidance(guidedIt, expand); } - - @Override - public void consume(TreeTraversal.GuidedIt it) { - doPerformChildrenGuidance(it, expand); - } - } - return new G(); + }; } private void doPerformChildrenGuidance(TreeTraversal.GuidedIt it, Condition expand) { @@ -296,7 +288,7 @@ public abstract class FilteredTraverserBase EMPTY = new Meta( @@ -326,37 +318,33 @@ public abstract class FilteredTraverserBase(impl, this); } - private boolean valueAnd(T t) { + boolean valueAnd(T t) { for (Cond c = this; c != null; c = c.next) { if (!c.impl.value(t)) return false; } return true; } - private boolean valueOr(T t) { + boolean valueOr(T t) { for (Cond c = this; c != null; c = c.next) { if (c.impl.value(t)) return true; } return false; } - Condition OR() { - return new Condition() { - @Override - public boolean value(T t) { - return valueOr(t); - } - }; - } + final Condition OR = new Condition() { + @Override + public boolean value(T t) { + return valueOr(t); + } + }; - Condition AND() { - return new Condition() { - @Override - public boolean value(T t) { - return valueAnd(t); - } - }; - } + final Condition AND = new Condition() { + @Override + public boolean value(T t) { + return valueAnd(t); + } + }; @Override public String toString() { diff --git a/platform/util/src/com/intellij/util/containers/TreeTraversal.java b/platform/util/src/com/intellij/util/containers/TreeTraversal.java index 300eb5e93a9e..e8f8bb344469 100644 --- a/platform/util/src/com/intellij/util/containers/TreeTraversal.java +++ b/platform/util/src/com/intellij/util/containers/TreeTraversal.java @@ -16,7 +16,6 @@ package com.intellij.util.containers; import com.intellij.openapi.util.Condition; -import com.intellij.util.Consumer; import com.intellij.util.Function; import com.intellij.util.Functions; import org.jetbrains.annotations.NotNull; @@ -148,14 +147,17 @@ public abstract class TreeTraversal { } public static abstract class GuidedIt extends It { + + public interface Guide { + void guide(GuidedIt guidedIt); + } + @Nullable public T curChild, curParent; @Nullable public Iterable curChildren; public boolean curNoChildren; - public abstract GuidedIt setGuide(Consumer> guide); - public abstract GuidedIt queueNext(T child); public abstract GuidedIt result(T node); public abstract GuidedIt queueLast(T child); @@ -166,13 +168,16 @@ public abstract class TreeTraversal { } @NotNull - public static final TreeTraversal GUIDED_TRAVERSAL = new TreeTraversal("GUIDED_TRAVERSAL") { - @NotNull - @Override - public It createIterator(@NotNull Iterable roots, @NotNull Function> tree) { - return new GuidedItImpl(roots, tree); - } - }; + public static TreeTraversal GUIDED_TRAVERSAL(@NotNull final GuidedIt.Guide guide) { + return new TreeTraversal("GUIDED_TRAVERSAL") { + @NotNull + @Override + public It createIterator(@NotNull Iterable roots, @NotNull Function> tree) { + //noinspection unchecked + return new GuidedItImpl(roots, tree, (GuidedIt.Guide)guide); + } + }; + } /** * Returns an iterator over the nodes in a tree structure, using pre-order @@ -503,19 +508,17 @@ public abstract class TreeTraversal { // Misc // ----------------------------------------------------------------------------- private static final class GuidedItImpl extends GuidedIt { - P1 first, last; + final Guide guide; - Consumer> guide; + P1 first, last; T curResult; - GuidedItImpl(@NotNull Iterable roots, Function> tree) { + GuidedItImpl(@NotNull Iterable roots, + @NotNull Function> tree, + @NotNull Guide guide) { super(tree); first = last = P1.create(roots); - } - - public GuidedIt setGuide(Consumer> guide) { this.guide = guide; - return this; } public GuidedIt queueNext(T child) { @@ -546,7 +549,7 @@ public abstract class TreeTraversal { curParent = top.node; curChildren = top.itle; curNoChildren = top.empty; - guide.consume(this); + guide.guide(this); } if (!hasNext) { last = last.remove(); diff --git a/platform/vcs-tests/testSrc/com/intellij/vcs/test/VcsPlatformTest.kt b/platform/vcs-tests/testSrc/com/intellij/vcs/test/VcsPlatformTest.kt index dd9bc487be53..162f55382acd 100644 --- a/platform/vcs-tests/testSrc/com/intellij/vcs/test/VcsPlatformTest.kt +++ b/platform/vcs-tests/testSrc/com/intellij/vcs/test/VcsPlatformTest.kt @@ -88,7 +88,7 @@ abstract class VcsPlatformTest : PlatformTestCase() { // we don't need a module in Git tests } - override fun isRunInEdt(): Boolean { + override fun runInDispatchThread(): Boolean { return false } diff --git a/plugins/github/test/org/jetbrains/plugins/github/test/GithubTest.java b/plugins/github/test/org/jetbrains/plugins/github/test/GithubTest.java index b32f77b0c03a..da64988f5b16 100644 --- a/plugins/github/test/org/jetbrains/plugins/github/test/GithubTest.java +++ b/plugins/github/test/org/jetbrains/plugins/github/test/GithubTest.java @@ -206,9 +206,4 @@ public abstract class GithubTest extends GitPlatformTest { protected void afterTest() throws Exception { } - - @Override - protected boolean isRunInEdt() { - return true; - } } diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/references/PropertyReferenceBase.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/references/PropertyReferenceBase.java index e8ea30f5dc76..bd5a0dc543c1 100644 --- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/references/PropertyReferenceBase.java +++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/references/PropertyReferenceBase.java @@ -20,11 +20,15 @@ import com.intellij.lang.properties.IProperty; import com.intellij.lang.properties.PropertiesBundle; import com.intellij.lang.properties.PropertiesImplUtil; import com.intellij.lang.properties.psi.PropertiesFile; +import com.intellij.lang.properties.xml.XmlPropertiesFileImpl; +import com.intellij.lang.properties.xml.XmlProperty; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.TextRange; +import com.intellij.pom.PomTargetPsiElement; import com.intellij.pom.references.PomService; import com.intellij.psi.*; +import com.intellij.psi.xml.XmlTag; import com.intellij.util.ArrayUtil; import com.intellij.util.IncorrectOperationException; import com.intellij.util.containers.ContainerUtil; @@ -32,7 +36,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; -import java.util.Comparator; import java.util.List; import java.util.Set; @@ -40,7 +43,7 @@ import java.util.Set; * @author nik */ public abstract class PropertyReferenceBase implements PsiPolyVariantReference, EmptyResolveMessageProvider { - private static final Logger LOG = Logger.getInstance("#com.intellij.lang.properties.references.PropertyReferenceBase"); + private static final Logger LOG = Logger.getInstance(PropertyReferenceBase.class); protected final String myKey; protected final PsiElement myElement; protected boolean mySoft; @@ -114,6 +117,7 @@ public abstract class PropertyReferenceBase implements PsiPolyVariantReference, } public boolean isReferenceTo(PsiElement element) { + if (!isProperty(element)) return false; for (ResolveResult result : multiResolve(false)) { final PsiElement el = result.getElement(); if (el != null && el.isEquivalentTo(element)) return true; @@ -181,4 +185,17 @@ public abstract class PropertyReferenceBase implements PsiPolyVariantReference, public Object[] getVariants() { return ArrayUtil.EMPTY_OBJECT_ARRAY; } + + private static boolean isProperty(PsiElement element) { + if (element instanceof IProperty) { + return true; + } + if (element instanceof PomTargetPsiElement) { + return ((PomTargetPsiElement)element).getTarget() instanceof XmlProperty; + } + if (element instanceof XmlTag && ((XmlTag)element).getName().equals(XmlPropertiesFileImpl.ENTRY_TAG_NAME)) { + return PropertiesImplUtil.isPropertiesFile(element.getContainingFile()); + } + return false; + } } diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/xml/XmlPropertiesFileImpl.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/xml/XmlPropertiesFileImpl.java index 243538ca581e..f1db7c69d264 100644 --- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/xml/XmlPropertiesFileImpl.java +++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/xml/XmlPropertiesFileImpl.java @@ -46,6 +46,8 @@ import java.util.*; * Date: 7/26/11 */ public class XmlPropertiesFileImpl extends XmlPropertiesFile { + public static final String ENTRY_TAG_NAME = "entry"; + private static final Key> KEY = Key.create("xml properties file"); private final XmlFile myFile; @@ -62,7 +64,7 @@ public class XmlPropertiesFileImpl extends XmlPropertiesFile { XmlTag rootTag = myFile.getRootTag(); final List propertiesOrder = new ArrayList(); if (rootTag != null) { - XmlTag[] entries = rootTag.findSubTags("entry"); + XmlTag[] entries = rootTag.findSubTags(ENTRY_TAG_NAME); for (XmlTag entry : entries) { XmlProperty property = new XmlProperty(entry, this); propertiesOrder.add(property); diff --git a/xml/impl/src/com/intellij/codeInsight/completion/XmlSmartEnterProcessor.java b/xml/impl/src/com/intellij/codeInsight/completion/XmlSmartEnterProcessor.java index d13430d54e57..cef0afbf8b5b 100644 --- a/xml/impl/src/com/intellij/codeInsight/completion/XmlSmartEnterProcessor.java +++ b/xml/impl/src/com/intellij/codeInsight/completion/XmlSmartEnterProcessor.java @@ -121,10 +121,10 @@ public class XmlSmartEnterProcessor extends SmartEnterProcessor { } else if (probableCommaOffset >= text.length() || ((ch = text.charAt(probableCommaOffset)) != '/' && ch != '>')) { final XmlAttribute xmlAttribute = PsiTreeUtil.getParentOfType(atCaret, XmlAttribute.class, false, XmlTag.class); - final CharSequence text2insert = getClosingPart(xmlAttribute, tagAtCaret, true); + final String text2insert = getClosingPart(xmlAttribute, tagAtCaret, true); doc.insertString(insertionOffset, text2insert); - caretTo = insertionOffset + (text2insert.length() > 2 ? 1 : text2insert.length()); + caretTo = insertionOffset + text2insert.indexOf('>') + 1; } commitChanges(project, editor, psiFile, caretTo, null);