From a4e576a47484805a33c0a5f914c361ed63bfd3ac Mon Sep 17 00:00:00 2001 From: "Ilya.Kazakevich" Date: Sat, 31 Oct 2015 04:29:00 +0300 Subject: [PATCH 001/124] PY-17356: Attributes cached for function since as_manager / from_queryset is called multiple times --- .../python/psi/impl/PyFunctionImpl.java | 28 +++++++++++++++---- 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java index a88555bff68e..7f7b91c58f46 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java @@ -18,6 +18,7 @@ package com.jetbrains.python.psi.impl; import com.intellij.lang.ASTNode; import com.intellij.navigation.ItemPresentation; import com.intellij.openapi.extensions.Extensions; +import com.intellij.openapi.util.Key; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.text.StringUtil; @@ -29,10 +30,7 @@ import com.intellij.psi.search.LocalSearchScope; import com.intellij.psi.search.SearchScope; import com.intellij.psi.stubs.IStubElementType; import com.intellij.psi.stubs.StubElement; -import com.intellij.psi.util.CachedValueProvider; -import com.intellij.psi.util.CachedValuesManager; -import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.psi.util.QualifiedName; +import com.intellij.psi.util.*; import com.intellij.util.IncorrectOperationException; import com.intellij.util.PlatformIcons; import com.jetbrains.python.PyElementTypes; @@ -67,6 +65,9 @@ import static com.jetbrains.python.psi.impl.PyCallExpressionHelper.interpretAsMo */ public class PyFunctionImpl extends PyBaseElementImpl implements PyFunction { + private static final Key>> + ATTRIBUTES_KEY = Key.create("attributes"); + public PyFunctionImpl(ASTNode astNode) { super(astNode); } @@ -732,8 +733,23 @@ public class PyFunctionImpl extends PyBaseElementImpl implements @NotNull @Override public List findAttributes() { + return CachedValuesManager.getManager(getProject()).getCachedValue(this, ATTRIBUTES_KEY, new CachedValueProvider>() { + @Nullable + @Override + public Result> compute() { + final List result = findAttributesStatic(PyFunctionImpl.this); + return Result.create(result, PsiModificationTracker.MODIFICATION_COUNT); + } + }, false); + } + + /** + * @param self should be this + */ + @NotNull + private static List findAttributesStatic(@NotNull final PsiElement self) { final List result = new ArrayList(); - for (final PyAssignmentStatement statement : new PsiQuery(this).siblings(PyAssignmentStatement.class).getElements()) { + for (final PyAssignmentStatement statement : new PsiQuery(self).siblings(PyAssignmentStatement.class).getElements()) { for (final PyQualifiedExpression targetExpression : new PsiQuery(statement.getTargets()).filter(PyQualifiedExpression.class) .getElements()) { final PyExpression qualifier = targetExpression.getQualifier(); @@ -744,7 +760,7 @@ public class PyFunctionImpl extends PyBaseElementImpl implements if (qualifierReference == null) { continue; } - if (qualifierReference.isReferenceTo(this)) { + if (qualifierReference.isReferenceTo(self)) { result.add(statement); } } From c07ce34cb22639fb4e6edf8c39dce65b4e71feca Mon Sep 17 00:00:00 2001 From: "Ilya.Kazakevich" Date: Sat, 31 Oct 2015 05:23:16 +0300 Subject: [PATCH 002/124] PY-17356: PyTypeParser is slow, so we cache its result in PyCustomMember --- .../python/codeInsight/PyCustomMember.java | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/python/psi-api/src/com/jetbrains/python/codeInsight/PyCustomMember.java b/python/psi-api/src/com/jetbrains/python/codeInsight/PyCustomMember.java index 77218c6457fc..543d635050d5 100644 --- a/python/psi-api/src/com/jetbrains/python/codeInsight/PyCustomMember.java +++ b/python/psi-api/src/com/jetbrains/python/codeInsight/PyCustomMember.java @@ -17,8 +17,11 @@ package com.jetbrains.python.codeInsight; import com.intellij.extapi.psi.ASTWrapperPsiElement; import com.intellij.icons.AllIcons; +import com.intellij.openapi.util.Key; +import com.intellij.openapi.util.UserDataHolderBase; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiReference; +import com.intellij.psi.util.*; import com.intellij.util.Function; import com.jetbrains.python.psi.PyClass; import com.jetbrains.python.psi.PyFunction; @@ -34,7 +37,9 @@ import javax.swing.*; /** * @author Dennis.Ushakov */ -public class PyCustomMember { +public class PyCustomMember extends UserDataHolderBase { + private static final Key> + RESOLVE = Key.create("resolve"); private final String myName; private final boolean myResolveToInstance; private final Function myTypeCallback; @@ -165,14 +170,26 @@ public class PyCustomMember { } @Nullable - public PsiElement resolve(@NotNull PsiElement context) { + public PsiElement resolve(@NotNull final PsiElement context) { + if (myTarget != null) { return myTarget; } PyClass targetClass = null; if (myTypeName != null) { - targetClass = PyPsiFacade.getInstance(context.getProject()).createClassByQName(myTypeName, context); + + final ParameterizedCachedValueProvider provider = new ParameterizedCachedValueProvider() { + @Nullable + @Override + public CachedValueProvider.Result compute( + final PsiElement param) { + final PyClass result = PyPsiFacade.getInstance(param.getProject()).createClassByQName(myTypeName, param); + return CachedValueProvider.Result.create(result, PsiModificationTracker.MODIFICATION_COUNT); + } + }; + targetClass = CachedValuesManager.getManager(context.getProject()).getParameterizedCachedValue(this, RESOLVE, + provider, false, context); } final PsiElement resolveTarget = findResolveTarget(context); if (resolveTarget instanceof PyFunction && !myAlwaysResolveToCustomElement) { @@ -212,6 +229,7 @@ public class PyCustomMember { /** * Checks if some reference points to this element + * * @param reference reference to check * @return true if reference points to it */ From 92a04e100068305513ab0dc0dd6f0db5976f9008 Mon Sep 17 00:00:00 2001 From: "Ilya.Kazakevich" Date: Wed, 4 Nov 2015 02:48:29 +0300 Subject: [PATCH 003/124] PY-17356: shortcuts added to make inspections faster --- .../nameResolver/NameResolverTools.java | 80 ++++++++++++++++++- 1 file changed, 77 insertions(+), 3 deletions(-) diff --git a/python/psi-api/src/com/jetbrains/python/nameResolver/NameResolverTools.java b/python/psi-api/src/com/jetbrains/python/nameResolver/NameResolverTools.java index b9cbbaec5061..5118d2cd9edc 100644 --- a/python/psi-api/src/com/jetbrains/python/nameResolver/NameResolverTools.java +++ b/python/psi-api/src/com/jetbrains/python/nameResolver/NameResolverTools.java @@ -18,19 +18,22 @@ package com.jetbrains.python.nameResolver; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Pair; import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; import com.intellij.psi.PsiReference; import com.intellij.psi.util.PsiCacheKey; import com.intellij.psi.util.PsiModificationTracker; import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.util.QualifiedName; import com.intellij.util.Function; import com.jetbrains.python.psi.*; import com.jetbrains.python.psi.resolve.PyResolveContext; +import com.jetbrains.python.psi.types.PyFunctionType; +import com.jetbrains.python.psi.types.PyType; +import com.jetbrains.python.psi.types.TypeEvalContext; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; +import java.util.*; /** * @author Ilya.Kazakevich @@ -103,6 +106,77 @@ public final class NameResolverTools { return null; } + /** + * Same as {@link #isName(PyElement, FQNamesProvider...)} for call expr, but first checks name. + * Aliases not supported, but much lighter that way + * + * @param call expr + * @param function names to check + * @param context + * @return true if callee is correct + */ + public static boolean isCalleeShortCut(@NotNull final PyCallExpression call, + @NotNull final FQNamesProvider function, + @Nullable final TypeEvalContext context) { + if (context == null) { + return call.isCallee(function); + } + final PyExpression callee = call.getCallee(); + if (callee == null) { + return false; + } + + final PyType calleeType = context.getType(callee); + if (!(calleeType instanceof PyFunctionType)) { + return false; + } + final PyCallable callable = ((PyFunctionType)calleeType).getCallable(); + final String callableName = callable.getName(); + if (callableName == null) { + return false; + } + + final Set possibleNames = new HashSet(); + for (final String lastComponent : getLastComponents(function)) { + possibleNames.add(lastComponent); + } + return possibleNames.contains(callableName) && call.isCallee(function); + } + + @NotNull + private static List getLastComponents(@NotNull final FQNamesProvider provider) { + final List result = new ArrayList(); + for (final String name : provider.getNames()) { + final String component = QualifiedName.fromDottedString(name).getLastComponent(); + if (component != null) { + result.add(component); + } + } + return result; + } + + /** + * Checks if some string contains last component one of name + * @param text test to check + * @param names + */ + public static boolean isContainsName(@NotNull final String text, @NotNull final FQNamesProvider names) { + for (final String lastComponent : getLastComponents(names)) { + if (text.contains(lastComponent)) { + return true; + } + } + return false; + } + /** + * Checks if some file contains last component one of name + * @param file file to check + * @param names + */ + public static boolean isContainsName(@NotNull final PsiFile file, @NotNull final FQNamesProvider names) { + return isContainsName(file.getText(), names); + } + /** * Looks for call of some function */ From 33e0477669bafc0de9f1de40500d043b450d00d1 Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Thu, 5 Nov 2015 20:26:40 +0300 Subject: [PATCH 004/124] use Java 8 features in test --- .../softwrap/mapping/SoftWrapStressTest.java | 50 ++++++------------- 1 file changed, 14 insertions(+), 36 deletions(-) diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapStressTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapStressTest.java index fdc7acd86bdb..3fc17a9ca09c 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapStressTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapStressTest.java @@ -20,7 +20,6 @@ import com.intellij.openapi.editor.ex.DocumentEx; import com.intellij.openapi.editor.impl.AbstractEditorTest; import com.intellij.openapi.editor.impl.SoftWrapModelImpl; import com.intellij.openapi.util.registry.Registry; -import gnu.trove.TIntObjectProcedure; import org.jetbrains.annotations.NotNull; import java.util.*; @@ -82,8 +81,8 @@ public class SoftWrapStressTest extends AbstractEditorTest { } private static void checkConsistencyWithFoldingsAndTabs(CacheEntry entry) { - Map actualFoldRegions = new HashMap(); - List actualTabPositions = new ArrayList(); + Map actualFoldRegions = new HashMap<>(); + List actualTabPositions = new ArrayList<>(); for (int i = entry.startOffset; i < entry.endOffset; i++) { FoldRegion region = myEditor.getFoldingModel().getCollapsedRegionAtOffset(i); if (region == null) { @@ -97,16 +96,13 @@ public class SoftWrapStressTest extends AbstractEditorTest { } } } - final Map cachedFoldRegions = new HashMap(); - entry.getFoldingData().forEachEntry(new TIntObjectProcedure() { - @Override - public boolean execute(int offset, FoldingData data) { - cachedFoldRegions.put(offset, data.getFoldRegion()); - return true; - } + final Map cachedFoldRegions = new HashMap<>(); + entry.getFoldingData().forEachEntry((offset, data) -> { + cachedFoldRegions.put(offset, data.getFoldRegion()); + return true; }); assertEquals(actualFoldRegions, cachedFoldRegions); - List cachedTabPositions = new ArrayList(); + List cachedTabPositions = new ArrayList<>(); for (TabData tabData : entry.getTabData()) { cachedTabPositions.add(tabData.offset); } @@ -188,7 +184,7 @@ public class SoftWrapStressTest extends AbstractEditorTest { @NotNull private static Set checkSoftWraps() { List softWraps = myEditor.getSoftWrapModel().getSoftWrapsForRange(0, myEditor.getDocument().getTextLength()); - Set softWrapOffsets = new HashSet(); + Set softWrapOffsets = new HashSet<>(); int lastOffset = -1; for (SoftWrap softWrap : softWraps) { assertEquals(softWrap.getStart(), softWrap.getEnd()); @@ -253,12 +249,9 @@ public class SoftWrapStressTest extends AbstractEditorTest { final int endOffset = random.nextInt(textLength + 1); if (startOffset == endOffset) return; final FoldingModel foldingModel = editor.getFoldingModel(); - foldingModel.runBatchFoldingOperation(new Runnable() { - @Override - public void run() { - foldingModel.addFoldRegion(Math.min(startOffset, endOffset), Math.max(startOffset, endOffset), "."); - } - }); + foldingModel.runBatchFoldingOperation(() -> foldingModel.addFoldRegion(Math.min(startOffset, endOffset), + Math.max(startOffset, endOffset), + ".")); } } @@ -269,12 +262,7 @@ public class SoftWrapStressTest extends AbstractEditorTest { FoldRegion[] foldRegions = foldingModel.getAllFoldRegions(); if (foldRegions.length == 0) return; final FoldRegion region = foldRegions[random.nextInt(foldRegions.length)]; - foldingModel.runBatchFoldingOperation(new Runnable() { - @Override - public void run() { - foldingModel.removeFoldRegion(region); - } - }); + foldingModel.runBatchFoldingOperation(() -> foldingModel.removeFoldRegion(region)); } } @@ -285,12 +273,7 @@ public class SoftWrapStressTest extends AbstractEditorTest { FoldRegion[] foldRegions = foldingModel.getAllFoldRegions(); if (foldRegions.length == 0) return; final FoldRegion region = foldRegions[random.nextInt(foldRegions.length)]; - foldingModel.runBatchFoldingOperation(new Runnable() { - @Override - public void run() { - region.setExpanded(false); - } - }); + foldingModel.runBatchFoldingOperation(() -> region.setExpanded(false)); } } @@ -301,12 +284,7 @@ public class SoftWrapStressTest extends AbstractEditorTest { FoldRegion[] foldRegions = foldingModel.getAllFoldRegions(); if (foldRegions.length == 0) return; final FoldRegion region = foldRegions[random.nextInt(foldRegions.length)]; - foldingModel.runBatchFoldingOperation(new Runnable() { - @Override - public void run() { - region.setExpanded(true); - } - }); + foldingModel.runBatchFoldingOperation(() -> region.setExpanded(true)); } } } From 8de9b0fa459444ce3818473d6921aaba4b26cfb2 Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Thu, 5 Nov 2015 21:05:08 +0300 Subject: [PATCH 005/124] extract EditorStressTest --- .../openapi/editor/impl/EditorStressTest.java | 162 +++++++++++++++++ .../softwrap/mapping/SoftWrapStressTest.java | 165 +++--------------- 2 files changed, 185 insertions(+), 142 deletions(-) create mode 100644 platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/EditorStressTest.java diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/EditorStressTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/EditorStressTest.java new file mode 100644 index 000000000000..48ce8895a33d --- /dev/null +++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/EditorStressTest.java @@ -0,0 +1,162 @@ +/* + * 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 com.intellij.openapi.editor.impl; + +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.FoldRegion; +import com.intellij.openapi.editor.FoldingModel; +import com.intellij.openapi.editor.ex.DocumentEx; + +import java.util.Arrays; +import java.util.List; +import java.util.Random; + +public class EditorStressTest extends AbstractEditorTest { + private static final int ITERATIONS = 10000; + private static final Long SEED_OVERRIDE = null; // set non-null value to run with a specific seed + + private static final List ourActions = Arrays.asList(new AddText("a"), + new AddText("\n"), + new AddText("\t"), + new RemoveCharacter(), + new MoveCharacter(), + new AddFoldRegion(), + new RemoveFoldRegion(), + new CollapseFoldRegion(), + new ExpandFoldRegion()); + + private final Random myRandom = new Random() {{ + //noinspection ConstantConditions + setSeed(mySeed = (SEED_OVERRIDE == null ? nextLong() : SEED_OVERRIDE)); + }}; + private long mySeed; + + public void testRandomActions() { + int i = 0; + try { + initText(""); + configureSoftWraps(10); + for (i = 1; i <= ITERATIONS; i++) { + doRandomAction(); + checkConsistency(myEditor); + } + } + catch (Throwable t) { + throw new RuntimeException("Failed when run with seed=" + mySeed + " in iteration " + i, t); + } + } + + private void doRandomAction() { + ourActions.get(myRandom.nextInt(ourActions.size())).perform(myEditor, myRandom); + } + + protected void checkConsistency(Editor editor) { + } + + interface Action { + void perform(Editor editor, Random random); + } + + private static class AddText implements Action { + private final String myText; + + AddText(String text) { + myText = text; + } + + @Override + public void perform(Editor editor, Random random) { + Document document = editor.getDocument(); + int offset = random.nextInt(document.getTextLength() + 1); + document.insertString(offset, myText); + } + } + + private static class RemoveCharacter implements Action { + @Override + public void perform(Editor editor, Random random) { + Document document = editor.getDocument(); + int textLength = document.getTextLength(); + if (textLength <= 0) return; + int offset = random.nextInt(textLength); + document.deleteString(offset, offset + 1); + } + } + + private static class MoveCharacter implements Action { + @Override + public void perform(Editor editor, Random random) { + Document document = editor.getDocument(); + int textLength = document.getTextLength(); + if (textLength <= 0) return; + int offset = random.nextInt(textLength); + int targetOffset = random.nextInt(textLength + 1); + if (targetOffset < offset || targetOffset > offset + 1) { + ((DocumentEx)document).moveText(offset, offset + 1, targetOffset); + } + } + } + + private static class AddFoldRegion implements Action { + @Override + public void perform(final Editor editor, Random random) { + Document document = editor.getDocument(); + int textLength = document.getTextLength(); + if (textLength <= 0) return; + final int startOffset = random.nextInt(textLength + 1); + final int endOffset = random.nextInt(textLength + 1); + if (startOffset == endOffset) return; + final FoldingModel foldingModel = editor.getFoldingModel(); + foldingModel.runBatchFoldingOperation(() -> foldingModel.addFoldRegion(Math.min(startOffset, endOffset), + Math.max(startOffset, endOffset), + ".")); + } + } + + private static class RemoveFoldRegion implements Action { + @Override + public void perform(final Editor editor, Random random) { + final FoldingModel foldingModel = editor.getFoldingModel(); + FoldRegion[] foldRegions = foldingModel.getAllFoldRegions(); + if (foldRegions.length == 0) return; + final FoldRegion region = foldRegions[random.nextInt(foldRegions.length)]; + foldingModel.runBatchFoldingOperation(() -> foldingModel.removeFoldRegion(region)); + } + } + + private static class CollapseFoldRegion implements Action { + @Override + public void perform(final Editor editor, Random random) { + final FoldingModel foldingModel = editor.getFoldingModel(); + FoldRegion[] foldRegions = foldingModel.getAllFoldRegions(); + if (foldRegions.length == 0) return; + final FoldRegion region = foldRegions[random.nextInt(foldRegions.length)]; + foldingModel.runBatchFoldingOperation(() -> region.setExpanded(false)); + } + } + + private static class ExpandFoldRegion implements Action { + @Override + public void perform(final Editor editor, Random random) { + final FoldingModel foldingModel = editor.getFoldingModel(); + FoldRegion[] foldRegions = foldingModel.getAllFoldRegions(); + if (foldRegions.length == 0) return; + final FoldRegion region = foldRegions[random.nextInt(foldRegions.length)]; + foldingModel.runBatchFoldingOperation(() -> region.setExpanded(true)); + } + } +} \ No newline at end of file diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapStressTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapStressTest.java index 3fc17a9ca09c..d72fcdfc69bb 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapStressTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapStressTest.java @@ -16,77 +16,51 @@ package com.intellij.openapi.editor.impl.softwrap.mapping; import com.intellij.openapi.editor.*; -import com.intellij.openapi.editor.ex.DocumentEx; -import com.intellij.openapi.editor.impl.AbstractEditorTest; +import com.intellij.openapi.editor.impl.EditorStressTest; import com.intellij.openapi.editor.impl.SoftWrapModelImpl; import com.intellij.openapi.util.registry.Registry; import org.jetbrains.annotations.NotNull; import java.util.*; -public class SoftWrapStressTest extends AbstractEditorTest { - private static final int ITERATIONS = 10000; - private static final Long SEED_OVERRIDE = null; // set non-null value to run with a specific seed - - private static final List ourActions = Arrays.asList(new AddText("a"), - new AddText("\n"), - new AddText("\t"), - new RemoveCharacter(), - new MoveCharacter(), - new AddFoldRegion(), - new RemoveFoldRegion(), - new CollapseFoldRegion(), - new ExpandFoldRegion()); - - private final Random myRandom = new Random() {{ - //noinspection ConstantConditions - setSeed(mySeed = (SEED_OVERRIDE == null ? nextLong() : SEED_OVERRIDE)); - }}; - private long mySeed; - - public void testSoftWrapModelInternalCachesStayConsistentAfterDocumentAndFoldingChanges() { +public class SoftWrapStressTest extends EditorStressTest { + @Override + protected void setUp() throws Exception { + super.setUp(); Registry.get("editor.new.rendering").setValue(false); - int i = 0; + } + + @Override + protected void tearDown() throws Exception { try { - initText(""); - configureSoftWraps(10); - for (i = 1; i <= ITERATIONS; i++) { - doRandomAction(); - checkConsistency(); - } - } - catch (Throwable t) { - throw new RuntimeException("Failed when run with seed=" + mySeed + " in iteration " + i, t); - } - finally { Registry.get("editor.new.rendering").setValue(true); } + finally { + super.tearDown(); + } } - - private void doRandomAction() { - ourActions.get(myRandom.nextInt(ourActions.size())).perform(myEditor, myRandom); - } - - private static void checkConsistency() { - Set softWrapOffsets = checkSoftWraps(); - List cache = ((SoftWrapModelImpl)myEditor.getSoftWrapModel()).getDataMapper().getCache(); + + @Override + protected void checkConsistency(Editor editor) { + Set softWrapOffsets = checkSoftWraps(editor); + List cache = ((SoftWrapModelImpl)editor.getSoftWrapModel()).getDataMapper().getCache(); CacheEntry prevEntry = null; for (CacheEntry entry : cache) { boolean currentLineStartsWithSoftWrap = checkRelationBetweenNeighbourEntries(entry, prevEntry, softWrapOffsets); checkConsistencyWithinEntry(entry, currentLineStartsWithSoftWrap); - checkConsistencyWithFoldingsAndTabs(entry); + checkConsistencyWithFoldingsAndTabs(editor, entry); prevEntry = entry; } assertTrue(softWrapOffsets.isEmpty()); } - private static void checkConsistencyWithFoldingsAndTabs(CacheEntry entry) { + private static void checkConsistencyWithFoldingsAndTabs(Editor editor, CacheEntry entry) { Map actualFoldRegions = new HashMap<>(); List actualTabPositions = new ArrayList<>(); for (int i = entry.startOffset; i < entry.endOffset; i++) { - FoldRegion region = myEditor.getFoldingModel().getCollapsedRegionAtOffset(i); + FoldRegion region = editor.getFoldingModel().getCollapsedRegionAtOffset(i); if (region == null) { - if (myEditor.getDocument().getCharsSequence().charAt(i) == '\t') { + if (editor.getDocument().getCharsSequence().charAt(i) == '\t') { actualTabPositions.add(i); } } @@ -182,8 +156,8 @@ public class SoftWrapStressTest extends AbstractEditorTest { } @NotNull - private static Set checkSoftWraps() { - List softWraps = myEditor.getSoftWrapModel().getSoftWrapsForRange(0, myEditor.getDocument().getTextLength()); + private static Set checkSoftWraps(Editor editor) { + List softWraps = editor.getSoftWrapModel().getSoftWrapsForRange(0, editor.getDocument().getTextLength()); Set softWrapOffsets = new HashSet<>(); int lastOffset = -1; for (SoftWrap softWrap : softWraps) { @@ -194,97 +168,4 @@ public class SoftWrapStressTest extends AbstractEditorTest { } return softWrapOffsets; } - - interface Action { - void perform(Editor editor, Random random); - } - - private static class AddText implements Action { - private final String myText; - - AddText(String text) { - myText = text; - } - - @Override - public void perform(Editor editor, Random random) { - Document document = editor.getDocument(); - int offset = random.nextInt(document.getTextLength() + 1); - document.insertString(offset, myText); - } - } - - private static class RemoveCharacter implements Action { - @Override - public void perform(Editor editor, Random random) { - Document document = editor.getDocument(); - int textLength = document.getTextLength(); - if (textLength <= 0) return; - int offset = random.nextInt(textLength); - document.deleteString(offset, offset + 1); - } - } - - private static class MoveCharacter implements Action { - @Override - public void perform(Editor editor, Random random) { - Document document = editor.getDocument(); - int textLength = document.getTextLength(); - if (textLength <= 0) return; - int offset = random.nextInt(textLength); - int targetOffset = random.nextInt(textLength + 1); - if (targetOffset < offset || targetOffset > offset + 1) { - ((DocumentEx)document).moveText(offset, offset + 1, targetOffset); - } - } - } - - private static class AddFoldRegion implements Action { - @Override - public void perform(final Editor editor, Random random) { - Document document = editor.getDocument(); - int textLength = document.getTextLength(); - if (textLength <= 0) return; - final int startOffset = random.nextInt(textLength + 1); - final int endOffset = random.nextInt(textLength + 1); - if (startOffset == endOffset) return; - final FoldingModel foldingModel = editor.getFoldingModel(); - foldingModel.runBatchFoldingOperation(() -> foldingModel.addFoldRegion(Math.min(startOffset, endOffset), - Math.max(startOffset, endOffset), - ".")); - } - } - - private static class RemoveFoldRegion implements Action { - @Override - public void perform(final Editor editor, Random random) { - final FoldingModel foldingModel = editor.getFoldingModel(); - FoldRegion[] foldRegions = foldingModel.getAllFoldRegions(); - if (foldRegions.length == 0) return; - final FoldRegion region = foldRegions[random.nextInt(foldRegions.length)]; - foldingModel.runBatchFoldingOperation(() -> foldingModel.removeFoldRegion(region)); - } - } - - private static class CollapseFoldRegion implements Action { - @Override - public void perform(final Editor editor, Random random) { - final FoldingModel foldingModel = editor.getFoldingModel(); - FoldRegion[] foldRegions = foldingModel.getAllFoldRegions(); - if (foldRegions.length == 0) return; - final FoldRegion region = foldRegions[random.nextInt(foldRegions.length)]; - foldingModel.runBatchFoldingOperation(() -> region.setExpanded(false)); - } - } - - private static class ExpandFoldRegion implements Action { - @Override - public void perform(final Editor editor, Random random) { - final FoldingModel foldingModel = editor.getFoldingModel(); - FoldRegion[] foldRegions = foldingModel.getAllFoldRegions(); - if (foldRegions.length == 0) return; - final FoldRegion region = foldRegions[random.nextInt(foldRegions.length)]; - foldingModel.runBatchFoldingOperation(() -> region.setExpanded(true)); - } - } } From 25d74560fff1c7f78c03d43268e9ce0ab2bc9325 Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Thu, 5 Nov 2015 21:50:27 +0300 Subject: [PATCH 006/124] don't use legacy code with editor.new.rendering --- .../intellij/openapi/editor/impl/SoftWrapModelImpl.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java index 9718e1a2151c..690f11a41e72 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java @@ -627,7 +627,12 @@ public class SoftWrapModelImpl implements SoftWrapModelEx, PrioritizedInternalDo if (!isSoftWrappingEnabled()) { return; } - executeSafely(myFoldProcessingEndTask); + if (myEditor.myUseNewRendering) { + myFoldProcessingEndTask.run(true); + } + else { + executeSafely(myFoldProcessingEndTask); + } } @Override From ac5f1e43b1fbbc9669f3b6448137441defd0d145 Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Thu, 5 Nov 2015 21:51:17 +0300 Subject: [PATCH 007/124] make sure seed and iteration are always logged, even if thrown exception is discarded upper in the call stack --- .../com/intellij/openapi/editor/impl/EditorStressTest.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/EditorStressTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/EditorStressTest.java index 48ce8895a33d..9cd6b7d0e6dd 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/EditorStressTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/EditorStressTest.java @@ -56,7 +56,9 @@ public class EditorStressTest extends AbstractEditorTest { } } catch (Throwable t) { - throw new RuntimeException("Failed when run with seed=" + mySeed + " in iteration " + i, t); + String message = "Failed when run with seed=" + mySeed + " in iteration " + i; + System.out.println(message); + throw new RuntimeException(message, t); } } From 01d5262bbf4ff026991aae57c7759c8616c7a82e Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Fri, 6 Nov 2015 11:24:36 +0300 Subject: [PATCH 008/124] don't invoke coordinate transformation functions while soft wrap model is in inconsistent state --- .../mapping/IncrementalCacheUpdateEvent.java | 67 ++++++++++++++----- .../mapping/SoftWrapApplianceManager.java | 3 +- .../openapi/editor/impl/EditorImplTest.java | 7 ++ 3 files changed, 60 insertions(+), 17 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/IncrementalCacheUpdateEvent.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/IncrementalCacheUpdateEvent.java index b59f48627323..1e638c951a54 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/IncrementalCacheUpdateEvent.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/IncrementalCacheUpdateEvent.java @@ -16,11 +16,11 @@ package com.intellij.openapi.editor.impl.softwrap.mapping; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.editor.Document; -import com.intellij.openapi.editor.LogicalPosition; -import com.intellij.openapi.editor.VisualPosition; +import com.intellij.openapi.editor.*; import com.intellij.openapi.editor.event.DocumentEvent; +import com.intellij.openapi.editor.ex.util.EditorUtil; import com.intellij.openapi.editor.impl.EditorImpl; +import com.intellij.openapi.editor.impl.SoftWrapModelImpl; import org.jetbrains.annotations.NotNull; /** @@ -55,15 +55,15 @@ public class IncrementalCacheUpdateEvent { * @param event object that describes document change that caused cache update */ IncrementalCacheUpdateEvent(@NotNull DocumentEvent event, @NotNull CachingSoftWrapDataMapper mapper, @NotNull EditorImpl editor) { - this(event.getDocument(), event.getOffset(), event.getOffset() + event.getOldLength(), event.getOffset() + event.getNewLength(), mapper, editor); + this(event.getOffset(), event.getOffset() + event.getOldLength(), event.getOffset() + event.getNewLength(), mapper, editor); } /** * Creates new IncrementalCacheUpdateEvent object for the event not changing document length * (like expansion of folded region). */ - IncrementalCacheUpdateEvent(@NotNull Document document, int startOffset, int endOffset, @NotNull CachingSoftWrapDataMapper mapper, @NotNull EditorImpl editor) { - this(document, startOffset, endOffset, endOffset, mapper, editor); + IncrementalCacheUpdateEvent(int startOffset, int endOffset, @NotNull CachingSoftWrapDataMapper mapper, @NotNull EditorImpl editor) { + this(startOffset, endOffset, endOffset, mapper, editor); myNewEndLogicalLine = myOldEndLogicalLine; } @@ -82,22 +82,59 @@ public class IncrementalCacheUpdateEvent { myOldEndLogicalLine = myNewEndLogicalLine = Math.max(0, document.getLineCount() - 1); } - private IncrementalCacheUpdateEvent(@NotNull Document document, int startOffset, int oldEndOffset, int newEndOffset, + private IncrementalCacheUpdateEvent(int startOffset, int oldEndOffset, int newEndOffset, @NotNull CachingSoftWrapDataMapper mapper, @NotNull EditorImpl editor) { - myStartOffset = editor.myUseNewRendering ? editor.visualLineStartOffset(editor.offsetToVisualLine(startOffset) - 1) : - mapper.getPreviousVisualLineStartOffset(startOffset); - myMandatoryEndOffset = newEndOffset; - myLengthDiff = newEndOffset - oldEndOffset; - myStartLogicalPosition = editor.myUseNewRendering ? editor.offsetToLogicalPosition(myStartOffset) : - mapper.offsetToLogicalPosition(myStartOffset); if (editor.myUseNewRendering) { - myStartVisualPosition = editor.logicalToVisualPosition(myStartLogicalPosition); + VisualLineInfo info = getVisualLineInfo(editor, startOffset, false); + if (info.startsWithSoftWrap) { + info = getVisualLineInfo(editor, info.startOffset, true); + } + myStartOffset = info.startOffset; + myStartLogicalPosition = editor.offsetToLogicalPosition(myStartOffset); + myStartVisualPosition = new VisualPosition(info.visualLine, 0); } else { + myStartOffset = mapper.getPreviousVisualLineStartOffset(startOffset); + myStartLogicalPosition = mapper.offsetToLogicalPosition(myStartOffset); LOG.assertTrue(myStartLogicalPosition.visualPositionAware); myStartVisualPosition = myStartLogicalPosition.toVisualPosition(); } - myOldEndLogicalLine = document.getLineNumber(oldEndOffset); + myMandatoryEndOffset = newEndOffset; + myLengthDiff = newEndOffset - oldEndOffset; + myOldEndLogicalLine = editor.getDocument().getLineNumber(oldEndOffset); + } + + + private static VisualLineInfo getVisualLineInfo(@NotNull EditorImpl editor, int offset, boolean beforeSoftWrap) { + Document document = editor.getDocument(); + int textLength = document.getTextLength(); + if (offset <= 0 || textLength == 0) return new VisualLineInfo(0, 0, false); + offset = Math.min(offset, textLength); + + int startOffset = EditorUtil.getNotFoldedLineStartOffset(editor, offset); + + SoftWrapModelImpl softWrapModel = editor.getSoftWrapModel(); + int wrapIndex = softWrapModel.getSoftWrapIndex(offset); + int prevSoftWrapIndex = wrapIndex < 0 ? (- wrapIndex - 2) : wrapIndex - (beforeSoftWrap ? 1 : 0); + SoftWrap prevSoftWrap = prevSoftWrapIndex < 0 ? null : softWrapModel.getRegisteredSoftWraps().get(prevSoftWrapIndex); + + int visualLine = document.getLineNumber(offset) - editor.getFoldingModel().getFoldedLinesCountBefore(offset) + (prevSoftWrapIndex + 1); + int visualLineStartOffset = prevSoftWrap == null ? startOffset : Math.max(startOffset, prevSoftWrap.getStart()); + return new VisualLineInfo(visualLine, + visualLineStartOffset, + prevSoftWrap != null && prevSoftWrap.getStart() == visualLineStartOffset); + } + + private static class VisualLineInfo { + private final int visualLine; + private final int startOffset; + private final boolean startsWithSoftWrap; + + private VisualLineInfo(int visualLine, int startOffset, boolean wrap) { + this.visualLine = visualLine; + this.startOffset = startOffset; + startsWithSoftWrap = wrap; + } } public void updateAfterDocumentChange(@NotNull Document document) { diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java index 3cfb4c336b19..cc48ab689852 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java @@ -193,8 +193,7 @@ public class SoftWrapApplianceManager implements Dumpable { for (Segment range : ranges) { int lastOffset = lastRecalculatedOffset[0]; if (range.getEndOffset() > lastOffset) { - recalculateSoftWraps(new IncrementalCacheUpdateEvent(myEditor.getDocument(), - Math.max(range.getStartOffset(), lastOffset), range.getEndOffset(), + recalculateSoftWraps(new IncrementalCacheUpdateEvent(Math.max(range.getStartOffset(), lastOffset), range.getEndOffset(), myDataMapper, myEditor)); } } diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/EditorImplTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/EditorImplTest.java index ebc3a285bc2a..9b1fc12e031f 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/EditorImplTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/EditorImplTest.java @@ -199,4 +199,11 @@ public class EditorImplTest extends AbstractEditorTest { myEditor.getSettings().setAdditionalLinesCount(0); assertEquals(new Dimension(50, 30), myEditor.getContentComponent().getPreferredSize()); } + + public void testCollapsingRegionContainingSoftWrap() throws Exception { + initText("abcdef abcdef"); + configureSoftWraps(10); + addCollapsedFoldRegion(0, 13, "..."); + assertEquals(new VisualPosition(0, 3), myEditor.offsetToVisualPosition(13)); + } } From 98968ef32ffc1495cd173296951480bbc7f957ac Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Fri, 6 Nov 2015 11:27:06 +0300 Subject: [PATCH 009/124] cleanup --- .../impl/softwrap/mapping/SoftWrapApplianceManager.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java index cc48ab689852..49d7b9b1db0d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java @@ -239,8 +239,7 @@ public class SoftWrapApplianceManager implements Dumpable { LOG.error("Soft wrapping is not supported for documents with non-standard line endings. File: " + myEditor.getVirtualFile()); } if (myInProgress) { - LogMessageEx.error(LOG, "Detected race condition at soft wraps recalculation", - (myEditor instanceof EditorImpl) ? ((EditorImpl)myEditor).dumpState() : "", event.toString()); + LogMessageEx.error(LOG, "Detected race condition at soft wraps recalculation", myEditor.dumpState(), event.toString()); } myInProgress = true; try { @@ -458,10 +457,9 @@ public class SoftWrapApplianceManager implements Dumpable { int startOffset = myContext.currentPosition.offset; while (myContext.currentPosition.offset < myContext.tokenEndOffset) { if (counter++ > limit) { - String editorInfo = myEditor instanceof EditorImpl ? ((EditorImpl)myEditor).dumpState() : myEditor.getClass().toString(); LogMessageEx.error(LOG, "Cycled soft wraps recalculation detected", String.format( "Start recalculation offset: %d, visible area width: %d, calculation context: %s, editor info: %s", - startOffset, myVisibleAreaWidth, myContext, editorInfo)); + startOffset, myVisibleAreaWidth, myContext, myEditor.dumpState())); for (int i = myContext.currentPosition.offset; i < myContext.tokenEndOffset; i++) { char c = myContext.text.charAt(i); if (c == '\n') { From e1046a95e85f841e09a1cbaaad693cbc80851bee Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Fri, 6 Nov 2015 11:31:26 +0300 Subject: [PATCH 010/124] fix project leak via parsable --- .../plugins/relaxNG/validation/RngParser.java | 26 +++++-------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/xml/relaxng/src/org/intellij/plugins/relaxNG/validation/RngParser.java b/xml/relaxng/src/org/intellij/plugins/relaxNG/validation/RngParser.java index b7a8492df582..38fd5ee0ecc1 100644 --- a/xml/relaxng/src/org/intellij/plugins/relaxNG/validation/RngParser.java +++ b/xml/relaxng/src/org/intellij/plugins/relaxNG/validation/RngParser.java @@ -16,14 +16,13 @@ package org.intellij.plugins.relaxNG.validation; +import com.intellij.javaee.UriUtil; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.editor.Document; import com.intellij.openapi.util.AtomicNotNullLazyValue; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.NotNullLazyValue; import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; import com.intellij.psi.search.PsiElementProcessor; import com.intellij.psi.util.CachedValue; @@ -31,7 +30,6 @@ import com.intellij.psi.util.CachedValueProvider; import com.intellij.psi.util.CachedValuesManager; import com.intellij.psi.xml.XmlFile; import com.intellij.util.containers.ContainerUtil; -import com.intellij.xml.util.XmlUtil; import com.thaiopensource.datatype.xsd.DatatypeLibraryFactoryImpl; import com.thaiopensource.relaxng.impl.SchemaReaderImpl; import com.thaiopensource.util.PropertyMap; @@ -160,6 +158,7 @@ public class RngParser { private static Parseable createParsable(final PsiFile file, final ErrorHandler eh) { final InputSource source = makeInputSource(file); + final VirtualFile virtualFile = file.getVirtualFile(); if (file.getFileType() == RncFileType.getInstance()) { return new CompactParseable(source, eh) { @@ -167,7 +166,7 @@ public class RngParser { public ParsedPattern parseInclude(String uri, SchemaBuilder schemaBuilder, IncludedGrammar g, String inheritedNs) throws BuildException, IllegalSchemaException { - return super.parseInclude(resolveURI(file, uri), schemaBuilder, g, inheritedNs); + return super.parseInclude(resolveURI(virtualFile, uri), schemaBuilder, g, inheritedNs); } }; } else { @@ -176,27 +175,16 @@ public class RngParser { public ParsedPattern parseInclude(String uri, SchemaBuilder schemaBuilder, IncludedGrammar g, String inheritedNs) throws BuildException, IllegalSchemaException { - return super.parseInclude(resolveURI(file, uri), schemaBuilder, g, inheritedNs); + return super.parseInclude(resolveURI(virtualFile, uri), schemaBuilder, g, inheritedNs); } }; } } - public static String resolveURI(PsiFile descriptorFile, String s) { - final PsiFile file = XmlUtil.findXmlFile(descriptorFile, s); - + private static String resolveURI(VirtualFile descriptorFile, String s) { + final VirtualFile file = UriUtil.findRelativeFile(s, descriptorFile); if (file != null) { - final VirtualFile virtualFile = file.getVirtualFile(); - if (virtualFile != null) { - final PsiDocumentManager dm = PsiDocumentManager.getInstance(file.getProject()); - final Document d = dm.getCachedDocument(file); - if (d != null) { - // TODO: fix. write action + saving -> deadlock -// dm.commitDocument(d); -// FileDocumentManager.getInstance().saveDocument(d); - } - s = VfsUtilCore.fixIDEAUrl(virtualFile.getUrl()); - } + s = VfsUtilCore.fixIDEAUrl(file.getUrl()); } return s; } From a7b28ab90179bf2e403801ee1cca2a28ff4f8cc9 Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Thu, 5 Nov 2015 22:12:52 +0300 Subject: [PATCH 011/124] Do not run indent detector in any way in viewer mode --- .../FileIndentOptionsProviderTest.kt | 62 +++++++++++++++++++ .../openapi/editor/impl/SettingsImpl.java | 8 ++- 2 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 java/java-tests/testSrc/com/intellij/psi/codeStyle/autodetect/FileIndentOptionsProviderTest.kt diff --git a/java/java-tests/testSrc/com/intellij/psi/codeStyle/autodetect/FileIndentOptionsProviderTest.kt b/java/java-tests/testSrc/com/intellij/psi/codeStyle/autodetect/FileIndentOptionsProviderTest.kt new file mode 100644 index 000000000000..973f3c494c35 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/psi/codeStyle/autodetect/FileIndentOptionsProviderTest.kt @@ -0,0 +1,62 @@ +/* + * 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 com.intellij.psi.codeStyle.autodetect + +import com.intellij.openapi.editor.EditorFactory +import com.intellij.openapi.editor.impl.EditorImpl +import com.intellij.openapi.extensions.ExtensionPoint +import com.intellij.openapi.extensions.Extensions +import com.intellij.openapi.extensions.LoadingOrder +import com.intellij.psi.PsiDocumentManager +import com.intellij.psi.codeStyle.FileIndentOptionsProvider +import com.intellij.testFramework.LightPlatformTestCase +import org.junit.Test +import org.mockito.Matchers +import org.mockito.Mockito.* + +class ViewerEditorTest: LightPlatformTestCase() { + lateinit var mockProvider: FileIndentOptionsProvider + lateinit var extensionPoint: ExtensionPoint + + override fun setUp() { + super.setUp() + extensionPoint = Extensions.getRootArea().getExtensionPoint(FileIndentOptionsProvider.EP_NAME) + mockProvider = mock(FileIndentOptionsProvider::class.java) + extensionPoint.registerExtension(mockProvider, LoadingOrder.FIRST) + } + + override fun tearDown() { + extensionPoint.unregisterExtension(mockProvider) + super.tearDown() + } + + @Test + fun `test do not use file indent option providers for viewer editors`() { + val file = createFile("Test.java", "class Test {}") + val document = PsiDocumentManager.getInstance(getProject()).getDocument(file) + val editor = EditorFactory.getInstance().createEditor(document!!, getProject(), file.virtualFile, true); + try { + (editor as EditorImpl).reinitSettings() + editor.settings.isLineNumbersShown = true + editor.settings.getTabSize(getProject()) + } + finally { + EditorFactory.getInstance().releaseEditor(editor) + } + verify(mockProvider, never()).getIndentOptions(Matchers.any(), Matchers.any()) + } + +} \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SettingsImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SettingsImpl.java index c675d490f072..3a98896d4bf4 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SettingsImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SettingsImpl.java @@ -32,6 +32,7 @@ import com.intellij.openapi.editor.ex.DocumentEx; import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.editor.ex.EditorSettingsExternalizable; import com.intellij.openapi.editor.impl.softwrap.SoftWrapAppliancePlaces; +import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.registry.Registry; import com.intellij.psi.PsiDocumentManager; @@ -355,7 +356,12 @@ public class SettingsImpl implements EditorSettings { } else { PsiFile file = getPsiFile(project); - tabSize = CodeStyleSettingsManager.getSettings(project).getIndentOptionsByFile(file).TAB_SIZE; + if (myEditor != null && myEditor.isViewer()) { + FileType fileType = file != null ? file.getFileType() : null; + tabSize = CodeStyleSettingsManager.getSettings(project).getIndentOptions(fileType).TAB_SIZE; + } else { + tabSize = CodeStyleSettingsManager.getSettings(project).getIndentOptionsByFile(file).TAB_SIZE; + } } myCachedTabSize = Integer.valueOf(tabSize); return tabSize; From 84d9b0e5a6a75ff254036180f3cce133e1454e35 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Fri, 6 Nov 2015 12:11:21 +0300 Subject: [PATCH 012/124] check for cyclic Disposable registrations for IDEA-147098 --- .../testFramework/UsefulTestCase.java | 8 ++- .../com/intellij/openapi/util/Disposer.java | 7 ++- .../openapi/util/objectTree/ObjectNode.java | 10 ++-- .../openapi/util/objectTree/ObjectTree.java | 50 +++++++------------ .../openapi/util/objectTree/DisposerTest.java | 44 ++++++++++++++-- 5 files changed, 76 insertions(+), 43 deletions(-) diff --git a/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java b/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java index 0cbe7c600eee..3d5a24c1f03f 100644 --- a/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java +++ b/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java @@ -127,6 +127,8 @@ public abstract class UsefulTestCase extends TestCase { } } + private boolean oldDisposerDebug; + protected boolean shouldContainTempFiles() { return true; } @@ -142,11 +144,15 @@ public abstract class UsefulTestCase extends TestCase { myTempDir = new File(ORIGINAL_TEMP_DIR, TEMP_DIR_MARKER + testName).getPath(); FileUtil.resetCanonicalTempPathCache(myTempDir); } - ApplicationInfoImpl.setInPerformanceTest(isPerformanceTest()); + boolean isPerformanceTest = isPerformanceTest(); + ApplicationInfoImpl.setInPerformanceTest(isPerformanceTest); + // turn off Disposer debugging for performance tests + oldDisposerDebug = Disposer.setDebugMode(Disposer.isDebugMode() && !isPerformanceTest); } @Override protected void tearDown() throws Exception { + Disposer.setDebugMode(oldDisposerDebug); try { Disposer.dispose(myTestRootDisposable); cleanupSwingDataStructures(); diff --git a/platform/util/src/com/intellij/openapi/util/Disposer.java b/platform/util/src/com/intellij/openapi/util/Disposer.java index 6307017967ac..4d597880f38d 100644 --- a/platform/util/src/com/intellij/openapi/util/Disposer.java +++ b/platform/util/src/com/intellij/openapi/util/Disposer.java @@ -23,6 +23,7 @@ import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.TestOnly; import java.lang.reflect.Field; import java.lang.reflect.Modifier; @@ -126,12 +127,16 @@ public class Disposer { } } + @TestOnly public static boolean isEmpty() { return ourDebugMode && ourTree.isEmpty(); } - public static void setDebugMode(final boolean debugMode) { + // returns old value + public static boolean setDebugMode(final boolean debugMode) { + boolean oldValue = ourDebugMode; ourDebugMode = debugMode; + return oldValue; } public static boolean isDebugMode() { diff --git a/platform/util/src/com/intellij/openapi/util/objectTree/ObjectNode.java b/platform/util/src/com/intellij/openapi/util/objectTree/ObjectNode.java index 5ce40516f200..4f356c6d8801 100644 --- a/platform/util/src/com/intellij/openapi/util/objectTree/ObjectNode.java +++ b/platform/util/src/com/intellij/openapi/util/objectTree/ObjectNode.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * 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. @@ -18,6 +18,7 @@ package com.intellij.openapi.util.objectTree; import com.intellij.openapi.Disposable; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProcessCanceledException; +import com.intellij.openapi.util.Disposer; import com.intellij.util.SmartList; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -46,13 +47,12 @@ final class ObjectNode { ObjectNode(@NotNull ObjectTree tree, @Nullable ObjectNode parentNode, @NotNull T object, - long modification, - @Nullable final Throwable trace) { + long modification) { myTree = tree; myParent = parentNode; myObject = object; - myTrace = trace; + myTrace = Disposer.isDebugMode() ? new Throwable() : null; myOwnModification = modification; } @@ -171,7 +171,7 @@ final class ObjectNode { @Override @NonNls public String toString() { - return "Node: " + myObject.toString(); + return "Node: " + myObject; } Throwable getTrace() { diff --git a/platform/util/src/com/intellij/openapi/util/objectTree/ObjectTree.java b/platform/util/src/com/intellij/openapi/util/objectTree/ObjectTree.java index 11212543a1d2..6340aafb237a 100644 --- a/platform/util/src/com/intellij/openapi/util/objectTree/ObjectTree.java +++ b/platform/util/src/com/intellij/openapi/util/objectTree/ObjectTree.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * 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. @@ -17,10 +17,9 @@ package com.intellij.openapi.util.objectTree; import com.intellij.openapi.Disposable; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.util.Disposer; import com.intellij.util.ArrayUtil; +import com.intellij.util.IncorrectOperationException; import com.intellij.util.containers.ContainerUtil; -import gnu.trove.Equality; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.TestOnly; @@ -59,11 +58,12 @@ public final class ObjectTree { public final void register(@NotNull T parent, @NotNull T child) { synchronized (treeLock) { - ObjectNode parentNode = getOrCreateNodeFor(parent, null); + ObjectNode parentNode = getNode(parent); + if (parentNode == null) parentNode = createNodeFor(parent, null); ObjectNode childNode = getNode(child); if (childNode == null) { - childNode = createNodeFor(child, parentNode, Disposer.isDebugMode() ? new Throwable() : null); + childNode = createNodeFor(child, parentNode); } else { ObjectNode oldParent = childNode.getParent(); @@ -72,38 +72,26 @@ public final class ObjectTree { } } myRootObjects.remove(child); - checkWasNotAddedAlready(childNode, child); + + checkWasNotAddedAlready(parentNode, childNode); + parentNode.addChild(childNode); fireRegistered(childNode.getObject()); } } - private void checkWasNotAddedAlready(@NotNull ObjectNode childNode, @NotNull T child) { - ObjectNode parent = childNode.getParent(); - boolean childIsInTree = parent != null; - if (!childIsInTree) return; - - while (parent != null) { - if (parent.getObject() == child) { - LOG.error(child + " was already added as a child of: " + parent); + private void checkWasNotAddedAlready(ObjectNode childNode, @NotNull ObjectNode parentNode) { + for (ObjectNode node = childNode; node != null; node = node.getParent()) { + if (node == parentNode) { + throw new IncorrectOperationException("'"+childNode.getObject() + "' was already added as a child of '" + parentNode.getObject()+"'"); } - parent = parent.getParent(); } } @NotNull - private ObjectNode getOrCreateNodeFor(@NotNull T object, @Nullable ObjectNode defaultParent) { - final ObjectNode node = getNode(object); - - if (node != null) return node; - - return createNodeFor(object, defaultParent, Disposer.isDebugMode() ? new Throwable() : null); - } - - @NotNull - private ObjectNode createNodeFor(@NotNull T object, @Nullable ObjectNode parentNode, @Nullable final Throwable trace) { - final ObjectNode newNode = new ObjectNode(this, parentNode, object, getNextModification(), trace); + private ObjectNode createNodeFor(@NotNull T object, @Nullable ObjectNode parentNode) { + final ObjectNode newNode = new ObjectNode(this, parentNode, object, getNextModification()); if (parentNode == null) { myRootObjects.add(object); } @@ -125,9 +113,7 @@ public final class ObjectTree { executeUnregistered(object, action); return true; } - else { - return false; - } + return false; } node.execute(disposeTree, action); return true; @@ -138,7 +124,7 @@ public final class ObjectTree { @NotNull List recursiveGuard, @NotNull final ObjectTreeAction action) { synchronized (recursiveGuard) { - if (ArrayUtil.indexOf(recursiveGuard, object, Equality.IDENTITY) != -1) return; + if (ArrayUtil.indexOf(recursiveGuard, object, ContainerUtil.identityStrategy()) != -1) return; recursiveGuard.add(object); } @@ -147,7 +133,7 @@ public final class ObjectTree { } finally { synchronized (recursiveGuard) { - int i = ArrayUtil.lastIndexOf(recursiveGuard, object, Equality.IDENTITY); + int i = ArrayUtil.lastIndexOf(recursiveGuard, object, ContainerUtil.identityStrategy()); assert i != -1; recursiveGuard.remove(i); } @@ -216,7 +202,7 @@ public final class ObjectTree { } } } - + @TestOnly public boolean isEmpty() { synchronized (treeLock) { diff --git a/platform/util/testSrc/com/intellij/openapi/util/objectTree/DisposerTest.java b/platform/util/testSrc/com/intellij/openapi/util/objectTree/DisposerTest.java index ce4132496aea..84aeea82e008 100644 --- a/platform/util/testSrc/com/intellij/openapi/util/objectTree/DisposerTest.java +++ b/platform/util/testSrc/com/intellij/openapi/util/objectTree/DisposerTest.java @@ -17,6 +17,7 @@ package com.intellij.openapi.util.objectTree; import com.intellij.openapi.Disposable; import com.intellij.openapi.util.Disposer; +import com.intellij.util.IncorrectOperationException; import junit.framework.TestCase; import org.jetbrains.annotations.NonNls; @@ -216,11 +217,10 @@ public class DisposerTest extends TestCase { } private class MyDisposable implements Disposable { - - private boolean myDisposed = false; + private boolean myDisposed; protected String myName; - public MyDisposable(@NonNls String aName) { + MyDisposable(@NonNls String aName) { myName = aName; } @@ -252,7 +252,7 @@ public class DisposerTest extends TestCase { } private class SelDisposable extends MyDisposable { - public SelDisposable(@NonNls String aName) { + private SelDisposable(@NonNls String aName) { super(aName); } @@ -276,4 +276,40 @@ public class DisposerTest extends TestCase { return result.toString(); } + + public void testIncest() { + Disposable parent = newDisposable("parent"); + Disposable child = newDisposable("child"); + Disposer.register(parent, child); + + Disposable grand = newDisposable("grand"); + Disposer.register(child, grand); + + try { + Disposer.register(grand, parent); + fail("must not allow"); + } + catch (IncorrectOperationException e) { + assertEquals("'grand' was already added as a child of 'parent'", e.getMessage()); + } + finally { + Disposer.dispose(grand); + Disposer.dispose(child); + Disposer.dispose(parent); + } + } + + private static Disposable newDisposable(final String name) { + return new Disposable() { + @Override + public void dispose() { + + } + + @Override + public String toString() { + return name; + } + }; + } } From 6ac9b9d08c5a986e98fd611107c25f3cdb3712ed Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Fri, 6 Nov 2015 12:46:48 +0300 Subject: [PATCH 013/124] guava inspection description is rewritten (IDEA-147473) (IDEA-147460) --- resources-en/src/inspectionDescriptions/Guava.html | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/resources-en/src/inspectionDescriptions/Guava.html b/resources-en/src/inspectionDescriptions/Guava.html index 2e21dbe99177..8f3a5e3fe614 100644 --- a/resources-en/src/inspectionDescriptions/Guava.html +++ b/resources-en/src/inspectionDescriptions/Guava.html @@ -1,6 +1,11 @@ Inspection detects usages of Guava's functional primitives like -c.g.c.c.FluentIterable, c.g.c.b.Optional, c.g.c.b.Function and c.g.c.b.Supplier. +FluentIterable, Optional, Function, Predicate and Supplier. +
+
+This inspection only reports if the project +or module is configured to use a language level +of 8 or higher. \ No newline at end of file From 51a519f96a3bf3354ac462db683f6b8f61ffd114 Mon Sep 17 00:00:00 2001 From: Konstantin Ulitin Date: Fri, 6 Nov 2015 12:45:33 +0300 Subject: [PATCH 014/124] use proper element type for building stubs in LightStubBuilder --- .../src/com/intellij/psi/stubs/LightStubBuilder.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/platform/core-impl/src/com/intellij/psi/stubs/LightStubBuilder.java b/platform/core-impl/src/com/intellij/psi/stubs/LightStubBuilder.java index 5571f2137243..bf95e89dde34 100644 --- a/platform/core-impl/src/com/intellij/psi/stubs/LightStubBuilder.java +++ b/platform/core-impl/src/com/intellij/psi/stubs/LightStubBuilder.java @@ -22,10 +22,10 @@ import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.fileTypes.LanguageFileType; import com.intellij.psi.PsiFile; import com.intellij.psi.StubBuilder; +import com.intellij.psi.impl.source.PsiFileImpl; import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.IFileElementType; import com.intellij.psi.tree.ILightStubFileElementType; -import com.intellij.psi.tree.IStubFileElementType; import com.intellij.util.containers.Stack; import gnu.trove.TIntStack; import org.jetbrains.annotations.NotNull; @@ -45,10 +45,10 @@ public class LightStubBuilder implements StubBuilder { LOG.error("File is not of LanguageFileType: " + fileType + ", " + file); return null; } - Language language = ((LanguageFileType)fileType).getLanguage(); - final IFileElementType contentType = LanguageParserDefinitions.INSTANCE.forLanguage(language).getFileNodeType(); - if (!(contentType instanceof IStubFileElementType)) { - LOG.error("File is not of IStubFileElementType: " + contentType + ", " + file); + assert file instanceof PsiFileImpl; + final IFileElementType contentType = ((PsiFileImpl)file).getElementTypeForStubBuilder(); + if (contentType == null) { + LOG.error("File is not of IStubFileElementType: " + file); return null; } From 1e3d48c1788163851b97a8e886f70e9e6b360ed5 Mon Sep 17 00:00:00 2001 From: "Vladislav.Soroka" Date: Fri, 6 Nov 2015 12:51:53 +0300 Subject: [PATCH 015/124] maven: fix blinking test --- .../idea/maven/MavenImportingTestCase.java | 2 +- .../MavenProjectModelModifierTest.java | 23 +++++++++++-------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenImportingTestCase.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenImportingTestCase.java index bd55bb31b4d7..ba658b2e27a3 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenImportingTestCase.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenImportingTestCase.java @@ -371,7 +371,7 @@ public abstract class MavenImportingTestCase extends MavenTestCase { return getRootManager(moduleName).getContentEntries(); } - private ModuleRootManager getRootManager(String module) { + public ModuleRootManager getRootManager(String module) { return ModuleRootManager.getInstance(getModule(module)); } diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/actions/MavenProjectModelModifierTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/actions/MavenProjectModelModifierTest.java index 2822493cb873..e55fb286c73d 100644 --- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/actions/MavenProjectModelModifierTest.java +++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/actions/MavenProjectModelModifierTest.java @@ -17,9 +17,7 @@ package org.jetbrains.idea.maven.actions; import com.intellij.openapi.module.EffectiveLanguageLevelUtil; import com.intellij.openapi.module.Module; -import com.intellij.openapi.roots.DependencyScope; -import com.intellij.openapi.roots.ExternalLibraryDescriptor; -import com.intellij.openapi.roots.JavaProjectModelModifier; +import com.intellij.openapi.roots.*; import com.intellij.openapi.roots.libraries.Library; import com.intellij.openapi.roots.libraries.LibraryTablesRegistrar; import com.intellij.openapi.vfs.VirtualFile; @@ -44,8 +42,8 @@ import java.util.regex.Pattern; public class MavenProjectModelModifierTest extends MavenDomWithIndicesTestCase { public void testAddExternalLibraryDependency() throws IOException { importProject("test" + - "project" + - "1"); + "project" + + "1"); Promise result = getExtension().addExternalLibraryDependency(Collections.singletonList(getModule("project")), new JunitLibraryDescriptor(), @@ -98,14 +96,21 @@ public class MavenProjectModelModifierTest extends MavenDomWithIndicesTestCase { "project" + "1"); - Promise result = - getExtension().addExternalLibraryDependency(Collections.singletonList(getModule("project")), new CommonsIoLibraryDescriptorUnknownVersion(), - DependencyScope.COMPILE); + Promise result = getExtension().addExternalLibraryDependency( + Collections.singletonList(getModule("project")), new CommonsIoLibraryDescriptorUnknownVersion(), DependencyScope.COMPILE); assertNotNull(result); final String version = assertHasDependency(myProjectPom, "commons-io", "commons-io"); assertEquals("RELEASE", version); waitUntilImported(result); - assertModuleLibDep("project", "Maven: commons-io:commons-io:2.4"); + + LibraryOrderEntry dep = null; + for (OrderEntry e : getRootManager("project").getOrderEntries()) { + // can be commons-io:commons-io:2.4 or commons-io:commons-io:RELEASE + if (LibraryOrderEntry.class.isInstance(e) && e.getPresentableName().startsWith("Maven: commons-io:commons-io:")) { + dep = (LibraryOrderEntry)e; + } + } + assertNotNull(dep); } public void testAddModuleDependency() throws IOException { From caab8e580790f551e2f570b816aef2e488722654 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Fri, 6 Nov 2015 12:09:07 +0300 Subject: [PATCH 016/124] IDEA-143572 Android: IAE at com.android.tools.idea.gradle.parser.GradleGroovyFile.checkInitialized --- .../AbstractExternalProjectImportBuilder.java | 82 +++++++++++-------- 1 file changed, 48 insertions(+), 34 deletions(-) diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/wizard/AbstractExternalProjectImportBuilder.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/wizard/AbstractExternalProjectImportBuilder.java index cf7be530aaa1..f4f94ea4b711 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/wizard/AbstractExternalProjectImportBuilder.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/wizard/AbstractExternalProjectImportBuilder.java @@ -33,6 +33,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.roots.ui.configuration.ModulesConfigurator; import com.intellij.openapi.roots.ui.configuration.ModulesProvider; +import com.intellij.openapi.startup.StartupManager; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; @@ -124,7 +125,7 @@ public abstract class AbstractExternalProjectImportBuilder modules = ContainerUtil.newSmartList(); final IdeModifiableModelsProvider modelsProvider = isFromUI ? new IdeUIModifiableModelsProvider( @@ -163,46 +164,59 @@ public abstract class AbstractExternalProjectImportBuilder externalProjectNode, + boolean isFromUI, + final List modules, + IdeModifiableModelsProvider modelsProvider, final ExternalProjectSettings projectSettings) { + myProjectDataManager.importData(externalProjectNode, project, modelsProvider, true); + myExternalProjectNode = null; + + // resolve dependencies + final Runnable resolveDependenciesTask = new Runnable() { + @Override + public void run() { + ExternalSystemUtil.refreshProject( + project, myExternalSystemId, projectSettings.getExternalProjectPath(), false, + ProgressExecutionMode.IN_BACKGROUND_ASYNC); + } + }; + if (!isFromUI) { + resolveDependenciesTask.run(); + } + else { + // execute when current dialog is closed + ExternalSystemUtil.invokeLater(project, ModalityState.NON_MODAL, new Runnable() { + @Override + public void run() { + final Module[] committedModules = ModuleManager.getInstance(project).getModules(); + if (ContainerUtil.list(committedModules).containsAll(modules)) { + resolveDependenciesTask.run(); + } + else { + ExternalSystemApiUtil.getLocalSettings(project, myExternalSystemId).forgetExternalProjects( + Collections.singleton(projectSettings.getExternalProjectPath())); + ExternalSystemApiUtil.getSettings(project, myExternalSystemId).unlinkExternalProject( + projectSettings.getExternalProjectPath()); + + ExternalProjectsManager.getInstance(project).forgetExternalProjectData( + myExternalSystemId, projectSettings.getExternalProjectPath()); + } + } + }); + } + } + @NotNull private ExternalProjectSettings getCurrentExternalProjectSettings() { ExternalProjectSettings result = myControl.getProjectSettings().clone(); From d8f90c8826d299cb4aa81aa30233216a13ec717f Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Fri, 6 Nov 2015 11:25:30 +0100 Subject: [PATCH 017/124] [platform] system health issues logged always --- .../src/com/intellij/ide/SystemHealthMonitor.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/SystemHealthMonitor.java b/platform/platform-impl/src/com/intellij/ide/SystemHealthMonitor.java index 9c23f46a9b0d..dea9ecaff2b7 100644 --- a/platform/platform-impl/src/com/intellij/ide/SystemHealthMonitor.java +++ b/platform/platform-impl/src/com/intellij/ide/SystemHealthMonitor.java @@ -54,7 +54,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; public class SystemHealthMonitor extends ApplicationComponent.Adapter { - private static final Logger LOG = Logger.getInstance("#com.intellij.ide.SystemHealthMonitor"); + private static final Logger LOG = Logger.getInstance(SystemHealthMonitor.class); private static final NotificationGroup GROUP = new NotificationGroup("System Health", NotificationDisplayType.STICKY_BALLOON, false); private static final NotificationGroup LOG_GROUP = NotificationGroup.logOnlyGroup("System Health (minor)"); @@ -112,9 +112,9 @@ public class SystemHealthMonitor extends ApplicationComponent.Adapter { private void showNotification(@PropertyKey(resourceBundle = "messages.IdeBundle") String key) { final String ignoreKey = "ignore." + key; - if (myProperties.isValueSet(ignoreKey)) { - return; - } + boolean ignored = myProperties.isValueSet(ignoreKey); + LOG.info("issue detected: " + key + (ignored ? " (ignored)" : "")); + if (ignored) return; final String message = IdeBundle.message(key) + IdeBundle.message("sys.health.acknowledge.link"); From 0d13912ba83981c64b6458e2070ab3ca33688eb9 Mon Sep 17 00:00:00 2001 From: "Vladislav.Soroka" Date: Fri, 6 Nov 2015 13:28:25 +0300 Subject: [PATCH 018/124] maven: index update error log fix --- .../main/java/org/jetbrains/idea/maven/indices/MavenIndex.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndex.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndex.java index 5215ae2ae44c..f4e3b10f1dd4 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndex.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenIndex.java @@ -351,7 +351,7 @@ public class MavenIndex { private void handleUpdateException(Exception e) { myFailureMessage = e.getMessage(); - MavenLog.LOG.warn("Failed to update Maven indices for: [" + myId + "] " + myRepositoryPathOrUrl, e); + MavenLog.LOG.warn("Failed to update Maven indices for: [" + myId.getValue() + "] " + myRepositoryPathOrUrl, e); } private int createContext(File contextDir, String suffix) throws MavenServerIndexerException { From 6c0727a38dd399ef2e67668c9958b0f4522c7d14 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 5 Nov 2015 20:26:43 +0100 Subject: [PATCH 019/124] drill to directory content in case of flatten packages for content/source root directories (IDEA-147449) --- .../packageDependencies/ui/DirectoryNode.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/platform/lang-impl/src/com/intellij/packageDependencies/ui/DirectoryNode.java b/platform/lang-impl/src/com/intellij/packageDependencies/ui/DirectoryNode.java index 7464c9f4cf48..0393cf8848bc 100644 --- a/platform/lang-impl/src/com/intellij/packageDependencies/ui/DirectoryNode.java +++ b/platform/lang-impl/src/com/intellij/packageDependencies/ui/DirectoryNode.java @@ -121,6 +121,20 @@ public class DirectoryNode extends PackageDependenciesNode { if (child instanceof FileNode || recursively) { child.fillFiles(set, true); } + else if (child instanceof DirectoryNode) { + final VirtualFile directory = ((DirectoryNode)child).getDirectory(); + if (directory != null) { + final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(myProject).getFileIndex(); + final VirtualFile contentRoot = fileIndex.getContentRootForFile(directory); + final VirtualFile sourceRoot = fileIndex.getSourceRootForFile(directory); + if (directory.equals(contentRoot) || + contentRoot != null && contentRoot.equals(directory.getParent()) || + directory.equals(sourceRoot) || + sourceRoot != null && sourceRoot.equals(directory.getParent())) { + child.fillFiles(set, false); + } + } + } } } From db3999c65aaa4dd960eae30f9d7c81bb8f0eaa8e Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 6 Nov 2015 11:12:55 +0100 Subject: [PATCH 020/124] don't check public modifier for abstract classes cause inheritors would be checked for actual runnable --- .../src/com/intellij/psi/util/PsiClassUtil.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/java/java-psi-api/src/com/intellij/psi/util/PsiClassUtil.java b/java/java-psi-api/src/com/intellij/psi/util/PsiClassUtil.java index 745b9bae07c5..1f2d47996384 100644 --- a/java/java-psi-api/src/com/intellij/psi/util/PsiClassUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/util/PsiClassUtil.java @@ -33,7 +33,11 @@ public class PsiClassUtil { public static boolean isRunnableClass(final PsiClass aClass, final boolean mustBePublic, boolean mustNotBeAbstract) { if (aClass instanceof PsiAnonymousClass) return false; if (aClass.isInterface()) return false; - if (mustBePublic && !aClass.hasModifierProperty(PsiModifier.PUBLIC)) return false; + if (mustBePublic && !aClass.hasModifierProperty(PsiModifier.PUBLIC)) { + if (mustNotBeAbstract || !aClass.hasModifierProperty(PsiModifier.ABSTRACT)) { + return false; + } + } if (aClass.hasModifierProperty(PsiModifier.PRIVATE)) return false; if (mustNotBeAbstract && aClass.hasModifierProperty(PsiModifier.ABSTRACT)) return false; return aClass.getContainingClass() == null || aClass.hasModifierProperty(PsiModifier.STATIC); From fa128d15656e777b052ff99d6999401a9db48b45 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Fri, 6 Nov 2015 14:49:55 +0300 Subject: [PATCH 021/124] IDEA-143572 Android: IAE at com.android.tools.idea.gradle.parser.GradleGroovyFile.checkInitialized: fix import Gradle module from project structure --- .../AbstractExternalProjectImportBuilder.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/wizard/AbstractExternalProjectImportBuilder.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/wizard/AbstractExternalProjectImportBuilder.java index f4f94ea4b711..109a4ce6070f 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/wizard/AbstractExternalProjectImportBuilder.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/wizard/AbstractExternalProjectImportBuilder.java @@ -164,12 +164,15 @@ public abstract class AbstractExternalProjectImportBuilder Date: Fri, 6 Nov 2015 15:23:36 +0300 Subject: [PATCH 022/124] OC-9697 Include ObjC symbols into search everywhere --- .../DefaultSearchEverywhereClassifier.java | 50 +++++++++++++++ .../ide/actions/SearchEverywhereAction.java | 36 +++++------ .../actions/SearchEverywhereClassifier.java | 63 +++++++++++++++++++ .../src/META-INF/LangExtensionPoints.xml | 1 + .../src/META-INF/LangExtensions.xml | 1 + 5 files changed, 131 insertions(+), 20 deletions(-) create mode 100644 platform/lang-impl/src/com/intellij/ide/actions/DefaultSearchEverywhereClassifier.java create mode 100644 platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereClassifier.java diff --git a/platform/lang-impl/src/com/intellij/ide/actions/DefaultSearchEverywhereClassifier.java b/platform/lang-impl/src/com/intellij/ide/actions/DefaultSearchEverywhereClassifier.java new file mode 100644 index 000000000000..f77d294d1aaa --- /dev/null +++ b/platform/lang-impl/src/com/intellij/ide/actions/DefaultSearchEverywhereClassifier.java @@ -0,0 +1,50 @@ +/* + * 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 com.intellij.ide.actions; + +import com.intellij.lang.Language; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class DefaultSearchEverywhereClassifier implements SearchEverywhereClassifier { + @Override + public boolean isClass(@Nullable Object o) { + return o instanceof PsiElement; + } + + @Override + public boolean isSymbol(@Nullable Object o) { + if (o instanceof PsiElement) { + final PsiElement e = (PsiElement)o; + return !e.getLanguage().is(Language.findLanguageByID("JAVA")) || !(e.getParent() instanceof PsiFile); + } + return false; + } + + @Nullable + @Override + public VirtualFile getVirtualFile(@NotNull Object o) { + if (o instanceof PsiElement) { + final PsiElement element = (PsiElement)o; + final PsiFile file = element.getContainingFile(); + return file != null ? file.getVirtualFile() : null; + } + return null; + } +} diff --git a/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java b/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java index 309c78e113a1..5899bf88f37a 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java @@ -49,6 +49,7 @@ import com.intellij.lang.Language; import com.intellij.lang.LanguagePsiElementExternalizer; import com.intellij.navigation.ItemPresentation; import com.intellij.navigation.NavigationItem; +import com.intellij.navigation.PsiElementNavigationItem; import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.actionSystem.ex.ActionUtil; @@ -1737,12 +1738,14 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA myProgressIndicator, new Processor() { @Override public boolean process(Object o) { - if (isSymbol(o)) { - final PsiElement element = (PsiElement)o; - final PsiFile file = element.getContainingFile(); - if (!myListModel.contains(o) && !symbols.contains(o) && - //some elements are non-physical like DB columns - (file == null || (file.getVirtualFile() != null && (includeLibs || scope.accept(file.getVirtualFile()))))) { + if (SearchEverywhereClassifier.EP_Manager.isSymbol(o) && !myListModel.contains(o) && !symbols.contains(o)) { + VirtualFile virtualFile = SearchEverywhereClassifier.EP_Manager.getVirtualFile(o); + //some elements are non-physical like DB columns + if (o instanceof PsiElementNavigationItem) { + o = ((PsiElementNavigationItem)o).getTargetElement(); + } + if ((o instanceof PsiElement && ((PsiElement)o).getContainingFile() == null) || + (virtualFile != null && (includeLibs || scope.accept(virtualFile)))) { symbols.add(o); } } @@ -1758,16 +1761,6 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA return symbols; } - protected boolean isSymbol(Object o) { - if (o instanceof PsiElement) { - final PsiElement e = (PsiElement)o; - //todo[kb] need a better way to avoid mixing java classes with symbols. Same to other languages where - //todo[kb] symbol provider returns classes. We need kind of suppressor API & EP here. - return !e.getLanguage().is(Language.findLanguageByID("JAVA")) || !(e.getParent() instanceof PsiFile); - } - return false; - } - private SearchResult getClasses(String pattern, boolean includeLibs, final int max, ChooseByNamePopup chooseByNamePopup) { final SearchResult classes = new SearchResult(); if (chooseByNamePopup == null || shouldSkipPattern(pattern)) { @@ -1777,17 +1770,20 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA myProgressIndicator, new Processor() { @Override public boolean process(Object o) { - if (o instanceof PsiElement && !myListModel.contains(o) && !classes.contains(o)) { + if (SearchEverywhereClassifier.EP_Manager.isClass(o) && !myListModel.contains(o) && !classes.contains(o)) { if (classes.size() == max) { classes.needMore = true; return false; } classes.add(o); + + if (o instanceof PsiElementNavigationItem) { + o = ((PsiElementNavigationItem)o).getTargetElement(); + } if (o instanceof PsiNamedElement) { final String name = ((PsiNamedElement)o).getName(); - final PsiFile file = ((PsiNamedElement)o).getContainingFile(); - if (file != null) { - final VirtualFile virtualFile = file.getVirtualFile(); + VirtualFile virtualFile = SearchEverywhereClassifier.EP_Manager.getVirtualFile(o); + if (virtualFile != null) { if (StringUtil.equals(name, virtualFile.getNameWithoutExtension())) { myAlreadyAddedFiles.add(virtualFile); } diff --git a/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereClassifier.java b/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereClassifier.java new file mode 100644 index 000000000000..df01b72c04f5 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereClassifier.java @@ -0,0 +1,63 @@ +/* + * 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 com.intellij.ide.actions; + +import com.intellij.openapi.extensions.ExtensionPointName; +import com.intellij.openapi.extensions.Extensions; +import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author Philipp Smorygo + */ +public interface SearchEverywhereClassifier { + class EP_Manager { + private EP_Manager() {} + + public static boolean isClass(@Nullable Object o) { + for (SearchEverywhereClassifier classifier : Extensions.getExtensions(SearchEverywhereClassifier.EP_NAME)) { + if (classifier.isClass(o)) return true; + } + return false; + } + + public static boolean isSymbol(@Nullable Object o) { + for (SearchEverywhereClassifier classifier : Extensions.getExtensions(SearchEverywhereClassifier.EP_NAME)) { + if (classifier.isSymbol(o)) return true; + } + return false; + } + + @Nullable + public static VirtualFile getVirtualFile(@NotNull Object o) { + for (SearchEverywhereClassifier classifier : Extensions.getExtensions(SearchEverywhereClassifier.EP_NAME)) { + VirtualFile virtualFile = classifier.getVirtualFile(o); + if (virtualFile != null) return virtualFile; + } + return null; + } + } + + ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.searchEverywhereClassifier"); + + boolean isClass(@Nullable Object o); + + boolean isSymbol(@Nullable Object o); + + @Nullable + VirtualFile getVirtualFile(@NotNull Object o); +} diff --git a/platform/platform-resources/src/META-INF/LangExtensionPoints.xml b/platform/platform-resources/src/META-INF/LangExtensionPoints.xml index b2ec46225bdc..ac297d36c338 100644 --- a/platform/platform-resources/src/META-INF/LangExtensionPoints.xml +++ b/platform/platform-resources/src/META-INF/LangExtensionPoints.xml @@ -843,6 +843,7 @@ + diff --git a/platform/platform-resources/src/META-INF/LangExtensions.xml b/platform/platform-resources/src/META-INF/LangExtensions.xml index 6f1691dbb1c3..5a9b04f6555a 100644 --- a/platform/platform-resources/src/META-INF/LangExtensions.xml +++ b/platform/platform-resources/src/META-INF/LangExtensions.xml @@ -557,6 +557,7 @@ + From 521a88bfb3e7ea731e85203a60541b1287a5a5d6 Mon Sep 17 00:00:00 2001 From: "Vladislav.Soroka" Date: Fri, 6 Nov 2015 15:26:56 +0300 Subject: [PATCH 023/124] external system: do not cleanup orphan project libraries if import runs from Project Structure Dialog --- .../service/project/manage/LibraryDataService.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/LibraryDataService.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/LibraryDataService.java index f1ed6303c9ff..e4211e70a44f 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/LibraryDataService.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/LibraryDataService.java @@ -10,6 +10,7 @@ import com.intellij.openapi.externalSystem.model.project.LibraryPathType; import com.intellij.openapi.externalSystem.model.project.ProjectData; import com.intellij.openapi.externalSystem.service.project.ExternalLibraryPathTypeMapper; import com.intellij.openapi.externalSystem.service.project.IdeModifiableModelsProvider; +import com.intellij.openapi.externalSystem.service.project.IdeUIModifiableModelsProvider; import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil; import com.intellij.openapi.externalSystem.util.ExternalSystemConstants; import com.intellij.openapi.externalSystem.util.ExternalSystemUtil; @@ -22,7 +23,6 @@ import com.intellij.openapi.roots.OrderRootType; import com.intellij.openapi.roots.RootPolicy; import com.intellij.openapi.roots.libraries.Library; import com.intellij.openapi.roots.libraries.LibraryTable; -import com.intellij.openapi.util.Computable; import com.intellij.openapi.vfs.JarFileSystem; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; @@ -110,8 +110,7 @@ public class LibraryDataService extends AbstractProjectDataService> libraryFiles, @NotNull Library.ModifiableModel model, - @NotNull String libraryName) - { + @NotNull String libraryName) { for (Map.Entry> entry : libraryFiles.entrySet()) { for (File file : entry.getValue()) { VirtualFile virtualFile = ExternalSystemUtil.refreshAndFindFileByIoFile(file); @@ -167,6 +166,11 @@ public class LibraryDataService extends AbstractProjectDataService orphanIdeLibraries = ContainerUtil.newSmartList(); final LibraryTable.ModifiableModel librariesModel = modelsProvider.getModifiableProjectLibrariesModel(); for (Library library : librariesModel.getLibraries()) { From 2ca501b2cdcf7987dba6c94398e4179371a14002 Mon Sep 17 00:00:00 2001 From: Alexander Zolotov Date: Thu, 5 Nov 2015 20:31:46 +0300 Subject: [PATCH 024/124] CSS: do not cache custom selectors --- .../src/com/intellij/xml/util/HtmlUtil.java | 41 +++++++++++-------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/xml/xml-psi-impl/src/com/intellij/xml/util/HtmlUtil.java b/xml/xml-psi-impl/src/com/intellij/xml/util/HtmlUtil.java index 6a393d7a374f..c479ceba74be 100644 --- a/xml/xml-psi-impl/src/com/intellij/xml/util/HtmlUtil.java +++ b/xml/xml-psi-impl/src/com/intellij/xml/util/HtmlUtil.java @@ -318,22 +318,7 @@ public class HtmlUtil { final String tagName = tokenizer.nextToken(); if (tagName.length() == 0) continue; - descriptors[index++] = new XmlElementDescriptorImpl(null) { - @Override - public String getName(PsiElement context) { - return tagName; - } - - @Override - public String getDefaultName() { - return tagName; - } - - @Override - public boolean allowElementsFromNamespace(final String namespace, final XmlTag context) { - return true; - } - }; + descriptors[index++] = new CustomXmlTagDescriptor(tagName); } return descriptors; @@ -684,4 +669,28 @@ public class HtmlUtil { public static boolean isScriptTag(@Nullable XmlTag tag) { return tag != null && tag.getLocalName().equalsIgnoreCase(SCRIPT_TAG_NAME); } + + public static class CustomXmlTagDescriptor extends XmlElementDescriptorImpl { + private final String myTagName; + + public CustomXmlTagDescriptor(String tagName) { + super(null); + myTagName = tagName; + } + + @Override + public String getName(PsiElement context) { + return myTagName; + } + + @Override + public String getDefaultName() { + return myTagName; + } + + @Override + public boolean allowElementsFromNamespace(final String namespace, final XmlTag context) { + return true; + } + } } From 3045138aef12570407b40cc1975600980c77db45 Mon Sep 17 00:00:00 2001 From: "Vassiliy.Kudryashov" Date: Fri, 6 Nov 2015 15:37:36 +0300 Subject: [PATCH 025/124] project leak via toolbar->icon->DeferredIcon.evaluator->RunManager$1->project --- .../src/com/intellij/openapi/wm/impl/IdeRootPane.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeRootPane.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeRootPane.java index 5a45cf7898ac..15143b8480d5 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeRootPane.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeRootPane.java @@ -38,6 +38,7 @@ import com.intellij.openapi.wm.impl.status.MemoryUsagePanel; import com.intellij.ui.BalloonLayout; import com.intellij.ui.BalloonLayoutImpl; import com.intellij.ui.PopupHandler; +import com.intellij.ui.ScreenUtil; import com.intellij.ui.components.JBLayeredPane; import com.intellij.ui.components.JBPanel; import com.intellij.util.containers.ContainerUtil; @@ -147,7 +148,9 @@ public class IdeRootPane extends JRootPane implements UISettingsListener { */ public final void removeNotify(){ myUISettings.removeUISettingsListener(this); - removeToolbar(); + if (ScreenUtil.isStandardAddRemoveNotify(this)) { + removeToolbar(); + } super.removeNotify(); } From 4515f3496e6b1f2499c07c7828b9dcf7083a9ca5 Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Fri, 6 Nov 2015 15:35:31 +0300 Subject: [PATCH 026/124] fallback url provided when legacy key conversion is not possible (IDEA-147130), 'JetProfile' term changed to 'JetBrains Account' in UI error messages --- .../openapi/application/ApplicationInfo.java | 1 + .../application/impl/ApplicationInfoImpl.java | 18 +++++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/platform/core-api/src/com/intellij/openapi/application/ApplicationInfo.java b/platform/core-api/src/com/intellij/openapi/application/ApplicationInfo.java index 3b57b78c053c..2b1d076af620 100644 --- a/platform/core-api/src/com/intellij/openapi/application/ApplicationInfo.java +++ b/platform/core-api/src/com/intellij/openapi/application/ApplicationInfo.java @@ -36,6 +36,7 @@ public abstract class ApplicationInfo { public abstract String getThirdPartySoftwareURL(); public abstract String getJetbrainsTvUrl(); public abstract String getEvalLicenseUrl(); + public abstract String getKeyConversionUrl(); public abstract Rectangle getAboutLogoRect(); public abstract boolean hasHelp(); diff --git a/platform/core-impl/src/com/intellij/openapi/application/impl/ApplicationInfoImpl.java b/platform/core-impl/src/com/intellij/openapi/application/impl/ApplicationInfoImpl.java index 6ea1233625a1..3fe63183d244 100644 --- a/platform/core-impl/src/com/intellij/openapi/application/impl/ApplicationInfoImpl.java +++ b/platform/core-impl/src/com/intellij/openapi/application/impl/ApplicationInfoImpl.java @@ -110,6 +110,7 @@ public class ApplicationInfoImpl extends ApplicationInfoEx { private String myThirdPartySoftwareUrl; private String myJetbrainsTvUrl; private String myEvalLicenseUrl = "https://www.jetbrains.com/company/useterms.html"; + private String myKeyConversionUrl = "https://www.jetbrains.com/shop/eform/keys-exchange"; private Rectangle myAboutLogoRect; @@ -187,6 +188,8 @@ public class ApplicationInfoImpl extends ApplicationInfoEx { private static final String STEPS_PROVIDER = "provider"; private static final String ELEMENT_EVALUATION = "evaluation"; private static final String ATTRIBUTE_EVAL_LICENSE_URL = "license-url"; + private static final String ELEMENT_LICENSING = "licensing"; + private static final String ATTRIBUTE_KEY_CONVERSION_URL = "key-conversion-url"; private static final String ESSENTIAL_PLUGIN = "essential-plugin"; private static final String DEFAULT_PLUGINS_HOST = "http://plugins.jetbrains.com"; @@ -541,6 +544,11 @@ public class ApplicationInfoImpl extends ApplicationInfoEx { return myEvalLicenseUrl; } + @Override + public String getKeyConversionUrl() { + return myKeyConversionUrl; + } + @Override public Rectangle getAboutLogoRect() { return myAboutLogoRect; @@ -836,7 +844,15 @@ public class ApplicationInfoImpl extends ApplicationInfoEx { if (evaluationElement != null) { final String url = evaluationElement.getAttributeValue(ATTRIBUTE_EVAL_LICENSE_URL); if (url != null && !url.isEmpty()) { - myEvalLicenseUrl = url; + myEvalLicenseUrl = url.trim(); + } + } + + Element licensingElement = parentNode.getChild(ELEMENT_LICENSING); + if (licensingElement != null) { + final String url = licensingElement.getAttributeValue(ATTRIBUTE_KEY_CONVERSION_URL); + if (url != null && !url.isEmpty()) { + myKeyConversionUrl = url.trim(); } } From fb32abd2fead8af17cd1cf612dc27f9172562b8e Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Fri, 6 Nov 2015 15:55:03 +0300 Subject: [PATCH 027/124] correctly render alternative sources from jdk (show something more than just rt.jar) --- ...AlternativeSourceNotificationProvider.java | 34 ++++++------------- 1 file changed, 10 insertions(+), 24 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/AlternativeSourceNotificationProvider.java b/java/debugger/impl/src/com/intellij/debugger/ui/AlternativeSourceNotificationProvider.java index 34e42469cd82..1cd8ef71af4a 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/AlternativeSourceNotificationProvider.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/AlternativeSourceNotificationProvider.java @@ -18,14 +18,11 @@ package com.intellij.debugger.ui; import com.intellij.debugger.DebuggerBundle; import com.intellij.debugger.impl.DebuggerUtilsEx; import com.intellij.ide.highlighter.JavaClassFileType; +import com.intellij.ide.util.ModuleRendererFactory; import com.intellij.openapi.fileEditor.FileEditor; import com.intellij.openapi.fileEditor.FileEditorManager; -import com.intellij.openapi.module.Module; -import com.intellij.openapi.module.ModuleUtilCore; import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; -import com.intellij.openapi.roots.ProjectFileIndex; -import com.intellij.openapi.roots.ProjectRootManager; import com.intellij.openapi.ui.ComboBox; import com.intellij.openapi.util.Key; import com.intellij.openapi.vfs.VirtualFile; @@ -33,6 +30,7 @@ import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.ui.EditorNotificationPanel; import com.intellij.ui.EditorNotifications; +import com.intellij.ui.components.JBList; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import com.intellij.xdebugger.XDebugSession; @@ -41,6 +39,7 @@ import com.intellij.xdebugger.XSourcePosition; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import javax.swing.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; @@ -115,7 +114,7 @@ public class AlternativeSourceNotificationProvider extends EditorNotifications.P new Function() { @Override public ComboBoxClassElement fun(PsiClass psiClass) { - return new ComboBoxClassElement(psiClass); + return new ComboBoxClassElement((PsiClass)psiClass.getNavigationElement()); } }); @@ -132,27 +131,15 @@ public class AlternativeSourceNotificationProvider extends EditorNotifications.P myClass = aClass; } + private static JList ourDummyList = new JBList(); // to use ModuleRendererFactory + @Override public String toString() { if (myText == null) { - Module module = ModuleUtilCore.findModuleForPsiElement(myClass); - if (module != null) { - myText = module.getName(); - } - else { - VirtualFile virtualFile = myClass.getContainingFile().getVirtualFile(); - final ProjectFileIndex index = ProjectRootManager.getInstance(myClass.getProject()).getFileIndex(); - VirtualFile root = index.getSourceRootForFile(virtualFile); - if (root == null) { - root = index.getClassRootForFile(virtualFile); - } - if (root != null) { - myText = root.getName(); - } - else { - myText = virtualFile.getPath(); - } - } + ModuleRendererFactory factory = ModuleRendererFactory.findInstance(myClass); + DefaultListCellRenderer moduleRenderer = factory.getModuleRenderer(); + moduleRenderer.getListCellRendererComponent(ourDummyList, myClass, 1, false, false); + myText = moduleRenderer.getText(); } return myText; } @@ -174,7 +161,6 @@ public class AlternativeSourceNotificationProvider extends EditorNotifications.P public void actionPerformed(ActionEvent e) { FileEditorManager.getInstance(project).closeFile(file); PsiClass item = ((ComboBoxClassElement)switcher.getSelectedItem()).myClass; - item = (PsiClass)item.getNavigationElement(); // go through compiled DebuggerUtilsEx.setAlternativeSource(file, item.getContainingFile().getVirtualFile()); item.navigate(true); XDebugSession session = XDebuggerManager.getInstance(project).getCurrentSession(); From e8805cb2ccd31e434d30df73ec6feae62f13fe77 Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Fri, 6 Nov 2015 15:55:37 +0300 Subject: [PATCH 028/124] "initialize variable" & "initialize in constructor" suggests default constructors (with inheritor's if collection) (IDEA-145431) --- .../completion/JavaInheritorsGetter.java | 21 ++- .../quickfix/AddVariableInitializerFix.java | 148 ++++++++++++++++-- .../InitializeFinalFieldInConstructorFix.java | 67 +++----- .../addVariableInitializer/after1.java | 2 +- .../addVariableInitializer/after2.java | 2 +- .../afterMultipleInvoke.java | 4 +- .../afterParamWithSameName.java | 2 +- .../afterSimpleInvoke.java | 2 +- 8 files changed, 171 insertions(+), 77 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaInheritorsGetter.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaInheritorsGetter.java index 74745435d576..cceb1668a231 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaInheritorsGetter.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaInheritorsGetter.java @@ -221,19 +221,26 @@ public class JavaInheritorsGetter extends CompletionProvider expectedClassTypes, final PrefixMatcher matcher, final Consumer consumer) { + processInheritors(parameters.getOriginalFile(), parameters.getPosition(), expectedClassTypes, matcher, consumer); + } + + public static void processInheritors(final PsiFile file, + final PsiElement context, + final Collection expectedClassTypes, + final PrefixMatcher matcher, final Consumer consumer) { //quick - if (!processMostProbableInheritors(parameters, expectedClassTypes, consumer)) return; + if (!processMostProbableInheritors(file, context, expectedClassTypes, consumer)) return; //long for (final PsiClassType type : expectedClassTypes) { - CodeInsightUtil.processSubTypes(type, parameters.getPosition(), false, matcher, consumer); + CodeInsightUtil.processSubTypes(type, context, false, matcher, consumer); } } - private static boolean processMostProbableInheritors(CompletionParameters parameters, + private static boolean processMostProbableInheritors(PsiFile contextFile, + PsiElement context, Collection expectedClassTypes, Consumer consumer) { - PsiFile file = parameters.getOriginalFile(); for (final PsiClassType type : expectedClassTypes) { consumer.consume(type); @@ -243,15 +250,15 @@ public class JavaInheritorsGetter extends CompletionProvider processor = CodeInsightUtil.createInheritorsProcessor(parameters.getPosition(), type, 0, false, + final Processor processor = CodeInsightUtil.createInheritorsProcessor(context, type, 0, false, consumer, baseClass, baseSubstitutor); final StatisticsInfo[] stats = StatisticsManager.getInstance().getAllValues(JavaStatisticsManager.getAfterNewKey(type)); for (final StatisticsInfo statisticsInfo : stats) { final String value = statisticsInfo.getValue(); if (value.startsWith(JavaStatisticsManager.CLASS_PREFIX)) { final String qname = value.substring(JavaStatisticsManager.CLASS_PREFIX.length()); - final PsiClass psiClass = JavaPsiFacade.getInstance(file.getProject()).findClass(qname, file.getResolveScope()); - if (psiClass != null && !PsiTreeUtil.isAncestor(file, psiClass, true) && !processor.process(psiClass)) break; + final PsiClass psiClass = JavaPsiFacade.getInstance(contextFile.getProject()).findClass(qname, contextFile.getResolveScope()); + if (psiClass != null && !PsiTreeUtil.isAncestor(contextFile, psiClass, true) && !processor.process(psiClass)) break; } } } diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddVariableInitializerFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddVariableInitializerFix.java index b1736eb96eb1..c12e64fdf25b 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddVariableInitializerFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddVariableInitializerFix.java @@ -16,18 +16,33 @@ package com.intellij.codeInsight.daemon.impl.quickfix; import com.intellij.codeInsight.CodeInsightBundle; -import com.intellij.codeInsight.CodeInsightUtilCore; import com.intellij.codeInsight.FileModificationService; +import com.intellij.codeInsight.completion.*; import com.intellij.codeInsight.intention.IntentionAction; +import com.intellij.codeInsight.lookup.*; +import com.intellij.codeInsight.template.*; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.editor.ScrollType; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.TextRange; import com.intellij.psi.*; +import com.intellij.psi.util.InheritanceUtil; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiTypesUtil; +import com.intellij.psi.util.PsiUtil; +import com.intellij.refactoring.util.RefactoringUtil; +import com.intellij.util.Consumer; +import com.intellij.util.Function; import com.intellij.util.IncorrectOperationException; +import com.intellij.util.SmartList; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +import static com.intellij.util.containers.ContainerUtil.*; public class AddVariableInitializerFix implements IntentionAction { private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.quickfix.AddReturnFix"); @@ -62,9 +77,10 @@ public class AddVariableInitializerFix implements IntentionAction { public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { if (!FileModificationService.getInstance().prepareFileForWrite(myVariable.getContainingFile())) return; - String initializerText = suggestInitializer(); - PsiElementFactory factory = JavaPsiFacade.getInstance(myVariable.getProject()).getElementFactory(); - PsiExpression initializer = factory.createExpressionFromText(initializerText, myVariable); + final LookupElement[] suggestedInitializers = suggestInitializer(myVariable); + LOG.assertTrue(suggestedInitializers.length > 0); + LOG.assertTrue(suggestedInitializers[0] instanceof ExpressionLookupItem); + final PsiExpression initializer = (PsiExpression) suggestedInitializers[0].getObject(); if (myVariable instanceof PsiLocalVariable) { ((PsiLocalVariable)myVariable).setInitializer(initializer); } @@ -74,17 +90,119 @@ public class AddVariableInitializerFix implements IntentionAction { else { LOG.error("Unknown variable type: "+myVariable); } - PsiVariable var = CodeInsightUtilCore.forcePsiPostprocessAndRestoreElement(myVariable); - TextRange range = var.getInitializer().getTextRange(); - int offset = range.getStartOffset(); - editor.getCaretModel().moveToOffset(offset); - editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE); - editor.getSelectionModel().setSelection(range.getStartOffset(), range.getEndOffset()); + runAssignmentTemplate(Collections.singletonList(myVariable.getInitializer()), suggestedInitializers, editor); } - private String suggestInitializer() { - PsiType type = myVariable.getType(); - return PsiTypesUtil.getDefaultValueOfType(type); + public static void runAssignmentTemplate(@NotNull final List initializers, + @NotNull final LookupElement[] suggestedInitializers, + @Nullable Editor editor) { + if (editor == null) return; + LOG.assertTrue(!initializers.isEmpty()); + final PsiExpression initializer = ContainerUtil.getFirstItem(initializers); + PsiElement context = initializers.size() == 1 ? initializer : PsiTreeUtil.findCommonParent(initializers); + PsiDocumentManager.getInstance(initializer.getProject()).doPostponedOperationsAndUnblockDocument(editor.getDocument()); + final TemplateBuilderImpl builder = (TemplateBuilderImpl)TemplateBuilderFactory.getInstance().createTemplateBuilder(context); + for (PsiExpression e : initializers) { + builder.replaceElement(e, new Expression() { + @Nullable + @Override + public Result calculateResult(ExpressionContext context1) { + return calculateQuickResult(context1); + } + + @Nullable + @Override + public Result calculateQuickResult(ExpressionContext context1) { + return new PsiElementResult(suggestedInitializers[0].getPsiElement()); + } + + @Nullable + @Override + public LookupElement[] calculateLookupItems(ExpressionContext context1) { + return suggestedInitializers; + } + }); + } + builder.run(editor, false); + } + + @NotNull + public static LookupElement[] suggestInitializer(final PsiVariable variable) { + PsiType type = variable.getType(); + final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(variable.getProject()); + if (type instanceof PsiClassType) { + final PsiClass aClass = PsiTypesUtil.getPsiClass(type); + if (aClass != null) { + final LookupElement nullLookupItem = new ExpressionLookupItem(elementFactory.createExpressionFromText(PsiKeyword.NULL, variable)); + if (InheritanceUtil.isInheritor(aClass, CommonClassNames.JAVA_LANG_ITERABLE) || + InheritanceUtil.isInheritor(aClass, CommonClassNames.JAVA_UTIL_MAP)) { + final List suggestedTypes = new SmartList(); + JavaInheritorsGetter.processInheritors(variable.getContainingFile(), variable, Collections.singleton((PsiClassType) type), PrefixMatcher.ALWAYS_TRUE, new Consumer() { + @Override + public void consume(PsiType type) { + LOG.assertTrue(type instanceof PsiClassType); + final PsiClass psiClass = PsiTypesUtil.getPsiClass(type); + if (psiClass != null && + !psiClass.isInterface() && + !psiClass.hasModifierProperty(PsiModifier.ABSTRACT) && + PsiUtil.hasDefaultConstructor(psiClass)) { + suggestedTypes.add(type); + } + } + }); + + List sortedLookups = map(sorted(map(suggestedTypes, new Function() { + @Override + public LookupElement fun(PsiType type) { + return PsiTypeLookupItem.createLookupItem(type, variable); + } + }), new Comparator() { + @Override + public int compare(LookupElement o1, LookupElement o2) { + final int count1 = StatisticsWeigher.getBaseStatisticsInfo(o1, null).getUseCount(); + final int count2 = StatisticsWeigher.getBaseStatisticsInfo(o2, null).getUseCount(); + return count2 - count1; + } + }), new Function() { + @Override + public LookupElement fun(LookupElement element) { + final LookupElementDecorator constructorLookupElement = + LookupElementDecorator.withInsertHandler(element, ConstructorInsertHandler.BASIC_INSTANCE); + return new LookupElementDecorator(constructorLookupElement) { + @Override + public void renderElement(LookupElementPresentation presentation) { + super.renderElement(presentation); + presentation.setTailText(""); + presentation.setItemText(PsiKeyword.NEW + " " + presentation.getItemText() + "()"); + } + + @Override + public void handleInsert(InsertionContext context) { + super.handleInsert(context); + context.getDocument().insertString(context.getStartOffset(), PsiKeyword.NEW + " "); + } + }; + } + }); + LookupElement[] result = new LookupElement[sortedLookups.size() + 1]; + result[0] = nullLookupItem; + for (int i = 0; i < sortedLookups.size(); i++) { + LookupElement lookup = sortedLookups.get(i); + result[i + 1] = lookup; + } + return result; + } else { + if (PsiUtil.hasDefaultConstructor(aClass)) { + final PsiExpression newExpression = elementFactory + .createExpressionFromText(PsiKeyword.NEW + " " + type.getCanonicalText(false) + "()", variable); + return new LookupElement[]{nullLookupItem, new ExpressionLookupItem(newExpression)}; + } + } + } + } + final String defaultValue = PsiTypesUtil.getDefaultValueOfType(type); + final PsiExpression expression = elementFactory.createExpressionFromText(defaultValue, variable); + return new LookupElement[] {new ExpressionLookupItem(expression)}; } @Override diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/InitializeFinalFieldInConstructorFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/InitializeFinalFieldInConstructorFix.java index ea5e3641cb34..d59fd0ddd6d5 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/InitializeFinalFieldInConstructorFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/InitializeFinalFieldInConstructorFix.java @@ -15,23 +15,20 @@ */ package com.intellij.codeInsight.daemon.impl.quickfix; -import com.intellij.codeInsight.CodeInsightUtilCore; import com.intellij.codeInsight.FileModificationService; import com.intellij.codeInsight.daemon.QuickFixBundle; import com.intellij.codeInsight.generation.PsiMethodMember; import com.intellij.codeInsight.intention.IntentionAction; +import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.ide.util.MemberChooser; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.editor.ScrollType; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.TextRange; import com.intellij.psi.*; import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.psi.search.LocalSearchScope; import com.intellij.psi.search.searches.ReferencesSearch; import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.psi.util.PsiTypesUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; @@ -93,59 +90,34 @@ public class InitializeFinalFieldInConstructorFix implements IntentionAction { ApplicationManager.getApplication().runWriteAction(new Runnable() { @Override public void run() { - final List statements = addFieldInitialization(constructors, myField, project); - final PsiExpressionStatement highestStatement = getHighestElement(statements); - if (highestStatement == null) return; - - final PsiAssignmentExpression expression = (PsiAssignmentExpression)highestStatement.getExpression(); - final PsiElement rightExpression = expression.getRExpression(); - - final TextRange expressionRange = rightExpression.getTextRange(); - editor.getCaretModel().moveToOffset(expressionRange.getStartOffset()); - editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE); - editor.getSelectionModel().setSelection(expressionRange.getStartOffset(), expressionRange.getEndOffset()); + addFieldInitialization(constructors, myField, project, editor); } }); } - @Nullable - private static T getHighestElement(@NotNull List elements) { - T highest = null; - int highestTextOffset = Integer.MAX_VALUE; - for (T element : elements) { - final T forcedElem = CodeInsightUtilCore.forcePsiPostprocessAndRestoreElement(element); - final int startOffset = forcedElem.getTextOffset(); - if (startOffset < highestTextOffset) { - highest = forcedElem; - highestTextOffset = startOffset; - } - } - return highest; - } + private static void addFieldInitialization(@NotNull List constructors, + @NotNull PsiField field, + @NotNull Project project, + @Nullable Editor editor) { + final List rExpressions = new ArrayList(constructors.size()); + final LookupElement[] suggestedInitializers = AddVariableInitializerFix.suggestInitializer(field); - @NotNull - private static List addFieldInitialization(@NotNull List constructors, - @NotNull PsiField field, - @NotNull Project project) { - final List statements = new ArrayList(); for (PsiMethod constructor : constructors) { - final PsiExpressionStatement statement = addFieldInitialization(constructor, field, project); - if (statement != null) { - statements.add(statement); - } + rExpressions.add(addFieldInitialization(constructor, suggestedInitializers, field, project)); } - return statements; + AddVariableInitializerFix.runAssignmentTemplate(rExpressions, suggestedInitializers, editor); } @Nullable - private static PsiExpressionStatement addFieldInitialization(@NotNull PsiMethod constructor, - @NotNull PsiField field, - @NotNull Project project) { + private static PsiExpression addFieldInitialization(@NotNull PsiMethod constructor, + @NotNull LookupElement[] suggestedInitializers, + @NotNull PsiField field, + @NotNull Project project) { PsiCodeBlock methodBody = constructor.getBody(); if (methodBody == null) return null; final String fieldName = field.getName(); - String stmtText = fieldName + " = " + suggestInitValue(field) + ";"; + String stmtText = fieldName + " = " + suggestedInitializers[0].getPsiElement().getText() + ";"; if (methodContainsParameterWithName(constructor, fieldName)) { stmtText = "this." + stmtText; } @@ -154,7 +126,9 @@ public class InitializeFinalFieldInConstructorFix implements IntentionAction { final PsiElementFactory factory = JavaPsiFacade.getInstance(psiManager.getProject()).getElementFactory(); final CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(project); - return (PsiExpressionStatement)methodBody.add(codeStyleManager.reformat(factory.createStatementFromText(stmtText, methodBody))); + final PsiExpressionStatement addedStatement = (PsiExpressionStatement)methodBody.add(codeStyleManager + .reformat(factory.createStatementFromText(stmtText, methodBody))); + return ((PsiAssignmentExpression)addedStatement.getExpression()).getRExpression(); } private static boolean methodContainsParameterWithName(@NotNull PsiMethod constructor, @NotNull String name) { @@ -228,11 +202,6 @@ public class InitializeFinalFieldInConstructorFix implements IntentionAction { return result.toArray(new PsiMethod[result.size()]); } - private static String suggestInitValue(@NotNull PsiField field) { - PsiType type = field.getType(); - return PsiTypesUtil.getDefaultValueOfType(type); - } - @Override public boolean startInWriteAction() { return false; diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addVariableInitializer/after1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addVariableInitializer/after1.java index 7f1e302f38d5..05d7f46088e6 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addVariableInitializer/after1.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addVariableInitializer/after1.java @@ -3,7 +3,7 @@ class AClass { int f() { - int i = 0; + int i = 0; return i; } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addVariableInitializer/after2.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addVariableInitializer/after2.java index 23a08dd405e6..01952f29feed 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addVariableInitializer/after2.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addVariableInitializer/after2.java @@ -2,6 +2,6 @@ class AClass { - final AClass f = null; + final AClass f = null; } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/initializeFinalFieldInConstructor/afterMultipleInvoke.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/initializeFinalFieldInConstructor/afterMultipleInvoke.java index 899b5e69f33f..6b4cbc49001e 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/initializeFinalFieldInConstructor/afterMultipleInvoke.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/initializeFinalFieldInConstructor/afterMultipleInvoke.java @@ -3,10 +3,10 @@ class A { private final int var; private Main() { - var = 0; + var = 0; } private Main(int var) { this.var = 0; } -} \ No newline at end of file +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/initializeFinalFieldInConstructor/afterParamWithSameName.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/initializeFinalFieldInConstructor/afterParamWithSameName.java index b4672ad65e0e..8dda8ee78eb3 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/initializeFinalFieldInConstructor/afterParamWithSameName.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/initializeFinalFieldInConstructor/afterParamWithSameName.java @@ -3,6 +3,6 @@ class A { private final int var; private Main(int var) { - this.var = 0; + this.var = 0; } } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/initializeFinalFieldInConstructor/afterSimpleInvoke.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/initializeFinalFieldInConstructor/afterSimpleInvoke.java index b594c4345357..2155e450fbb2 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/initializeFinalFieldInConstructor/afterSimpleInvoke.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/initializeFinalFieldInConstructor/afterSimpleInvoke.java @@ -3,6 +3,6 @@ class A { private final int var; private Main() { - var = 0; + var = 0; } } \ No newline at end of file From ca528afad5c7dae75c178c1fc6b4571dc98b22dd Mon Sep 17 00:00:00 2001 From: Michael Golubev Date: Fri, 6 Nov 2015 13:30:43 +0100 Subject: [PATCH 029/124] IDEA-144272 - IAE at com.intellij.openapi.wm.impl.ToolWindowManagerImpl.a --- .../runtime/ui/ServersToolWindowManager.java | 43 ++++++++++--------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/ServersToolWindowManager.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/ServersToolWindowManager.java index 2b3c4f8baa06..d8c1064928b2 100644 --- a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/ServersToolWindowManager.java +++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/ServersToolWindowManager.java @@ -64,33 +64,34 @@ public class ServersToolWindowManager extends AbstractProjectComponent { }); } - private void updateWindowAvailable(boolean showIfAvailable) { - boolean available = ServersToolWindowFactory.isAvailable(myProject); - + private void updateWindowAvailable(final boolean showIfAvailable) { final ToolWindowManager toolWindowManager = ToolWindowManager.getInstance(myProject); - final ToolWindow toolWindow = toolWindowManager.getToolWindow(WINDOW_ID); - if (toolWindow == null) { - if (available) { - toolWindowManager.invokeLater(new Runnable() { + toolWindowManager.invokeLater(new Runnable() { - @Override - public void run() { + @Override + public void run() { + boolean available = ServersToolWindowFactory.isAvailable(myProject); + + final ToolWindow toolWindow = toolWindowManager.getToolWindow(WINDOW_ID); + + if (toolWindow == null) { + if (available) { createToolWindow(myProject, toolWindowManager).show(null); } - }); - } - return; - } + return; + } - boolean doShow = !toolWindow.isAvailable() && available; - if (toolWindow.isAvailable() && !available) { - toolWindow.hide(null); - } - toolWindow.setAvailable(available, null); - if (showIfAvailable && doShow) { - toolWindow.show(null); - } + boolean doShow = !toolWindow.isAvailable() && available; + if (toolWindow.isAvailable() && !available) { + toolWindow.hide(null); + } + toolWindow.setAvailable(available, null); + if (showIfAvailable && doShow) { + toolWindow.show(null); + } + } + }); } private static ToolWindow createToolWindow(Project project, ToolWindowManager toolWindowManager) { From 865f0629c9b13d5988af7341011a4e2a717843c2 Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Fri, 6 Nov 2015 15:59:45 +0300 Subject: [PATCH 030/124] "initialize variable" & "initialize in constructor" suggests only public classes for collections --- .../daemon/impl/quickfix/AddVariableInitializerFix.java | 1 + 1 file changed, 1 insertion(+) diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddVariableInitializerFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddVariableInitializerFix.java index c12e64fdf25b..1c69fae07625 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddVariableInitializerFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddVariableInitializerFix.java @@ -145,6 +145,7 @@ public class AddVariableInitializerFix implements IntentionAction { if (psiClass != null && !psiClass.isInterface() && !psiClass.hasModifierProperty(PsiModifier.ABSTRACT) && + psiClass.hasModifierProperty(PsiModifier.PUBLIC) && PsiUtil.hasDefaultConstructor(psiClass)) { suggestedTypes.add(type); } From c5cf3ac835ab9eeb393953f0b81b80c8676810ea Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Fri, 6 Nov 2015 16:04:07 +0300 Subject: [PATCH 031/124] IDEA-146427 Entering and searching keyboard and mouse shortcuts in Settings | Keymap --- .../impl/ui/KeyboardShortcutDialog.java | 278 +++-------------- .../keymap/impl/ui/KeyboardShortcutPanel.java | 42 ++- .../openapi/keymap/impl/ui/KeymapPanel.java | 28 +- .../keymap/impl/ui/MouseShortcutDialog.java | 281 +++--------------- .../keymap/impl/ui/MouseShortcutPanel.java | 27 +- .../keymap/impl/ui/ShortcutDialog.java | 185 ++++++++++++ .../impl/ui/ShortcutFilteringPanel.java | 2 +- .../openapi/keymap/impl/ui/ShortcutPanel.java | 42 +++ .../keymap/impl/ui/ShortcutTextField.java | 12 +- .../src/messages/KeyMapBundle.properties | 5 + .../com/intellij/ui/components/JBPanel.java | 60 ++++ 11 files changed, 405 insertions(+), 557 deletions(-) create mode 100644 platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ShortcutDialog.java create mode 100644 platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ShortcutPanel.java diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeyboardShortcutDialog.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeyboardShortcutDialog.java index b08cf0fdd087..e00bdf6f7f0c 100644 --- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeyboardShortcutDialog.java +++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeyboardShortcutDialog.java @@ -15,260 +15,64 @@ */ package com.intellij.openapi.keymap.impl.ui; - -import com.intellij.ide.DataManager; -import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.actionSystem.KeyboardShortcut; -import com.intellij.openapi.actionSystem.ex.QuickList; -import com.intellij.openapi.help.HelpManager; import com.intellij.openapi.keymap.KeyMapBundle; import com.intellij.openapi.keymap.Keymap; -import com.intellij.openapi.keymap.KeymapUtil; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.DialogWrapper; -import com.intellij.openapi.wm.ex.IdeFocusTraversalPolicy; -import com.intellij.ui.IdeBorderFactory; -import com.intellij.ui.JBColor; -import com.intellij.ui.ScrollPaneFactory; -import com.intellij.util.ArrayUtil; import com.intellij.util.ui.JBUI; -import com.intellij.util.ui.UIUtil; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import javax.swing.*; -import javax.swing.border.EmptyBorder; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.ArrayList; -import java.util.Map; -import java.util.Set; +import java.awt.BorderLayout; +import java.awt.Component; +import java.util.Collection; +import javax.swing.JComponent; +import javax.swing.JPanel; -public class KeyboardShortcutDialog extends DialogWrapper { - private StrokePanel myFirstStrokePanel; - private StrokePanel mySecondStrokePanel; - private final JCheckBox myEnableSecondKeystroke; - private final JLabel myKeystrokePreview; - private final JTextArea myConflictInfoArea; - private Keymap myKeymap; - private final String myActionId; - private final Group myMainGroup; +/** + * @author Sergey.Malenkov + */ +final class KeyboardShortcutDialog extends ShortcutDialog { + private final JComponent myPreferredFocusedComponent; + + KeyboardShortcutDialog(Component parent) { + super(parent, "keyboard.shortcut.dialog.title", new KeyboardShortcutPanel(new BorderLayout())); + + KeyboardShortcutPanel panel = (KeyboardShortcutPanel)myShortcutPanel; + myPreferredFocusedComponent = panel.myFirstStroke; + + JPanel inner = new JPanel(new BorderLayout()); + inner.add(BorderLayout.CENTER, panel.mySecondStroke); + inner.add(BorderLayout.WEST, panel.mySecondStrokeEnable); + panel.add(BorderLayout.NORTH, panel.myFirstStroke); + panel.add(BorderLayout.SOUTH, inner); + panel.setBorder(JBUI.Borders.empty(0, 10)); + panel.mySecondStrokeEnable.setSelected(true); + panel.mySecondStrokeEnable.setText(KeyMapBundle.message("dialog.enable.second.stroke.checkbox")); - public KeyboardShortcutDialog(Component component, String actionId, final QuickList[] quickLists) { - super(component, true); - setTitle(KeyMapBundle.message("keyboard.shortcut.dialog.title")); - myActionId = actionId; - final Project project = CommonDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext(component)); - myMainGroup = ActionsTreeUtil.createMainGroup(project, myKeymap, quickLists, null, false, null); //without current filter - myEnableSecondKeystroke = new JCheckBox(); - UIUtil.applyStyle(UIUtil.ComponentStyle.SMALL, myEnableSecondKeystroke); - myEnableSecondKeystroke.setBorder(new EmptyBorder(4, 0, 0, 2)); - myEnableSecondKeystroke.setFocusable(false); - myKeystrokePreview = new JLabel(" "); - myConflictInfoArea = new JTextArea(""); - myConflictInfoArea.setFocusable(false); init(); } - @NotNull - protected Action[] createActions(){ - return new Action[]{getOKAction(),getCancelAction(),getHelpAction()}; + @Override + protected String getHelpId() { + return "preferences.keymap.shortcut"; } - protected JComponent createCenterPanel() { - JPanel panel = new JPanel(new GridBagLayout()); - - // First stroke - - myFirstStrokePanel = new StrokePanel(KeyMapBundle.message("first.stroke.panel.title")); - panel.add( - myFirstStrokePanel, - new GridBagConstraints(0,0,2,1,1,0,GridBagConstraints.CENTER,GridBagConstraints.HORIZONTAL,new Insets(0,0,0,0),0,0) - ); - - // Second stroke panel - - panel.add( - myEnableSecondKeystroke, - new GridBagConstraints(0,1,1,1,0,0,GridBagConstraints.NORTHWEST,GridBagConstraints.NONE,new Insets(0,0,0,0),0,0) - ); - - mySecondStrokePanel = new StrokePanel(KeyMapBundle.message("second.stroke.panel.title")); - panel.add( - mySecondStrokePanel, - new GridBagConstraints(1,1,1,1,1,0,GridBagConstraints.NORTHWEST,GridBagConstraints.HORIZONTAL,new Insets(0,0,0,0),0,0) - ); - - // Shortcut preview - - JPanel previewPanel = new JPanel(new BorderLayout()); - previewPanel.setBorder(IdeBorderFactory.createTitledBorder(KeyMapBundle.message("shortcut.preview.ide.border.factory.title"), true)); - previewPanel.add(myKeystrokePreview); - panel.add( - previewPanel, - new GridBagConstraints(0,2,2,1,1,0,GridBagConstraints.CENTER,GridBagConstraints.HORIZONTAL,new Insets(0,0,0,0),0,0) - ); - - // Conflicts - - JPanel conflictsPanel = new JPanel(new BorderLayout()); - conflictsPanel.setBorder(IdeBorderFactory.createTitledBorder(KeyMapBundle.message("conflicts.ide.border.factory.title"), - true)); - myConflictInfoArea.setEditable(false); - myConflictInfoArea.setBackground(panel.getBackground()); - myConflictInfoArea.setLineWrap(true); - myConflictInfoArea.setWrapStyleWord(true); - final JScrollPane conflictInfoScroll = ScrollPaneFactory.createScrollPane(myConflictInfoArea); - conflictInfoScroll.setPreferredSize(JBUI.size(260, 60)); - conflictInfoScroll.setBorder(null); - conflictsPanel.add(conflictInfoScroll); - panel.add( - conflictsPanel, - new GridBagConstraints(0,3,2,1,1,1,GridBagConstraints.CENTER,GridBagConstraints.BOTH,new Insets(0,0,0,0),0,0) - ); - - myEnableSecondKeystroke.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - handleSecondKey(); - updateCurrentKeyStrokeInfo(); - - /** TODO[anton]???? */ - if (myEnableSecondKeystroke.isSelected()) { - mySecondStrokePanel.getShortcutTextField().requestFocus(); - } - else { - myFirstStrokePanel.getShortcutTextField().requestFocus(); - } - } - }); - return panel; + @Override + public JComponent getPreferredFocusedComponent() { + return myPreferredFocusedComponent; } - public JComponent getPreferredFocusedComponent(){ - return IdeFocusTraversalPolicy.getPreferredFocusedComponent(myFirstStrokePanel); + @Override + KeyboardShortcut toShortcut(Object value) { + return value instanceof KeyboardShortcut ? (KeyboardShortcut)value : null; } - public void setData(Keymap keymap, KeyboardShortcut shortcut) { - myKeymap = keymap; - myEnableSecondKeystroke.setSelected(false); - if (shortcut != null) { - myFirstStrokePanel.getShortcutTextField().setKeyStroke(shortcut.getFirstKeyStroke()); - if (shortcut.getSecondKeyStroke() != null) { - myEnableSecondKeystroke.setSelected(true); - mySecondStrokePanel.getShortcutTextField().setKeyStroke(shortcut.getSecondKeyStroke()); - } - } - handleSecondKey(); - updateCurrentKeyStrokeInfo(); + @Override + Collection getConflicts(KeyboardShortcut shortcut, String actionId, Keymap keymap) { + return keymap.getConflicts(actionId, shortcut).keySet(); } - private void updateCurrentKeyStrokeInfo() { - if (myConflictInfoArea == null || myKeystrokePreview == null){ - return; - } - - myConflictInfoArea.setText(null); - myKeystrokePreview.setText(" "); - - if (myKeymap == null){ - return; - } - - KeyboardShortcut keyboardShortcut = getKeyboardShortcut(); - if (keyboardShortcut == null){ - return; - } - - String strokeText = getTextByKeyStroke(keyboardShortcut.getFirstKeyStroke()); - String suffixText = getTextByKeyStroke(keyboardShortcut.getSecondKeyStroke()); - if(suffixText != null && suffixText.length() > 0) { - strokeText += ',' + suffixText; - } - myKeystrokePreview.setText(strokeText); - - StringBuilder buffer = new StringBuilder(); - - Map> conflicts = myKeymap.getConflicts(myActionId, keyboardShortcut); - - Set keys = conflicts.keySet(); - String[] actionIds = ArrayUtil.toStringArray(keys); - boolean loaded = true; - for (String actionId : actionIds) { - String actionPath = myMainGroup.getActionQualifiedPath(actionId); - if (actionPath == null) { - loaded = false; - } - if (buffer.length() > 1) { - buffer.append('\n'); - } - buffer.append('['); - buffer.append(actionPath != null ? actionPath : actionId); - buffer.append(']'); - } - - if (buffer.length() == 0) { - myConflictInfoArea.setForeground(UIUtil.getTextAreaForeground()); - myConflictInfoArea.setText(KeyMapBundle.message("no.conflict.info.message")); - } - else { - myConflictInfoArea.setForeground(JBColor.RED); - if (loaded) { - myConflictInfoArea.setText(KeyMapBundle.message("assigned.to.info.message", buffer.toString())); - } - else { - myConflictInfoArea.setText("Assigned to " + buffer.toString() + " which is now not loaded but may be loaded later"); - } - } - } - - private void handleSecondKey() { - mySecondStrokePanel.setEnabled(myEnableSecondKeystroke.isSelected()); - } - - @Nullable - public KeyboardShortcut getKeyboardShortcut() { - KeyStroke firstStroke = myFirstStrokePanel.getKeyStroke(); - return firstStroke == null ? null : new KeyboardShortcut(firstStroke, myEnableSecondKeystroke.isSelected() ? mySecondStrokePanel.getKeyStroke() : null); - } - - static String getTextByKeyStroke(KeyStroke keyStroke) { - if(keyStroke == null) { - return ""; - } - return KeymapUtil.getKeystrokeText(keyStroke); - } - - protected void doHelpAction() { - HelpManager.getInstance().invokeHelp("preferences.keymap.shortcut"); - } - - private class StrokePanel extends JPanel { - private final ShortcutTextField myShortcutTextField; - - public StrokePanel(String borderText) { - setLayout(new BorderLayout()); - setBorder(IdeBorderFactory.createTitledBorder(borderText, false)); - - myShortcutTextField = new ShortcutTextField(){ - protected void updateCurrentKeyStrokeInfo() { - KeyboardShortcutDialog.this.updateCurrentKeyStrokeInfo(); - } - }; - add(myShortcutTextField); - } - - public ShortcutTextField getShortcutTextField() { - return myShortcutTextField; - } - - public void setEnabled(boolean state) { - myShortcutTextField.setEnabled(state); - repaint(); - } - - public KeyStroke getKeyStroke() { - return myShortcutTextField.getKeyStroke(); - } + @Override + String getActionPath(String actionId) { + String actionPath = super.getActionPath(actionId); + return actionPath != null ? actionPath : actionId; } } diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeyboardShortcutPanel.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeyboardShortcutPanel.java index 163b3975ca3a..982689937329 100644 --- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeyboardShortcutPanel.java +++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeyboardShortcutPanel.java @@ -16,7 +16,6 @@ package com.intellij.openapi.keymap.impl.ui; import com.intellij.openapi.actionSystem.KeyboardShortcut; -import com.intellij.openapi.actionSystem.Shortcut; import java.awt.LayoutManager; import java.awt.event.ItemEvent; @@ -24,19 +23,16 @@ import java.awt.event.ItemListener; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import javax.swing.JCheckBox; -import javax.swing.JPanel; import javax.swing.KeyStroke; /** * @author Sergey.Malenkov */ -final class KeyboardShortcutPanel extends JPanel { +final class KeyboardShortcutPanel extends ShortcutPanel { final ShortcutTextField myFirstStroke = new ShortcutTextField(); final ShortcutTextField mySecondStroke = new ShortcutTextField(); final JCheckBox mySecondStrokeEnable = new JCheckBox(); - private KeyboardShortcut myShortcut; - private final ItemListener myItemListener = new ItemListener() { @Override public void itemStateChanged(ItemEvent event) { @@ -50,37 +46,35 @@ final class KeyboardShortcutPanel extends JPanel { private final PropertyChangeListener myPropertyListener = new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent event) { - setShortcut(newShortcut()); - if (null == myFirstStroke.getKeyStroke()) { - myFirstStroke.requestFocus(); + if (KeyboardShortcutPanel.this != event.getSource()) { + setShortcut(newShortcut()); + if (null == myFirstStroke.getKeyStroke()) { + myFirstStroke.requestFocus(); + } + else if (null == mySecondStroke.getKeyStroke() && mySecondStrokeEnable.isSelected()) { + mySecondStroke.requestFocus(); + } } - else if (null == mySecondStroke.getKeyStroke() && mySecondStrokeEnable.isSelected()) { - mySecondStroke.requestFocus(); + else if (event.getNewValue() instanceof KeyboardShortcut) { + KeyboardShortcut shortcut = (KeyboardShortcut)event.getNewValue(); + myFirstStroke.setKeyStroke(shortcut.getFirstKeyStroke()); + mySecondStroke.setKeyStroke(shortcut.getSecondKeyStroke()); + } + else { + myFirstStroke.setKeyStroke(null); + mySecondStroke.setKeyStroke(null); } } }; KeyboardShortcutPanel(LayoutManager layout) { super(layout); + addPropertyChangeListener("shortcut", myPropertyListener); myFirstStroke.addPropertyChangeListener("keyStroke", myPropertyListener); mySecondStroke.addPropertyChangeListener("keyStroke", myPropertyListener); mySecondStrokeEnable.addItemListener(myItemListener); } - KeyboardShortcut getShortcut() { - return myShortcut; - } - - void setShortcut(KeyboardShortcut shortcut) { - Shortcut old = myShortcut; - if (old == null || !old.equals(shortcut)) { - myShortcut = shortcut; - myFirstStroke.setKeyStroke(shortcut == null ? null : shortcut.getFirstKeyStroke()); - mySecondStroke.setKeyStroke(shortcut == null ? null : shortcut.getSecondKeyStroke()); - firePropertyChange("shortcut", old, shortcut); - } - } - private KeyboardShortcut newShortcut() { KeyStroke key = myFirstStroke.getKeyStroke(); return key == null ? null : new KeyboardShortcut(key, !mySecondStrokeEnable.isSelected() ? null : mySecondStroke.getKeyStroke()); diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapPanel.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapPanel.java index eea7a96dab05..3083d4f6508b 100644 --- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapPanel.java +++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapPanel.java @@ -36,7 +36,6 @@ import com.intellij.openapi.options.Configurable; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.options.SearchableConfigurable; import com.intellij.openapi.project.DumbAwareAction; -import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.ui.popup.ListPopup; @@ -479,13 +478,8 @@ public class KeymapPanel extends JPanel implements SearchableConfigurable, Confi @NotNull Keymap keymap, @NotNull Component parent, @NotNull QuickList[] quickLists) { - KeyboardShortcutDialog dialog = new KeyboardShortcutDialog(parent, actionId, quickLists); - dialog.setData(keymap, shortcut instanceof KeyboardShortcut ? (KeyboardShortcut)shortcut : null); - if (!dialog.showAndGet()) { - return; - } - - KeyboardShortcut keyboardShortcut = dialog.getKeyboardShortcut(); + KeyboardShortcutDialog dialog = new KeyboardShortcutDialog(parent); + KeyboardShortcut keyboardShortcut = dialog.showAndGet(shortcut, actionId, keymap, quickLists); if (keyboardShortcut == null) { return; } @@ -535,22 +529,8 @@ public class KeymapPanel extends JPanel implements SearchableConfigurable, Confi Keymap keymap = createKeymapCopyIfNeeded(); - MouseShortcut mouseShortcut = shortcut instanceof MouseShortcut ? (MouseShortcut)shortcut : null; - Project project = CommonDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext(this)); - MouseShortcutDialog dialog = new MouseShortcutDialog( - this, - mouseShortcut, - keymap, - actionId, - ActionsTreeUtil.createMainGroup(project, keymap, myQuickLists, null, true, null), - restrictions - ); - if (!dialog.showAndGet()) { - return; - } - - mouseShortcut = dialog.getMouseShortcut(); - + MouseShortcutDialog dialog = new MouseShortcutDialog(this, restrictions.allowMouseDoubleClick); + MouseShortcut mouseShortcut = dialog.showAndGet(shortcut, actionId, keymap, myQuickLists); if (mouseShortcut == null) { return; } diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/MouseShortcutDialog.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/MouseShortcutDialog.java index 2de4bdf5f3eb..fe0e21de9a4c 100644 --- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/MouseShortcutDialog.java +++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/MouseShortcutDialog.java @@ -17,275 +17,68 @@ package com.intellij.openapi.keymap.impl.ui; import com.intellij.icons.AllIcons; import com.intellij.openapi.actionSystem.MouseShortcut; -import com.intellij.openapi.actionSystem.Shortcut; import com.intellij.openapi.keymap.KeyMapBundle; import com.intellij.openapi.keymap.Keymap; import com.intellij.openapi.keymap.KeymapUtil; -import com.intellij.openapi.keymap.impl.ShortcutRestrictions; -import com.intellij.openapi.ui.DialogWrapper; -import com.intellij.ui.IdeBorderFactory; -import com.intellij.ui.JBColor; -import com.intellij.ui.ScrollPaneFactory; import com.intellij.util.ui.JBUI; import com.intellij.util.ui.UIUtil; -import org.intellij.lang.annotations.JdkConstants; -import org.jetbrains.annotations.NotNull; -import javax.swing.*; -import java.awt.*; -import java.awt.event.*; +import java.awt.BorderLayout; +import java.awt.Component; +import java.util.Arrays; +import java.util.Collection; +import javax.swing.BorderFactory; +import javax.swing.JLabel; +import javax.swing.SwingConstants; /** * @author Vladimir Kondratyev + * @author Sergey.Malenkov */ -class MouseShortcutDialog extends DialogWrapper{ - private final Keymap myKeymap; - private final String myActionId; - private final Group myMainGroup; +final class MouseShortcutDialog extends ShortcutDialog { + private final JLabel myText = new JLabel("", SwingConstants.CENTER); - private final JRadioButton myRbSingleClick; - private final JRadioButton myRbDoubleClick; - private final JLabel myLblPreview; - private final JLabel myClickPad; - private final JTextArea myTarConflicts; + MouseShortcutDialog(Component component, boolean allowDoubleClick) { + super(component, "mouse.shortcut.dialog.title", new MouseShortcutPanel(allowDoubleClick)); - private final MouseShortcutConsumer myShortcutConsumer; - - private int myButton; - @JdkConstants.InputEventMask private int myModifiers; - - /** - * @param shortcut dialog will be initialized with this shortcut. It can be null - * if dialog is used to create new mouse shortcut. - */ - public MouseShortcutDialog( - JComponent parentComponent, - MouseShortcut shortcut, - @NotNull Keymap keymap, - @NotNull String actiondId, - @NotNull Group mainGroup, - @NotNull ShortcutRestrictions restrictions - ){ - super(parentComponent,true); - setTitle(KeyMapBundle.message("mouse.shortcut.dialog.title")); - - myKeymap=keymap; - myActionId=actiondId; - myMainGroup=mainGroup; - - myRbSingleClick=new JRadioButton(KeyMapBundle.message("mouse.shortcut.dialog.single.click.radio")); - myRbDoubleClick=new JRadioButton(KeyMapBundle.message("mouse.shortcut.dialog.double.click.radio")); - ButtonGroup buttonGroup=new ButtonGroup(); - buttonGroup.add(myRbSingleClick); - buttonGroup.add(myRbDoubleClick); - - myLblPreview=new JLabel(" "); - - myTarConflicts=new JTextArea(); - myTarConflicts.setFocusable(false); - myTarConflicts.setEditable(false); - myTarConflicts.setBackground(UIUtil.getPanelBackground()); - myTarConflicts.setLineWrap(true); - myTarConflicts.setWrapStyleWord(true); - - if(shortcut!=null){ - if(shortcut.getClickCount()==1){ - myRbSingleClick.setSelected(true); - }else{ - myRbDoubleClick.setSelected(true); - } - myButton=shortcut.getButton(); - myModifiers=shortcut.getModifiers(); - }else{ - myRbSingleClick.setSelected(true); - myButton=-1; - myModifiers=-1; - } - - myRbDoubleClick.setEnabled(restrictions.allowMouseDoubleClick); - - updatePreviewAndConflicts(); - - myClickPad = new JLabel( - KeyMapBundle.message("mouse.shortcut.label"), - AllIcons.General.Mouse, SwingConstants.LEADING - ); - myShortcutConsumer = new MouseShortcutConsumer(shortcut) { - @Override - public void consume(MouseShortcut shortcut) { - myButton = shortcut.getButton(); - myModifiers = shortcut.getModifiers(); - updatePreviewAndConflicts(); - } - }; - myClickPad.addHierarchyListener(myShortcutConsumer); + myShortcutPanel.add(BorderLayout.NORTH, new JLabel(AllIcons.General.Mouse, SwingConstants.CENTER)); + myShortcutPanel.add(BorderLayout.CENTER, myText); + myShortcutPanel.setBorder(BorderFactory.createCompoundBorder( + JBUI.Borders.customLine(MouseShortcutPanel.BORDER, 1, 0, 1, 0), + JBUI.Borders.empty(20) + )); init(); } - /** - * @return created/edited shortcut. Returns null if shortcut is invalid. - */ - public MouseShortcut getMouseShortcut(){ - if (myButton > 3 && myButton != MouseShortcut.BUTTON_WHEEL_UP && myButton != MouseShortcut.BUTTON_WHEEL_DOWN && getClickCount() == 2) { - return null; - } - - if(myButton!=-1 && myModifiers!=-1){ - return new MouseShortcut(myButton,myModifiers,getClickCount()); - }else{ - return null; - } - } - @Override protected String getHelpId() { return "preferences.mouse.shortcut"; } - protected JComponent createCenterPanel(){ - JPanel panel=new JPanel(new GridBagLayout()); - - // Single/Double click - - JPanel clickCountPanel=new JPanel(new GridBagLayout()); - clickCountPanel.setBorder(IdeBorderFactory.createTitledBorder( - KeyMapBundle.message("mouse.shortcut.dialog.click.count.border"), true)); - panel.add( - clickCountPanel, - new GridBagConstraints(0,0,1,1,1,0,GridBagConstraints.CENTER,GridBagConstraints.HORIZONTAL,new Insets(0,0,0,0),0,0) - ); - clickCountPanel.add( - myRbSingleClick, - new GridBagConstraints(0,0,1,1,1,0,GridBagConstraints.WEST,GridBagConstraints.NONE,new Insets(0,0,0,10),0,0) - ); - clickCountPanel.add( - myRbDoubleClick, - new GridBagConstraints(1,0,1,1,1,0,GridBagConstraints.EAST,GridBagConstraints.NONE,new Insets(0,0,0,0),0,0) - ); - - ActionListener listener=new ActionListener(){ - public void actionPerformed(ActionEvent e){ - updatePreviewAndConflicts(); - } - }; - myRbSingleClick.addActionListener(listener); - myRbDoubleClick.addActionListener(listener); - - // Click pad - - panel.add( - myClickPad, - new GridBagConstraints(0,1,1,1,1,0,GridBagConstraints.CENTER,GridBagConstraints.BOTH,new Insets(0,0,4,0),0,0) - ); - myClickPad.setBorder(BorderFactory.createCompoundBorder( - IdeBorderFactory.createTitledBorder(KeyMapBundle.message("mouse.shortcut.dialog.click.pad.border"), true), - JBUI.Borders.empty(20, 0, 20, 20))); - - // Shortcut preview - - JPanel previewPanel=new JPanel(new GridBagLayout()); - previewPanel.setBorder(IdeBorderFactory.createTitledBorder( - KeyMapBundle.message("mouse.shortcut.dialog.shortcut.preview.border"), true)); - panel.add( - previewPanel, - new GridBagConstraints(0,2,1,1,1,0,GridBagConstraints.CENTER,GridBagConstraints.BOTH,new Insets(0,0,4,0),0,0) - ); - previewPanel.add( - myLblPreview, - new GridBagConstraints(0,0,1,1,1,1,GridBagConstraints.CENTER,GridBagConstraints.BOTH,new Insets(2,2,2,2),0,0) - ); - - // Conflicts panel - - JPanel conflictsPanel=new JPanel(new GridBagLayout()); - conflictsPanel.setBorder(IdeBorderFactory.createTitledBorder( - KeyMapBundle.message("mouse.shortcut.dialog.conflicts.border"), true)); - panel.add( - conflictsPanel, - new GridBagConstraints(0,3,1,1,1,1,GridBagConstraints.CENTER,GridBagConstraints.BOTH,new Insets(0,0,0,0),0,0) - ); - myTarConflicts.setPreferredSize(JBUI.size(260,60)); - JScrollPane scrollPane= ScrollPaneFactory.createScrollPane(myTarConflicts); - scrollPane.setBorder(null); - conflictsPanel.add( - scrollPane, - new GridBagConstraints(0,0,1,1,1,1,GridBagConstraints.CENTER,GridBagConstraints.BOTH,new Insets(0,0,0,0),0,0) - ); - - return panel; + @Override + MouseShortcut toShortcut(Object value) { + return value instanceof MouseShortcut ? (MouseShortcut)value : null; } - private int getClickCount() { - return myRbSingleClick.isSelected() ? 1 : 2; - } - /** - * Updates all UI controls - */ - private void updatePreviewAndConflicts(){ - if(myButton==-1||myModifiers==-1){ - return; - } - - myTarConflicts.setText(null); - - // Set text into preview area - - // empty string should have same height - myLblPreview.setText(KeymapUtil.getMouseShortcutText(myButton,myModifiers,getClickCount()) + " "); - - // Detect conflicts - - final MouseShortcut mouseShortcut=new MouseShortcut(myButton,myModifiers,getClickCount()); - - if (myButton > 3 && getClickCount() == 2) { - myTarConflicts.setForeground(JBColor.RED); - myTarConflicts.setText(KeyMapBundle.message("mouse.shortcut.dialog.side.buttons.with.double.click", myButton)); - return; - } - - StringBuilder buffer = new StringBuilder(); - String[] actionIds = myKeymap.getActionIds(mouseShortcut); - for (String actionId : actionIds) { - if (actionId.equals(myActionId)) { - continue; - } - - String actionPath = myMainGroup.getActionQualifiedPath(actionId); - // actionPath == null for editor actions having corresponding $-actions - if (actionPath == null) { - continue; - } - - Shortcut[] shortcuts = myKeymap.getShortcuts(actionId); - for (Shortcut shortcut1 : shortcuts) { - if (!(shortcut1 instanceof MouseShortcut)) { - continue; - } - - MouseShortcut shortcut = (MouseShortcut)shortcut1; - - if (shortcut.getButton() != mouseShortcut.getButton() || shortcut.getModifiers() != mouseShortcut.getModifiers()) { - continue; - } - - if (buffer.length() > 1) { - buffer.append('\n'); - } - buffer.append('['); - buffer.append(actionPath); - buffer.append(']'); - break; - } - } - - if (buffer.length() == 0) { - myTarConflicts.setForeground(UIUtil.getTextAreaForeground()); - myTarConflicts.setText(KeyMapBundle.message("mouse.shortcut.dialog.no.conflicts.area")); + @Override + void setShortcut(MouseShortcut shortcut) { + super.setShortcut(shortcut); + if (shortcut == null) { + myText.setForeground(MouseShortcutPanel.FOREGROUND); + myText.setText(KeyMapBundle.message("dialog.mouse.pad.default.text")); } else { - myTarConflicts.setForeground(JBColor.RED); - myTarConflicts.setText(KeyMapBundle.message("mouse.shortcut.dialog.assigned.to.area", buffer.toString())); + myText.setForeground(UIUtil.getLabelForeground()); + myText.setText(KeyMapBundle.message("dialog.mouse.pad.shortcut.text", KeymapUtil.getMouseShortcutText( + shortcut.getButton(), + shortcut.getModifiers(), + shortcut.getClickCount()))); } } + + @Override + Collection getConflicts(MouseShortcut shortcut, String actionId, Keymap keymap) { + return Arrays.asList(keymap.getActionIds(shortcut)); + } } diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/MouseShortcutPanel.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/MouseShortcutPanel.java index 0e0e6eeeebd2..a407bb780f65 100644 --- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/MouseShortcutPanel.java +++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/MouseShortcutPanel.java @@ -22,18 +22,16 @@ import java.awt.BorderLayout; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseWheelEvent; -import javax.swing.JPanel; /** * @author Sergey.Malenkov */ -final class MouseShortcutPanel extends JPanel { +final class MouseShortcutPanel extends ShortcutPanel { static final JBColor FOREGROUND = new JBColor(0x8C8C8C, 0x8C8C8C); static final JBColor BACKGROUND = new JBColor(0xF5F5F5, 0x4B4F52); static final JBColor BORDER = new JBColor(0xDEDEDE, 0x383B3D); - private MouseShortcut myShortcut; - + private final int myClickCount; private final MouseAdapter myMouseListener = new MouseAdapter() { @Override public void mouseWheelMoved(MouseWheelEvent event) { @@ -46,35 +44,26 @@ final class MouseShortcutPanel extends JPanel { int button = MouseShortcut.getButton(event); int clickCount = event instanceof MouseWheelEvent ? 1 : event.getClickCount(); - if (0 <= button && clickCount < 3) { + if (0 <= button && clickCount <= myClickCount) { int modifiers = event.getModifiersEx(); - if (myShortcut == null - || button != myShortcut.getButton() - || modifiers != myShortcut.getModifiers() - || clickCount != myShortcut.getClickCount()) { - setShortcut(new MouseShortcut(button, modifiers, clickCount)); - } + setShortcut(new MouseShortcut(button, modifiers, clickCount)); } } }; - MouseShortcutPanel() { + MouseShortcutPanel(boolean allowDoubleClick) { super(new BorderLayout()); + myClickCount = allowDoubleClick ? 2 : 1; addMouseListener(myMouseListener); addMouseWheelListener(myMouseListener); setBackground(BACKGROUND); setOpaque(true); } - MouseShortcut getShortcut() { - return myShortcut; - } - void setShortcut(MouseShortcut shortcut) { - MouseShortcut old = myShortcut; + MouseShortcut old = getShortcut(); if (old != null || shortcut != null) { - myShortcut = shortcut; - firePropertyChange("shortcut", old, shortcut); + super.setShortcut(shortcut); } } } diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ShortcutDialog.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ShortcutDialog.java new file mode 100644 index 000000000000..c3ade8b94c5e --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ShortcutDialog.java @@ -0,0 +1,185 @@ +/* + * 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 com.intellij.openapi.keymap.impl.ui; + +import com.intellij.icons.AllIcons; +import com.intellij.ide.DataManager; +import com.intellij.openapi.actionSystem.CommonDataKeys; +import com.intellij.openapi.actionSystem.Shortcut; +import com.intellij.openapi.actionSystem.ex.QuickList; +import com.intellij.openapi.keymap.KeyMapBundle; +import com.intellij.openapi.keymap.Keymap; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.DialogWrapper; +import com.intellij.ui.ScrollPaneFactory; +import com.intellij.ui.SimpleColoredComponent; +import com.intellij.ui.SimpleTextAttributes; +import com.intellij.ui.components.GradientViewport; +import com.intellij.ui.components.JBPanel; +import com.intellij.ui.components.panels.VerticalLayout; +import com.intellij.util.ui.ButtonlessScrollBarUI; +import com.intellij.util.ui.JBUI; +import org.jetbrains.annotations.Nullable; + +import java.awt.BorderLayout; +import java.awt.Component; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.util.Collection; +import javax.swing.JComponent; +import javax.swing.JLabel; +import javax.swing.JScrollPane; +import javax.swing.ScrollPaneConstants; +import javax.swing.SwingConstants; +import javax.swing.border.Border; + +/** + * @author Sergey.Malenkov + */ +abstract class ShortcutDialog extends DialogWrapper { + private final SimpleColoredComponent myAction = new SimpleColoredComponent(); + private final JBPanel myConflictsContainer = new JBPanel(new VerticalLayout(0)); + private final JBPanel myConflictsPanel = new JBPanel(new BorderLayout()) + .withBorder(JBUI.Borders.empty(5, 10, 0, 10)) + .withPreferredHeight(64) + .withMinimumHeight(64); + + protected final ShortcutPanel myShortcutPanel; + private final Project myProject; + private String myActionId; + private Keymap myKeymap; + private Group myGroup; + + ShortcutDialog(Component parent, String title, ShortcutPanel panel) { + super(parent, true); + myShortcutPanel = panel; + myProject = CommonDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext(parent)); + setTitle(KeyMapBundle.message(title)); + } + + String getActionPath(String actionId) { + return myGroup == null ? null : myGroup.getActionQualifiedPath(actionId); + } + + abstract Collection getConflicts(T shortcut, String actionId, Keymap keymap); + + abstract T toShortcut(Object value); + + void setShortcut(T shortcut) { + if (!equal(shortcut, myShortcutPanel.getShortcut())) { + myShortcutPanel.setShortcut(shortcut); + } + myConflictsContainer.removeAll(); + if (shortcut != null) { + for (String id : getConflicts(shortcut, myActionId, myKeymap)) { + String path = id.equals(myActionId) ? null : getActionPath(id); + if (path != null) { + SimpleColoredComponent component = new SimpleColoredComponent(); + fill(component, id, path); + myConflictsContainer.add(VerticalLayout.TOP, component); + } + } + myConflictsPanel.revalidate(); + } + myConflictsPanel.setVisible(0 < myConflictsContainer.getComponentCount()); + } + + T showAndGet(Shortcut shortcut, String id, Keymap keymap, QuickList... lists) { + myActionId = id; + myKeymap = keymap; + myGroup = ActionsTreeUtil.createMainGroup(myProject, keymap, lists, null, false, null); + fill(myAction, id, getActionPath(id)); + setShortcut(toShortcut(shortcut)); + return showAndGet() ? myShortcutPanel.getShortcut() : null; + } + + @Nullable + @Override + protected Border createContentPaneBorder() { + return JBUI.Borders.empty(); + } + + @Nullable + @Override + protected JComponent createSouthPanel() { + JComponent panel = super.createSouthPanel(); + if (panel != null) { + panel.setBorder(JBUI.Borders.empty(8, 12)); + } + return panel; + } + + @Nullable + @Override + protected JComponent createNorthPanel() { + myAction.setIpad(JBUI.insets(10, 10, 5, 10)); + myShortcutPanel.addPropertyChangeListener("shortcut", new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent event) { + setShortcut(toShortcut(event.getNewValue())); + } + }); + JBPanel result = new JBPanel(new BorderLayout()).withPreferredWidth(300).withMinimumWidth(200); + result.add(BorderLayout.NORTH, myAction); + result.add(BorderLayout.SOUTH, myShortcutPanel); + return result; + } + + @Override + protected JComponent createCenterPanel() { + JLabel icon = new JLabel(AllIcons.General.BalloonWarning); + icon.setVerticalAlignment(SwingConstants.TOP); + + JLabel label = new JLabel(KeyMapBundle.message("dialog.conflicts.text")); + label.setBorder(JBUI.Borders.emptyLeft(2)); + + JScrollPane scroll = ScrollPaneFactory.createScrollPane(null, true); + scroll.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); + scroll.setViewport(new GradientViewport(myConflictsContainer, JBUI.insets(5), false)); + scroll.getVerticalScrollBar().setUI(ButtonlessScrollBarUI.createTransparent()); + scroll.getVerticalScrollBar().setUnitIncrement(JBUI.scale(10)); + + JBPanel panel = new JBPanel(new BorderLayout()); + panel.add(BorderLayout.NORTH, label); + panel.add(BorderLayout.CENTER, scroll); + + myConflictsPanel.add(BorderLayout.WEST, icon); + myConflictsPanel.add(BorderLayout.CENTER, panel); + myConflictsContainer.setOpaque(false); + return myConflictsPanel; + } + + private static boolean equal(Shortcut newShortcut, Shortcut oldShortcut) { + return newShortcut == null ? oldShortcut == null : newShortcut.equals(oldShortcut); + } + + private static void fill(SimpleColoredComponent component, String id, String path) { + if (path == null) { + component.append(id, SimpleTextAttributes.REGULAR_ITALIC_ATTRIBUTES); + } + else { + int index = path.lastIndexOf(" | "); + if (index < 0) { + component.append(path, SimpleTextAttributes.REGULAR_ATTRIBUTES); + } + else { + component.append(path.substring(index + 3), SimpleTextAttributes.REGULAR_ATTRIBUTES); + component.append(" in ", SimpleTextAttributes.GRAYED_ATTRIBUTES); + component.append(path.substring(0, index), SimpleTextAttributes.GRAYED_ATTRIBUTES); + } + } + } +} diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ShortcutFilteringPanel.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ShortcutFilteringPanel.java index 6e3b199eade5..ccedfc13be04 100644 --- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ShortcutFilteringPanel.java +++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ShortcutFilteringPanel.java @@ -40,7 +40,7 @@ import javax.swing.event.ChangeListener; */ final class ShortcutFilteringPanel extends JPanel { final KeyboardShortcutPanel myKeyboardPanel = new KeyboardShortcutPanel(new VerticalLayout(JBUI.scale(2))); - final MouseShortcutPanel myMousePanel = new MouseShortcutPanel(); + final MouseShortcutPanel myMousePanel = new MouseShortcutPanel(true); private Shortcut myShortcut; private JBPopup myPopup; diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ShortcutPanel.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ShortcutPanel.java new file mode 100644 index 000000000000..1cad3154f95b --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ShortcutPanel.java @@ -0,0 +1,42 @@ +/* + * 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 com.intellij.openapi.keymap.impl.ui; + +import com.intellij.openapi.actionSystem.Shortcut; + +import java.awt.LayoutManager; +import javax.swing.JPanel; + +/** + * @author Sergey.Malenkov + */ +class ShortcutPanel extends JPanel { + private T myShortcut; + + ShortcutPanel(LayoutManager layout) { + super(layout); + } + + T getShortcut() { + return myShortcut; + } + + void setShortcut(T shortcut) { + T old = myShortcut; + myShortcut = shortcut; + firePropertyChange("shortcut", old, shortcut); + } +} diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ShortcutTextField.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ShortcutTextField.java index b35a096fd51d..fa7f6787ac3f 100644 --- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ShortcutTextField.java +++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ShortcutTextField.java @@ -31,10 +31,10 @@ import javax.swing.text.DefaultCaret; import java.awt.*; import java.awt.event.KeyEvent; -public class ShortcutTextField extends JTextField { +public final class ShortcutTextField extends JTextField { private KeyStroke myKeyStroke; - public ShortcutTextField() { + ShortcutTextField() { enableEvents(AWTEvent.KEY_EVENT_MASK); setFocusTraversalKeysEnabled(false); putClientProperty("JTextField.variant", "search"); @@ -62,21 +62,17 @@ public class ShortcutTextField extends JTextField { } } - public void setKeyStroke(KeyStroke keyStroke) { + void setKeyStroke(KeyStroke keyStroke) { KeyStroke old = myKeyStroke; if (old != null || keyStroke != null) { myKeyStroke = keyStroke; super.setText(KeymapUtil.getKeystrokeText(keyStroke)); setCaretPosition(0); - updateCurrentKeyStrokeInfo(); firePropertyChange("keyStroke", old, keyStroke); } } - protected void updateCurrentKeyStrokeInfo() { - } - - public KeyStroke getKeyStroke() { + KeyStroke getKeyStroke() { return myKeyStroke; } diff --git a/platform/platform-resources-en/src/messages/KeyMapBundle.properties b/platform/platform-resources-en/src/messages/KeyMapBundle.properties index 29986a28f522..010c44825ea7 100644 --- a/platform/platform-resources-en/src/messages/KeyMapBundle.properties +++ b/platform/platform-resources-en/src/messages/KeyMapBundle.properties @@ -96,6 +96,11 @@ mouse.wheel.rotate.down.shortcut.text={0}Wheel down configuration.all.keymaps.should.have.non.empty.names.error.message=All keymaps should have non empty names configuration.all.keymaps.should.have.unique.names.error.message=All keymaps should have unique names +dialog.enable.second.stroke.checkbox=Second stroke: +dialog.mouse.pad.default.text=
Enter a shortcut here:
single or double-click, scroll the wheel,
modify with Ctrl, Alt and Shift +dialog.mouse.pad.shortcut.text=

{0}

+dialog.conflicts.text=Already assigned to: + filter.clear.action.text=Clear Filtering filter.settings.popup.title=Find Shortcut filter.enable.second.stroke.checkbox=Second stroke diff --git a/platform/util/src/com/intellij/ui/components/JBPanel.java b/platform/util/src/com/intellij/ui/components/JBPanel.java index b265c961e496..fb0101033965 100644 --- a/platform/util/src/com/intellij/ui/components/JBPanel.java +++ b/platform/util/src/com/intellij/ui/components/JBPanel.java @@ -16,6 +16,7 @@ package com.intellij.ui.components; import com.intellij.util.ui.JBFont; +import com.intellij.util.ui.JBUI; import com.intellij.util.ui.components.JBComponent; import javax.swing.*; @@ -27,6 +28,12 @@ import java.awt.*; */ @SuppressWarnings("unchecked") public class JBPanel extends JPanel implements JBComponent { + private Integer myPreferredWidth; + private Integer myPreferredHeight; + private Integer myMaximumWidth; + private Integer myMaximumHeight; + private Integer myMinimumWidth; + private Integer myMinimumHeight; public JBPanel(LayoutManager layout, boolean isDoubleBuffered) { super(layout, isDoubleBuffered); @@ -67,4 +74,57 @@ public class JBPanel extends JPanel implements JBComponent setOpaque(true); return (T)this; } + + public T withPreferredWidth(int width) { + myPreferredWidth = width; + return (T)this; + } + + public T withPreferredHeight(int height) { + myPreferredHeight = height; + return (T)this; + } + + public T withMaximumWidth(int width) { + myMaximumWidth = width; + return (T)this; + } + + public T withMaximumHeight(int height) { + myMaximumHeight = height; + return (T)this; + } + + public T withMinimumWidth(int width) { + myMinimumWidth = width; + return (T)this; + } + + public T withMinimumHeight(int height) { + myMinimumHeight = height; + return (T)this; + } + + @Override + public Dimension getPreferredSize() { + return getSize(super.getPreferredSize(), myPreferredWidth, myPreferredHeight, isPreferredSizeSet()); + } + + @Override + public Dimension getMaximumSize() { + return getSize(super.getMaximumSize(), myMaximumWidth, myMaximumHeight, isMaximumSizeSet()); + } + + @Override + public Dimension getMinimumSize() { + return getSize(super.getMinimumSize(), myMinimumWidth, myMinimumHeight, isMinimumSizeSet()); + } + + private static Dimension getSize(Dimension size, Integer width, Integer height, boolean isSet) { + if (!isSet && size != null) { + if (width != null) size.width = JBUI.scale(width); + if (height != null) size.height = JBUI.scale(height); + } + return size; + } } From 8d3d05df8c41602c7cc15a97d78a598159eaa144 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Fri, 6 Nov 2015 13:48:29 +0300 Subject: [PATCH 032/124] Fix typo in log message --- .../com/jetbrains/python/validation/Pep8ExternalAnnotator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/src/com/jetbrains/python/validation/Pep8ExternalAnnotator.java b/python/src/com/jetbrains/python/validation/Pep8ExternalAnnotator.java index 646b7b8fab3e..3e7cc9f2bc63 100644 --- a/python/src/com/jetbrains/python/validation/Pep8ExternalAnnotator.java +++ b/python/src/com/jetbrains/python/validation/Pep8ExternalAnnotator.java @@ -171,7 +171,7 @@ public class Pep8ExternalAnnotator extends ExternalAnnotator allSdks = PythonSdkType.getAllSdks(); Collections.sort(allSdks, PreferredSdkComparator.INSTANCE); for (Sdk sdk : allSdks) { From 7ad9c6f405f65f4eba91ee66b43213b43761486f Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Fri, 6 Nov 2015 13:55:57 +0300 Subject: [PATCH 033/124] PY-17470 PY-17529 Don't attempt to remove quotes from already unescaped docstring Because PyStringLiteralExpressionImpl#getNodeTextRange used for that strips at least first character unconditionally, user sees corrupted docstring description without the first letter. --- .../docstrings/PyStructuredDocstringFormatter.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/python/src/com/jetbrains/python/documentation/docstrings/PyStructuredDocstringFormatter.java b/python/src/com/jetbrains/python/documentation/docstrings/PyStructuredDocstringFormatter.java index 975b936904f0..645dbe9aee03 100644 --- a/python/src/com/jetbrains/python/documentation/docstrings/PyStructuredDocstringFormatter.java +++ b/python/src/com/jetbrains/python/documentation/docstrings/PyStructuredDocstringFormatter.java @@ -71,20 +71,20 @@ public class PyStructuredDocstringFormatter { final DocStringFormat format = DocStringUtil.guessDocStringFormat(preparedDocstring, element); if (format == DocStringFormat.GOOGLE) { formatter = PythonHelper.GOOGLE_FORMATTER; - structuredDocString = DocStringUtil.parseDocString(DocStringFormat.GOOGLE, preparedDocstring); + structuredDocString = DocStringUtil.parseDocStringContent(DocStringFormat.GOOGLE, preparedDocstring); } else if (format == DocStringFormat.NUMPY) { formatter = PythonHelper.NUMPY_FORMATTER; - structuredDocString = DocStringUtil.parseDocString(DocStringFormat.NUMPY, preparedDocstring); + structuredDocString = DocStringUtil.parseDocStringContent(DocStringFormat.NUMPY, preparedDocstring); } else if (format == DocStringFormat.EPYTEXT) { formatter = PythonHelper.EPYDOC_FORMATTER; - structuredDocString = DocStringUtil.parseDocString(DocStringFormat.EPYTEXT, preparedDocstring); + structuredDocString = DocStringUtil.parseDocStringContent(DocStringFormat.EPYTEXT, preparedDocstring); result.add(formatStructuredDocString(structuredDocString)); } else if (format == DocStringFormat.REST) { formatter = PythonHelper.REST_FORMATTER; - structuredDocString = DocStringUtil.parseDocString(DocStringFormat.REST, preparedDocstring); + structuredDocString = DocStringUtil.parseDocStringContent(DocStringFormat.REST, preparedDocstring); } else { From f56f422545c2e42128c6e7ad8197099f8f20961e Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Fri, 6 Nov 2015 14:35:16 +0300 Subject: [PATCH 034/124] PY-17470 Fix IndexError in rest_formatter.py helper This error occurs when there is no type test after colon in `:type` and `:rtype` declarations. --- python/helpers/rest_formatter.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/python/helpers/rest_formatter.py b/python/helpers/rest_formatter.py index 03fffd93848f..45755976750b 100644 --- a/python/helpers/rest_formatter.py +++ b/python/helpers/rest_formatter.py @@ -133,19 +133,19 @@ class RestHTMLTranslator(_EpydocHTMLTranslator): fields["return"] = n for n in node.children: - if not n.children: + if len(n.children) < 2: continue - child = n.children[0] - rawsource = child.rawsource + field_name, field_body = n.children[0], n.children[1] + rawsource = field_name.rawsource if rawsource.startswith("type "): index = rawsource.index("type ") name = re.sub(r'\\\*', '*', rawsource[index + 5:]) if name in fields: - fields[name].type = n.children[1][0][0] + fields[name].type = field_body[0][0] if field_body.children else '' node.children.remove(n) if rawsource == "rtype": if "return" in fields: - fields["return"].type = n.children[1][0][0] + fields["return"].type = field_body[0][0] if field_body.children else '' node.children.remove(n) HTMLTranslator.visit_field_list(self, node) From 6ae38d8c4086b06b32b9151e31717bd82d0d11df Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Fri, 6 Nov 2015 15:21:59 +0300 Subject: [PATCH 035/124] Unify line separators in documentation for Python keywords It also fixes PyQuickDocTest#testReturnKeyword test on Windows. --- .../jetbrains/python/documentation/PyDocumentationBuilder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/src/com/jetbrains/python/documentation/PyDocumentationBuilder.java b/python/src/com/jetbrains/python/documentation/PyDocumentationBuilder.java index cd61ba75ee97..4cebb5b3e92c 100644 --- a/python/src/com/jetbrains/python/documentation/PyDocumentationBuilder.java +++ b/python/src/com/jetbrains/python/documentation/PyDocumentationBuilder.java @@ -134,7 +134,7 @@ public class PyDocumentationBuilder { final FileReader reader = new FileReader(PythonHelpersLocator.getHelperPath("/tools/python_keywords/" + name)); try { final String text = FileUtil.loadTextAndClose(reader); - myEpilog.addItem(text); + myEpilog.addItem(StringUtil.convertLineSeparators(text, "\n")); } catch (IOException ignored) { } From 5ebfec4ec89730c4b7e11a39282a6a9ee5835a0d Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Fri, 6 Nov 2015 16:19:23 +0300 Subject: [PATCH 036/124] performance test: increased time for hot file indent detection --- .../autodetect/JavaAutoDetectIndentPerformanceTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/java-tests/testSrc/com/intellij/psi/codeStyle/autodetect/JavaAutoDetectIndentPerformanceTest.java b/java/java-tests/testSrc/com/intellij/psi/codeStyle/autodetect/JavaAutoDetectIndentPerformanceTest.java index eabe458396a2..00adb05989c3 100644 --- a/java/java-tests/testSrc/com/intellij/psi/codeStyle/autodetect/JavaAutoDetectIndentPerformanceTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/codeStyle/autodetect/JavaAutoDetectIndentPerformanceTest.java @@ -62,7 +62,7 @@ public class JavaAutoDetectIndentPerformanceTest extends AbstractIndentAutoDetec AbstractIndentAutoDetectionTest.detectIndentOptions(); PlatformTestUtil - .startPerformanceTest("Detecting indent on hot file", 30, AbstractIndentAutoDetectionTest::detectIndentOptions) + .startPerformanceTest("Detecting indent on hot file", 40, AbstractIndentAutoDetectionTest::detectIndentOptions) .cpuBound() .assertTiming(); } From 298ccd6b0a64f82d5d7ab11623e05efc39720f05 Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Fri, 6 Nov 2015 16:22:39 +0300 Subject: [PATCH 037/124] Show only last days recent tests --- .../impl/src/com/intellij/testIntegration/ShowRecentTests.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/java/execution/impl/src/com/intellij/testIntegration/ShowRecentTests.java b/java/execution/impl/src/com/intellij/testIntegration/ShowRecentTests.java index d590c25befb4..4834b82214bb 100644 --- a/java/execution/impl/src/com/intellij/testIntegration/ShowRecentTests.java +++ b/java/execution/impl/src/com/intellij/testIntegration/ShowRecentTests.java @@ -24,6 +24,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.popup.ListPopupStep; import com.intellij.ui.popup.list.ListPopupImpl; import com.intellij.util.PsiNavigateUtil; +import com.intellij.util.Time; import javax.swing.*; import java.awt.event.ActionEvent; @@ -35,7 +36,7 @@ public class ShowRecentTests extends AnAction { private static final int TEST_LIMIT = Integer.MAX_VALUE; private static Date getSinceDate() { - return new Date(0); + return new Date(System.currentTimeMillis() - Time.DAY); } @Override From d4d122d57fd95453c1045a18edabc302dace67b9 Mon Sep 17 00:00:00 2001 From: Denis Fokin Date: Fri, 6 Nov 2015 17:27:08 +0400 Subject: [PATCH 038/124] IDEA-145612 IllegalArgumentException "invalid keyCode" --- .../src/com/intellij/ide/IdeEventQueue.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java b/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java index c7eb78761a36..d8916bc6ce3b 100644 --- a/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java +++ b/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java @@ -483,15 +483,19 @@ public class IdeEventQueue extends EventQueue { modifiers |= InputEvent.ALT_MASK; } + int oldKeyCode = ke.getKeyCode(); + //noinspection MagicConstant - e = new KeyEvent(ke.getComponent(), ke.getID(), ke.getWhen(), modifiers, - ke.getKeyCode(), ke.getKeyChar(), ke.getKeyLocation()); + ke = new KeyEvent(ke.getComponent(), ke.getID(), ke.getWhen(), modifiers, + KeyEvent.VK_UNDEFINED, ke.getKeyChar(), KeyEvent.KEY_LOCATION_UNKNOWN); + + ke.setKeyCode(oldKeyCode); } } } } - return e; + return ke; } private static AWTEvent mapEvent(AWTEvent e) { From 1b5e7e27b7407fe311ac3c0576579afadc9d2ec8 Mon Sep 17 00:00:00 2001 From: nik Date: Fri, 6 Nov 2015 16:56:23 +0300 Subject: [PATCH 039/124] workaround for IDEA-147530: make sure that when a new light module is created it won't take settings from previously saved module --- .../intellij/testFramework/LightProjectDescriptor.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/platform/testFramework/src/com/intellij/testFramework/LightProjectDescriptor.java b/platform/testFramework/src/com/intellij/testFramework/LightProjectDescriptor.java index f0df8f8b9ca9..c84fe76dcea3 100644 --- a/platform/testFramework/src/com/intellij/testFramework/LightProjectDescriptor.java +++ b/platform/testFramework/src/com/intellij/testFramework/LightProjectDescriptor.java @@ -30,6 +30,7 @@ import com.intellij.openapi.roots.ContentIterator; import com.intellij.openapi.roots.ModifiableRootModel; import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; @@ -41,6 +42,7 @@ import com.intellij.util.indexing.IndexableFileSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.io.File; import java.io.IOException; import static com.intellij.openapi.roots.ModuleRootModificationUtil.updateModel; @@ -70,7 +72,13 @@ public class LightProjectDescriptor { return ApplicationManager.getApplication().runWriteAction(new Computable() { @Override public Module compute() { - return ModuleManager.getInstance(project).newModule("light_idea_test_case.iml", getModuleType().getId()); + String moduleFilePath = "light_idea_test_case.iml"; + File imlFile = new File(moduleFilePath); + if (imlFile.exists()) { + //temporary workaround for IDEA-147530: otherwise if someone saved module with this name before the created module will get its settings + FileUtil.delete(imlFile); + } + return ModuleManager.getInstance(project).newModule(moduleFilePath, getModuleType().getId()); } }); } From 77f160ec5e029fb5bd6474093953c754e4846d86 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Fri, 6 Nov 2015 14:57:35 +0100 Subject: [PATCH 040/124] [java] type annotations in method return type (IDEA-147494) --- .../com/intellij/psi/impl/PsiImplUtil.java | 11 +++++++- .../PsiJavaCodeReferenceElementImpl.java | 5 +--- .../psi/impl/source/PsiTypeElementImpl.java | 13 +++++----- .../codeInsight/psi/AnnotatedTypeTest.groovy | 26 +++++++++++++++---- 4 files changed, 38 insertions(+), 17 deletions(-) diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java index e6781ce9ed50..4c70eeffdf63 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java @@ -658,7 +658,16 @@ public class PsiImplUtil { findApplicableTarget((PsiAnnotation)element, TargetType.TYPE_USE) == TargetType.TYPE_USE; } - @Nullable + public static void collectTypeUseAnnotations(@NotNull PsiModifierList modifierList, @NotNull List annotations) { + for (PsiAnnotation annotation : modifierList.getAnnotations()) { + if (isTypeAnnotation(annotation)) { + annotations.add(annotation); + } + } + } + + /** @deprecated use {@link #collectTypeUseAnnotations(PsiModifierList, List)} (to be removed in IDEA 16) */ + @SuppressWarnings("unused") public static List getTypeUseAnnotations(@NotNull PsiModifierList modifierList) { SmartList result = null; diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java index 7b8c2632dd70..29305d4d75e6 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiJavaCodeReferenceElementImpl.java @@ -592,10 +592,7 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme if (!isQualified()) { PsiModifierList modifierList = PsiImplUtil.findNeighbourModifierList(this); if (modifierList != null) { - List typeAnnotations = PsiImplUtil.getTypeUseAnnotations(modifierList); - if (typeAnnotations != null && !typeAnnotations.isEmpty()) { - annotations.addAll(typeAnnotations); - } + PsiImplUtil.collectTypeUseAnnotations(modifierList, annotations); } } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiTypeElementImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiTypeElementImpl.java index fae8063dbe7e..8df615aa7c91 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiTypeElementImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiTypeElementImpl.java @@ -37,6 +37,8 @@ import org.jetbrains.annotations.Nullable; import java.util.List; public class PsiTypeElementImpl extends CompositePsiElement implements PsiTypeElement { + private static final Class[] INTERMEDIATES = {PsiComment.class, PsiWhiteSpace.class, PsiAnnotation.class, PsiTypeParameterList.class}; + @SuppressWarnings({"UnusedDeclaration"}) public PsiTypeElementImpl() { this(JavaElementType.TYPE); @@ -69,7 +71,7 @@ public class PsiTypeElementImpl extends CompositePsiElement implements PsiTypeEl } private PsiType calculateType() { - final PsiType inferredType = PsiAugmentProvider.getInferredType(this); + PsiType inferredType = PsiAugmentProvider.getInferredType(this); if (inferredType != null) { return inferredType; } @@ -153,16 +155,13 @@ public class PsiTypeElementImpl extends CompositePsiElement implements PsiTypeEl return type == null ? PsiType.NULL : type; } - private void addTypeUseAnnotations(List list) { + private void addTypeUseAnnotations(List annotations) { PsiElement parent = this; while (parent instanceof PsiTypeElement) { - PsiElement left = PsiTreeUtil.skipSiblingsBackward(parent, PsiComment.class, PsiWhiteSpace.class, PsiAnnotation.class); + PsiElement left = PsiTreeUtil.skipSiblingsBackward(parent, INTERMEDIATES); if (left instanceof PsiModifierList) { - List annotations = PsiImplUtil.getTypeUseAnnotations((PsiModifierList)left); - if (annotations != null && !annotations.isEmpty()) { - list.addAll(annotations); - } + PsiImplUtil.collectTypeUseAnnotations((PsiModifierList)left, annotations); break; } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/psi/AnnotatedTypeTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/psi/AnnotatedTypeTest.groovy index 98d166167804..bb2e2ba20a0b 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/psi/AnnotatedTypeTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/psi/AnnotatedTypeTest.groovy @@ -40,8 +40,8 @@ class AnnotatedTypeTest extends LightCodeInsightFixtureTestCase { class I { } } - class E1 extends Exception { } - class E2 extends Exception { }""".stripIndent()) + @SuppressWarnings("ExceptionClassNameDoesntEndWithException") class E1 extends Exception { } + @SuppressWarnings("ExceptionClassNameDoesntEndWithException") class E2 extends Exception { }""".stripIndent()) } public void testPrimitiveArrayType() { @@ -78,20 +78,32 @@ class AnnotatedTypeTest extends LightCodeInsightFixtureTestCase { public void testDisjunctionType() { def psi = factory.createStatementFromText("try { } catch (@A @TA(1) E1 | @TA(2) E2 e) { }", context) as PsiTryStatement - assertTypeText(psi.catchBlockParameters[0].type, "pkg.@pkg.TA(1) E1 | pkg.@pkg.TA(2) E2", "pkg.E1 | pkg.E2") + assertTypeText psi.catchBlockParameters[0].type, "pkg.@pkg.TA(1) E1 | pkg.@pkg.TA(2) E2", "pkg.E1 | pkg.E2" } public void testDiamondType() { def psi = factory.createStatementFromText("Class<@TA String> cs = new Class<>()", context) as PsiDeclarationStatement def var = psi.declaredElements[0] as PsiVariable - assertTypeText(var.initializer.type, "java.lang.Class", "java.lang.Class") + assertTypeText var.initializer.type, "java.lang.Class", "java.lang.Class" } public void testImmediateClassType() { def aClass = myFixture.javaFacade.findClass(CommonClassNames.JAVA_LANG_OBJECT) def annotations = factory.createParameterFromText("@TA int x", context).modifierList.annotations def type = new PsiImmediateClassType(aClass, PsiSubstitutor.EMPTY, LanguageLevel.JDK_1_8, annotations) - assertTypeText(type, "java.lang.@pkg.TA Object", CommonClassNames.JAVA_LANG_OBJECT) + assertTypeText type, "java.lang.@pkg.TA Object", CommonClassNames.JAVA_LANG_OBJECT + } + + public void testFieldType() { + def psi = factory.createFieldFromText("@A @TA(1) String f;", context) + assertTypeText psi.type, "java.lang.@pkg.TA(1) String", "java.lang.String" + assertAnnotations psi.type, "@TA(1)" + } + + public void testMethodReturnType() { + def psi = factory.createMethodFromText("@A @TA(1) String m() { return null; }", context) + assertTypeText psi.returnType, "java.lang.@pkg.TA(1) String", "java.lang.String" + assertAnnotations psi.returnType, "@TA(1)" } private void doTest(String text, String annotated, String canonical) { @@ -102,4 +114,8 @@ class AnnotatedTypeTest extends LightCodeInsightFixtureTestCase { assert type.getCanonicalText(true) == annotated assert type.getCanonicalText(false) == canonical } + + private static void assertAnnotations(PsiType type, String... annotations) { + assert type.annotations.collect { it.text } == annotations.toList() + } } \ No newline at end of file From 2f5e6277f058c24e4dfa298d502830be9eb807ac Mon Sep 17 00:00:00 2001 From: Daniil Ovchinnikov Date: Tue, 3 Nov 2015 16:29:46 +0300 Subject: [PATCH 041/124] [groovy] get presentable text in GroovyExpressionTypeProvider. It is needed to properly display `as`-coercion trait types e.g. `Foo as T1, T2` instead of `Foo`. --- .../groovy/codeInsight/hint/GroovyExpressionTypeProvider.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInsight/hint/GroovyExpressionTypeProvider.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInsight/hint/GroovyExpressionTypeProvider.java index 8408b4d746ab..5726f707d1b7 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInsight/hint/GroovyExpressionTypeProvider.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInsight/hint/GroovyExpressionTypeProvider.java @@ -31,7 +31,7 @@ public class GroovyExpressionTypeProvider extends ExpressionTypeProvider" : type.getCanonicalText()); + return StringUtil.escapeXml(type == null ? "" : type.getPresentableText()); } @NotNull From c71e3ad19609f3ee04a7d24fc0d91cc5e5a1b13b Mon Sep 17 00:00:00 2001 From: Daniil Ovchinnikov Date: Fri, 6 Nov 2015 16:53:11 +0300 Subject: [PATCH 042/124] [groovy] GroovyFindUsagesProvider: unused INSTANCE field and default constructor removed --- .../groovy/findUsages/GroovyFindUsagesProvider.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/findUsages/GroovyFindUsagesProvider.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/findUsages/GroovyFindUsagesProvider.java index 60f847946239..8c57cf8dc588 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/findUsages/GroovyFindUsagesProvider.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/findUsages/GroovyFindUsagesProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * 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. @@ -32,11 +32,6 @@ import org.jetbrains.plugins.groovy.refactoring.rename.PropertyForRename; */ public class GroovyFindUsagesProvider implements FindUsagesProvider { - public static final GroovyFindUsagesProvider INSTANCE = new GroovyFindUsagesProvider(); - - public GroovyFindUsagesProvider() { - } - @Override @Nullable public WordsScanner getWordsScanner() { From a745446a4210665786aaea776373265a942958cc Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Fri, 6 Nov 2015 11:47:37 +0300 Subject: [PATCH 043/124] validate soft wrap positions in editor stress test --- .../src/com/intellij/util/DocumentUtil.java | 8 ++++++ .../openapi/editor/impl/EditorStressTest.java | 26 ++++++++++++++++--- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/platform/core-impl/src/com/intellij/util/DocumentUtil.java b/platform/core-impl/src/com/intellij/util/DocumentUtil.java index e175e367b666..e88e13e1a90f 100644 --- a/platform/core-impl/src/com/intellij/util/DocumentUtil.java +++ b/platform/core-impl/src/com/intellij/util/DocumentUtil.java @@ -96,6 +96,14 @@ public final class DocumentUtil { return document.getLineStartOffset(lineNumber); } + public static int getLineEndOffset(int offset, @NotNull Document document) { + if (offset < 0 || offset > document.getTextLength()) { + return offset; + } + int lineNumber = document.getLineNumber(offset); + return document.getLineEndOffset(lineNumber); + } + @NotNull public static TextRange getLineTextRange(@NotNull Document document, int line) { return TextRange.create(document.getLineStartOffset(line), document.getLineEndOffset(line)); diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/EditorStressTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/EditorStressTest.java index 9cd6b7d0e6dd..5d26078803c1 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/EditorStressTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/EditorStressTest.java @@ -15,11 +15,10 @@ */ package com.intellij.openapi.editor.impl; -import com.intellij.openapi.editor.Document; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.editor.FoldRegion; -import com.intellij.openapi.editor.FoldingModel; +import com.intellij.openapi.editor.*; import com.intellij.openapi.editor.ex.DocumentEx; +import com.intellij.openapi.editor.ex.SoftWrapModelEx; +import com.intellij.util.DocumentUtil; import java.util.Arrays; import java.util.List; @@ -67,6 +66,25 @@ public class EditorStressTest extends AbstractEditorTest { } protected void checkConsistency(Editor editor) { + checkSoftWrapPositions(editor); + } + + private static void checkSoftWrapPositions(Editor editor) { + Document document = editor.getDocument(); + FoldingModel foldingModel = editor.getFoldingModel(); + List softWraps = ((SoftWrapModelEx)editor.getSoftWrapModel()).getRegisteredSoftWraps(); + int lastSoftWrapOffset = -1; + for (SoftWrap wrap : softWraps) { + int softWrapOffset = wrap.getStart(); + assertTrue("Soft wraps are not ordered", softWrapOffset > lastSoftWrapOffset); + FoldRegion foldRegion = foldingModel.getCollapsedRegionAtOffset(softWrapOffset); + assertTrue("Soft wrap is inside fold region", foldRegion == null || foldRegion.getStartOffset() == softWrapOffset); + assertFalse("Soft wrap before line break", softWrapOffset == DocumentUtil.getLineEndOffset(softWrapOffset, document) && + foldRegion == null); + assertFalse("Soft wrap after line break", softWrapOffset == DocumentUtil.getLineStartOffset(softWrapOffset, document) && + !foldingModel.isOffsetCollapsed(softWrapOffset - 1)); + lastSoftWrapOffset = softWrapOffset; + } } interface Action { From 558f9abdd69d65822b5ed3a15c72be39bacd37ca Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Fri, 6 Nov 2015 17:14:39 +0300 Subject: [PATCH 044/124] use consistent (and mockable) char width in tests --- .../src/com/intellij/openapi/editor/impl/FontInfo.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/FontInfo.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/FontInfo.java index 84b06477b953..6f0f44d7d348 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/FontInfo.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/FontInfo.java @@ -16,6 +16,7 @@ package com.intellij.openapi.editor.impl; import com.intellij.openapi.editor.ex.util.EditorUIUtil; +import com.intellij.openapi.editor.impl.view.FontLayoutService; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.registry.Registry; import com.intellij.util.ui.UIUtil; @@ -188,7 +189,7 @@ public class FontInfo { public int charWidth(char c) { final FontMetrics metrics = fontMetrics(); if (c < 128) return charWidth[c]; - return metrics.charWidth(c); + return FontLayoutService.getInstance().charWidth(metrics, c); } private FontMetrics fontMetrics() { @@ -199,8 +200,8 @@ public class FontInfo { EditorUIUtil.setupAntialiasing(graphics); graphics.setFont(myFont); myFontMetrics = graphics.getFontMetrics(); - for (int i = 0; i < 128; i++) { - charWidth[i] = myFontMetrics.charWidth(i); + for (char c = 0; c < 128; c++) { + charWidth[c] = FontLayoutService.getInstance().charWidth(myFontMetrics, c); } } return myFontMetrics; From f8bdc663162f27a02ab0ea617a29d6b0524d6deb Mon Sep 17 00:00:00 2001 From: "Vladimir.Orlov" Date: Fri, 6 Nov 2015 18:07:25 +0300 Subject: [PATCH 045/124] removed JVMVersion form idea.properties (IDEA-147254 JVM settings OS X). --- build/scripts/utils.gant | 1 - 1 file changed, 1 deletion(-) diff --git a/build/scripts/utils.gant b/build/scripts/utils.gant index 9c288d73d424..2f711c0c46c2 100644 --- a/build/scripts/utils.gant +++ b/build/scripts/utils.gant @@ -796,7 +796,6 @@ private Map readIdeaProperties(Map args) { ideaPropertiesFile.close(); def defaultProperties = ["CVS_PASSFILE": "~/.cvspass", - "JVMVersion": "1.6+", "com.apple.mrj.application.live-resize": "false", "idea.paths.selector": args.system_selector, "idea.executable": args.executable, From 96431dd854a29fa2aa6d0c15289d499710964433 Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 6 Nov 2015 11:51:14 +0100 Subject: [PATCH 046/124] IDEA-147454 Smart completion add parentheses to class declaration in throws statement --- .../JavaSmartCompletionContributor.java | 21 ++++++++++++------- .../smartType/MethodThrows-out.java | 10 +++++++++ .../completion/smartType/MethodThrows.java | 10 +++++++++ .../completion/SmartTypeCompletionTest.java | 2 ++ 4 files changed, 35 insertions(+), 8 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/MethodThrows-out.java create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/MethodThrows.java diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java index d181a34e6358..85d45e784f15 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java @@ -85,12 +85,6 @@ public class JavaSmartCompletionContributor extends CompletionContributor { return THROWABLES_FILTER; } - //throws list - PsiMethod method = PsiTreeUtil.getParentOfType(element, PsiMethod.class); - if (method != null && PsiTreeUtil.isAncestor(method.getThrowsList(), element, true)) { - return THROWABLES_FILTER; - } - //new xxx.yyy if (psiElement().afterLeaf(psiElement().withText(".")).withSuperParent(2, psiElement(PsiNewExpression.class)).accepts(element)) { if (((PsiNewExpression)element.getParent().getParent()).getClassReference() == element.getParent()) { @@ -107,6 +101,10 @@ public class JavaSmartCompletionContributor extends CompletionContributor { return null; } + private static boolean isInsideThrowsList(PsiElement element) { + PsiMethod method = PsiTreeUtil.getParentOfType(element, PsiMethod.class); + return method != null && PsiTreeUtil.isAncestor(method.getThrowsList(), element, true); + } public JavaSmartCompletionContributor() { @@ -128,11 +126,18 @@ public class JavaSmartCompletionContributor extends CompletionContributor { PsiTreeUtil.findElementOfClassAtOffset(element.getContainingFile(), parameters.getOffset(), PsiJavaCodeReferenceElement.class, false); if (reference != null) { ElementFilter filter = getClassReferenceFilter(element); + boolean completeConstructor = filter != null; + if (filter == null && isInsideThrowsList(element)) { + filter = THROWABLES_FILTER; + } if (filter != null) { final List infos = Arrays.asList(getExpectedTypes(parameters)); - for (final LookupElement item : completeReference(element, reference, filter, true, false, parameters, result.getPrefixMatcher())) { + for (LookupElement item : completeReference(element, reference, filter, true, false, parameters, result.getPrefixMatcher())) { if (item.getObject() instanceof PsiClass) { - result.addElement(decorate(LookupElementDecorator.withInsertHandler(item, ConstructorInsertHandler.SMART_INSTANCE), infos)); + if (completeConstructor) { + item = LookupElementDecorator.withInsertHandler(item, ConstructorInsertHandler.SMART_INSTANCE); + } + result.addElement(decorate(item, infos)); } } } diff --git a/java/java-tests/testData/codeInsight/completion/smartType/MethodThrows-out.java b/java/java-tests/testData/codeInsight/completion/smartType/MethodThrows-out.java new file mode 100644 index 000000000000..752a63dcd6d2 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/MethodThrows-out.java @@ -0,0 +1,10 @@ +class FirstException extends Exception {} +class SecondException extends Exception {} + +interface I { + void method() throws FirstException, SecondException; +} + +class C implements I { + void method() throws FirstException, SecondException; +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/smartType/MethodThrows.java b/java/java-tests/testData/codeInsight/completion/smartType/MethodThrows.java new file mode 100644 index 000000000000..d5332958a36e --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/MethodThrows.java @@ -0,0 +1,10 @@ +class FirstException extends Exception {} +class SecondException extends Exception {} + +interface I { + void method() throws FirstException, SecondException; +} + +class C implements I { + void method() throws FirstException, Sec; +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java index e45a9866d2c9..a48109935ecf 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java @@ -428,6 +428,8 @@ public class SmartTypeCompletionTest extends LightFixtureCompletionTestCase { public void testJavadocThrows() throws Throwable { doTest(); } + public void testMethodThrows() throws Throwable { doTest(); } + public void testDoNotExcludeAssignedVariable() throws Throwable { doTest(); } public void testArrayIndexTailType() throws Throwable { doTest(); } From 6fdc2d284ea8ed1a36ad84db48f687f5b400625b Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 6 Nov 2015 12:22:21 +0100 Subject: [PATCH 047/124] StaticInitializerReferencesSubClassInspection: don't report private subclasses that can't be initialized by another thread --- ...itializerReferencesSubClassInspection.java | 22 ++++++++++++++++++- .../StaticInitializer.java | 14 ++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/StaticInitializerReferencesSubClassInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/StaticInitializerReferencesSubClassInspection.java index 3cc2178e793f..d68ab88eb015 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/StaticInitializerReferencesSubClassInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/StaticInitializerReferencesSubClassInspection.java @@ -20,7 +20,10 @@ import com.intellij.codeInspection.ProblemsHolder; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Ref; import com.intellij.psi.*; +import com.intellij.psi.search.LocalSearchScope; +import com.intellij.psi.search.searches.ReferencesSearch; import com.intellij.psi.util.PsiUtil; +import com.intellij.util.Processor; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -68,7 +71,7 @@ public class StaticInitializerReferencesSubClassInspection extends BaseJavaBatch if (element instanceof PsiClass || element instanceof PsiReferenceParameterList || element instanceof PsiTypeElement) return; PsiClass targetClass = extractClass(element); - if (targetClass != null && !(targetClass instanceof PsiAnonymousClass) && targetClass.isInheritor(baseClass, true)) { + if (targetClass != null && targetClass.isInheritor(baseClass, true) && !hasSingleInitializationPlace(targetClass)) { PsiElement problemElement = calcProblemElement(element); if (problemElement != null) { result.set(Pair.create(problemElement, targetClass)); @@ -81,6 +84,23 @@ public class StaticInitializerReferencesSubClassInspection extends BaseJavaBatch return result.get(); } + private static boolean hasSingleInitializationPlace(@NotNull PsiClass targetClass) { + if (targetClass instanceof PsiAnonymousClass) return true; + if (!targetClass.hasModifierProperty(PsiModifier.PRIVATE)) return false; + + PsiFile file = targetClass.getContainingFile(); + if (file == null) return false; + + LocalSearchScope scope = new LocalSearchScope(file); + return ReferencesSearch.search(targetClass, scope).forEach(new Processor() { + int count = 0; + @Override + public boolean process(PsiReference reference) { + return ++count < 2; + } + }); + } + @Nullable private static PsiElement calcProblemElement(PsiElement element) { if (element instanceof PsiNewExpression) return calcProblemElement(((PsiNewExpression)element).getClassOrAnonymousClassReference()); diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/threading/StaticInitializerReferencesSubClass/StaticInitializer.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/threading/StaticInitializerReferencesSubClass/StaticInitializer.java index 21abd1631691..f5cc496d9d95 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/threading/StaticInitializerReferencesSubClass/StaticInitializer.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/threading/StaticInitializerReferencesSubClass/StaticInitializer.java @@ -4,17 +4,31 @@ class Super { static final Sub C3; static final Sub C4 = SubFactory.create(); static final String C5 = SubFactory.create().toString(); + static Super USED_PRIVATE = new MyUsedSub(); static Object OK_INSIDE_ANONYMOUS = new Object() {{ Sub s = new Sub(); }}; static Object OK_UNRELATED = "abc"; static Super OK_SAME = new Super(); static Super OK_SAME_ANONYMOUS = new Super(){}; static Sub[] OK_ARRAY = new Sub[3]; + static Super OK_PRIVATE = new MySub(); static java.util.List OK_GENERICS = new java.util.ArrayList(); static { C3 = new Sub(); } + + static void foo() { + MyUsedSub.foo(); + } + + private static class MySub extends Super { } + private static class MyUsedSub extends Super { + static void foo() { + System.out.println("hello"); + } + + } } class Sub extends Super implements Intf { From eb46a9c5a23f70aaab06b1e1bd65ffc755dfc589 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 6 Nov 2015 13:11:11 +0100 Subject: [PATCH 048/124] sm runner: scroll to source on manual selection only (IDEA-147403) --- .../runner/ui/SMTRunnerUIActionsHandler.java | 26 ++----------------- .../sm/runner/ui/SMTestRunnerResultsForm.java | 12 +++++++++ 2 files changed, 14 insertions(+), 24 deletions(-) diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/ui/SMTRunnerUIActionsHandler.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/ui/SMTRunnerUIActionsHandler.java index 62ba4445b46a..9b79b8f5652b 100644 --- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/ui/SMTRunnerUIActionsHandler.java +++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/ui/SMTRunnerUIActionsHandler.java @@ -15,16 +15,10 @@ */ package com.intellij.execution.testframework.sm.runner.ui; -import com.intellij.execution.testframework.*; -import com.intellij.execution.testframework.actions.ScrollToTestSourceAction; -import com.intellij.execution.testframework.sm.SMRunnerUtil; +import com.intellij.execution.testframework.AbstractTestProxy; +import com.intellij.execution.testframework.TestConsoleProperties; import com.intellij.execution.testframework.sm.runner.ProxyFilters; import com.intellij.execution.testframework.sm.runner.SMTestProxy; -import com.intellij.openapi.application.ModalityState; -import com.intellij.pom.Navigatable; -import com.intellij.util.OpenSourceUtil; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.util.List; @@ -67,20 +61,4 @@ public class SMTRunnerUIActionsHandler extends TestResultsViewer.SMEventsAdapter } } } - - public void onSelected(@Nullable final SMTestProxy selectedTestProxy, - @NotNull final TestResultsViewer viewer, - @NotNull final TestFrameworkRunningModel model) { - //TODO: tests o "onSelected" - SMRunnerUtil.runInEventDispatchThread(new Runnable() { - public void run() { - if (ScrollToTestSourceAction.isScrollEnabled(model)) { - final Navigatable descriptor = TestsUIUtil.getOpenFileDescriptor(selectedTestProxy, model); - if (descriptor != null) { - OpenSourceUtil.navigate(false, descriptor); - } - } - } - }, ModalityState.NON_MODAL); - } } diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/ui/SMTestRunnerResultsForm.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/ui/SMTestRunnerResultsForm.java index 4da5f6c16744..fe2f478346ca 100644 --- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/ui/SMTestRunnerResultsForm.java +++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/ui/SMTestRunnerResultsForm.java @@ -20,6 +20,7 @@ import com.intellij.execution.TestStateStorage; import com.intellij.execution.configurations.RunConfiguration; import com.intellij.execution.configurations.RunProfile; import com.intellij.execution.testframework.*; +import com.intellij.execution.testframework.actions.ScrollToTestSourceAction; import com.intellij.execution.testframework.export.TestResultsXmlFormatter; import com.intellij.execution.testframework.sm.SMRunnerUtil; import com.intellij.execution.testframework.sm.TestHistoryConfiguration; @@ -47,8 +48,10 @@ import com.intellij.openapi.util.io.FileUtilRt; import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.wm.IdeFocusManager; +import com.intellij.pom.Navigatable; import com.intellij.ui.JBColor; import com.intellij.util.Alarm; +import com.intellij.util.OpenSourceUtil; import com.intellij.util.PathUtil; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.text.DateFormatUtil; @@ -197,6 +200,7 @@ public class SMTestRunnerResultsForm extends TestResultsPanel @Override public void pass(AbstractTestProxy testProxy) { if (testProxy == null) return; + final AbstractTestProxy selectedProxy = testProxy; //drill to the first leaf while (!testProxy.isLeaf()) { final List children = testProxy.getChildren(); @@ -213,6 +217,14 @@ public class SMTestRunnerResultsForm extends TestResultsPanel //pretend the selection on the first leaf //so if test would be run, tracking would be restarted myLastSelected = testProxy; + + //ensure scroll to source on explicit selection only + if (ScrollToTestSourceAction.isScrollEnabled(SMTestRunnerResultsForm.this)) { + final Navigatable descriptor = TestsUIUtil.getOpenFileDescriptor(selectedProxy, SMTestRunnerResultsForm.this); + if (descriptor != null) { + OpenSourceUtil.navigate(false, descriptor); + } + } } }); From 56333d2303dfe25b6ee43557da1b219cfdbe7a25 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 6 Nov 2015 13:15:28 +0100 Subject: [PATCH 049/124] tests: allow scroll to source together with track running test as scroll should be done for manual selection only --- .../testframework/actions/ScrollToTestSourceAction.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/platform/testRunner/src/com/intellij/execution/testframework/actions/ScrollToTestSourceAction.java b/platform/testRunner/src/com/intellij/execution/testframework/actions/ScrollToTestSourceAction.java index dd2a417a5a2f..3254e58a98c0 100644 --- a/platform/testRunner/src/com/intellij/execution/testframework/actions/ScrollToTestSourceAction.java +++ b/platform/testRunner/src/com/intellij/execution/testframework/actions/ScrollToTestSourceAction.java @@ -32,7 +32,7 @@ public class ScrollToTestSourceAction extends ToggleBooleanProperty.Disablable { protected boolean isEnabled() { final AbstractProperty.AbstractPropertyContainer properties = getProperties(); final TestFrameworkRunningModel model = myModel; - return isEnabled(properties, model); + return isEnabled(model); } @Override @@ -40,14 +40,13 @@ public class ScrollToTestSourceAction extends ToggleBooleanProperty.Disablable { return true; } - private static boolean isEnabled(final AbstractProperty.AbstractPropertyContainer properties, final TestFrameworkRunningModel model) { - if (!TestConsoleProperties.TRACK_RUNNING_TEST.value(properties)) return true; + private static boolean isEnabled(final TestFrameworkRunningModel model) { return model != null && !model.isRunning(); } public static boolean isScrollEnabled(final TestFrameworkRunningModel model) { final TestConsoleProperties properties = model.getProperties(); - return isEnabled(properties, model) && TestConsoleProperties.SCROLL_TO_SOURCE.value(properties); + return isEnabled(model) && TestConsoleProperties.SCROLL_TO_SOURCE.value(properties); } public void setModel(final TestFrameworkRunningModel model) { From a73d1238ffd9b3e975c95feb386cdad4fb75b04d Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 6 Nov 2015 13:43:17 +0100 Subject: [PATCH 050/124] testdata for IDEA-147511 --- .../lambda/newMethodRef/IDEA147511.java | 47 +++++++++++++++++++ .../lambda/NewMethodRefHighlightingTest.java | 4 ++ 2 files changed, 51 insertions(+) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/IDEA147511.java diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/IDEA147511.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/IDEA147511.java new file mode 100644 index 000000000000..a5f20258335b --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/IDEA147511.java @@ -0,0 +1,47 @@ + +import java.util.Comparator; +import java.util.Optional; +import java.util.function.BinaryOperator; +import java.util.function.Consumer; +import java.util.stream.Stream; + +class Bug { + + public static void main(String[] args) { + Stream tokenStream = Stream.of("hello", "world"); + + Comparator order = Comparator.naturalOrder(); + Min min = tokenStream.collect( + () -> new Min<>(order), + Min::accept, + Min::combine); + + System.out.printf("Min = %s%n", + min.asOptional().orElse(null)); + } + + static class Min implements Consumer { + + private final BinaryOperator minOf; + private T min; + + public Min(Comparator order) { + this.minOf = BinaryOperator.minBy(order); + } + + @Override + public void accept(T t) { + this.min = min != null ? minOf.apply(min, t) : t; + } + + public void combine(Min other) { + if (other.min != null) { + accept(other.min); + } + } + + public Optional asOptional() { + return Optional.ofNullable(min); + } + } +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java index b24d597f2c28..26d02b495ac3 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/NewMethodRefHighlightingTest.java @@ -446,6 +446,10 @@ public class NewMethodRefHighlightingTest extends LightDaemonAnalyzerTestCase { doTest(); } + public void testIDEA147511() throws Exception { + doTest(); + } + private void doTest() { doTest(false); } From 25d3334300900f18fb897b6ee030faafef3a9231 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 6 Nov 2015 15:09:47 +0100 Subject: [PATCH 051/124] move member: restore qualifier in switch labels for non-enum constants (IDEA-147539) --- .../move/moveMembers/MoveJavaMemberHandler.java | 17 +++++++++-------- .../after/A.java | 2 ++ .../after/B.java | 13 +++++++++++++ .../before/A.java | 3 +++ .../before/B.java | 12 ++++++++++++ .../intellij/refactoring/MoveMembersTest.java | 7 +++++-- 6 files changed, 44 insertions(+), 10 deletions(-) create mode 100644 java/java-tests/testData/refactoring/moveMembers/stringConstantInSwitchLabelExpression/after/A.java create mode 100644 java/java-tests/testData/refactoring/moveMembers/stringConstantInSwitchLabelExpression/after/B.java create mode 100644 java/java-tests/testData/refactoring/moveMembers/stringConstantInSwitchLabelExpression/before/A.java create mode 100644 java/java-tests/testData/refactoring/moveMembers/stringConstantInSwitchLabelExpression/before/B.java diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveMembers/MoveJavaMemberHandler.java b/java/java-impl/src/com/intellij/refactoring/move/moveMembers/MoveJavaMemberHandler.java index 59dbd1ab271f..742f955d6dbf 100644 --- a/java/java-impl/src/com/intellij/refactoring/move/moveMembers/MoveJavaMemberHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/move/moveMembers/MoveJavaMemberHandler.java @@ -179,14 +179,15 @@ public class MoveJavaMemberHandler implements MoveMemberHandler { changeQualifier(refExpr, usage.qualifierClass, usage.member); } else { - final PsiReferenceParameterList parameterList = refExpr.getParameterList(); - if (parameterList != null && parameterList.getTypeArguments().length == 0 && !(refExpr instanceof PsiMethodReferenceExpression)){ - refExpr.setQualifierExpression(null); - } else { - final Project project = element.getProject(); - final PsiClass targetClass = - JavaPsiFacade.getInstance(project).findClass(options.getTargetClassName(), GlobalSearchScope.projectScope(project)); - if (targetClass != null) { + final Project project = element.getProject(); + final PsiClass targetClass = + JavaPsiFacade.getInstance(project).findClass(options.getTargetClassName(), GlobalSearchScope.projectScope(project)); + if (targetClass != null) { + final PsiReferenceParameterList parameterList = refExpr.getParameterList(); + if ((targetClass.isEnum() || PsiTreeUtil.isAncestor(targetClass, element, true)) && parameterList != null && parameterList.getTypeArguments().length == 0 && !(refExpr instanceof PsiMethodReferenceExpression)) { + refExpr.setQualifierExpression(null); + } + else { changeQualifier(refExpr, targetClass, usage.member); } } diff --git a/java/java-tests/testData/refactoring/moveMembers/stringConstantInSwitchLabelExpression/after/A.java b/java/java-tests/testData/refactoring/moveMembers/stringConstantInSwitchLabelExpression/after/A.java new file mode 100644 index 000000000000..8a58812a49b2 --- /dev/null +++ b/java/java-tests/testData/refactoring/moveMembers/stringConstantInSwitchLabelExpression/after/A.java @@ -0,0 +1,2 @@ +public interface A { +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/moveMembers/stringConstantInSwitchLabelExpression/after/B.java b/java/java-tests/testData/refactoring/moveMembers/stringConstantInSwitchLabelExpression/after/B.java new file mode 100644 index 000000000000..cc08541ae1bc --- /dev/null +++ b/java/java-tests/testData/refactoring/moveMembers/stringConstantInSwitchLabelExpression/after/B.java @@ -0,0 +1,13 @@ +public class B { + + public static final String FOO = "FOO"; +} + +class U { + public void example(String foo) { + switch (foo) { + case B.FOO: + break; + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/moveMembers/stringConstantInSwitchLabelExpression/before/A.java b/java/java-tests/testData/refactoring/moveMembers/stringConstantInSwitchLabelExpression/before/A.java new file mode 100644 index 000000000000..0451878b749f --- /dev/null +++ b/java/java-tests/testData/refactoring/moveMembers/stringConstantInSwitchLabelExpression/before/A.java @@ -0,0 +1,3 @@ +public interface A { + public static final String FOO = "FOO"; +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/moveMembers/stringConstantInSwitchLabelExpression/before/B.java b/java/java-tests/testData/refactoring/moveMembers/stringConstantInSwitchLabelExpression/before/B.java new file mode 100644 index 000000000000..309cd8c107c3 --- /dev/null +++ b/java/java-tests/testData/refactoring/moveMembers/stringConstantInSwitchLabelExpression/before/B.java @@ -0,0 +1,12 @@ +public class B { + +} + +class U { + public void example(String foo) { + switch (foo) { + case A.FOO: + break; + } + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/refactoring/MoveMembersTest.java b/java/java-tests/testSrc/com/intellij/refactoring/MoveMembersTest.java index e1e66c483fc4..79435401350a 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/MoveMembersTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/MoveMembersTest.java @@ -18,7 +18,6 @@ package com.intellij.refactoring; import com.intellij.JavaTestUtil; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.roots.LanguageLevelProjectExtension; -import com.intellij.openapi.vfs.VirtualFile; import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; @@ -174,7 +173,11 @@ public class MoveMembersTest extends MultiFileTestCase { public void testEscalateVisibility1() throws Exception { doTest("A", "B", true, VisibilityUtil.ESCALATE_VISIBILITY, 0); } - + + public void testStringConstantInSwitchLabelExpression() throws Exception { + doTest("A", "B", true, VisibilityUtil.ESCALATE_VISIBILITY, 0); + } + public void testMultipleWithDependencies() throws Exception { doTest("A", "B", true, VisibilityUtil.ESCALATE_VISIBILITY, 0, 1); } From a6bd93a9c79836004c1f6a7076af49f6d79e5df4 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 6 Nov 2015 16:13:23 +0100 Subject: [PATCH 052/124] change signature: fix search for tags to remove in unsorted array (IDEA-147535) --- .../JavaChangeSignatureUsageProcessor.java | 5 ++-- .../changeSignature/JavadocOfDeleted.java | 30 +++++++++++++++++++ .../JavadocOfDeleted_after.java | 29 ++++++++++++++++++ .../refactoring/ChangeSignatureTest.java | 6 ++++ 4 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 java/java-tests/testData/refactoring/changeSignature/JavadocOfDeleted.java create mode 100644 java/java-tests/testData/refactoring/changeSignature/JavadocOfDeleted_after.java 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 3cf8da2f8fb1..0797d6797949 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureUsageProcessor.java @@ -41,6 +41,7 @@ import com.intellij.refactoring.util.*; import com.intellij.refactoring.util.usageInfo.DefaultConstructorImplicitUsageInfo; import com.intellij.refactoring.util.usageInfo.NoConstructorClassUsageInfo; import com.intellij.usageView.UsageInfo; +import com.intellij.util.ArrayUtil; import com.intellij.util.IncorrectOperationException; import com.intellij.util.VisibilityUtil; import com.intellij.util.containers.ContainerUtil; @@ -857,13 +858,13 @@ public class JavaChangeSignatureUsageProcessor implements ChangeSignatureUsagePr public boolean value(Pair pair) { final PsiParameter parameter = pair.first; final String oldParamName = pair.second; - final int idx = Arrays.binarySearch(oldParameterNames, oldParamName); + final int idx = ArrayUtil.find(oldParameterNames, oldParamName); return idx >= 0 && idx == method.getParameterList().getParameterIndex(parameter) && changeInfo.getNewParameters()[idx].getOldIndex() == idx; } }, new Condition() { @Override public boolean value(String paramName) { - return Arrays.binarySearch(oldParameterNames, paramName) >= 0; + return ArrayUtil.find(oldParameterNames, paramName) >= 0; } }); } diff --git a/java/java-tests/testData/refactoring/changeSignature/JavadocOfDeleted.java b/java/java-tests/testData/refactoring/changeSignature/JavadocOfDeleted.java new file mode 100644 index 000000000000..123c9b00992b --- /dev/null +++ b/java/java-tests/testData/refactoring/changeSignature/JavadocOfDeleted.java @@ -0,0 +1,30 @@ +/* + * Copyright 2000-2011 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. + */ +class C { + /** + * This is the role - + * @param role another desc + * @param labelExpression blah-blah + * @return return description + */ + public Integer example(int role, String labelExpression) { + switch (role) { + case Constants.FOO: + break; + } + return 1; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/changeSignature/JavadocOfDeleted_after.java b/java/java-tests/testData/refactoring/changeSignature/JavadocOfDeleted_after.java new file mode 100644 index 000000000000..af54692fc2d8 --- /dev/null +++ b/java/java-tests/testData/refactoring/changeSignature/JavadocOfDeleted_after.java @@ -0,0 +1,29 @@ +/* + * Copyright 2000-2011 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. + */ +class C { + /** + * This is the role - + * @param role another desc + * @return return description + */ + public Integer example(int role) { + switch (role) { + case Constants.FOO: + break; + } + return 1; + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureTest.java b/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureTest.java index 3652f87a7880..afcb86dc945a 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureTest.java @@ -247,6 +247,12 @@ public class ChangeSignatureTest extends ChangeSignatureBaseTest { }, false); } + public void testJavadocOfDeleted() { + doTest(null, new ParameterInfoImpl[]{ + new ParameterInfoImpl(0, "role", PsiType.INT), + }, false); + } + public void testCovariantReturnType() { doTest(CommonClassNames.JAVA_LANG_RUNNABLE, new ParameterInfoImpl[0], false); } From 062fcda742e52a02a45ca6ea4c3e4875015a1a29 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 6 Nov 2015 16:13:59 +0100 Subject: [PATCH 053/124] fix unsorted array search --- .../structuralsearch/JavaStructuralSearchProfile.java | 3 ++- .../idea/eclipse/conversion/EclipseClasspathWriter.java | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaStructuralSearchProfile.java b/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaStructuralSearchProfile.java index b2b44aebd867..d79eb59219c5 100644 --- a/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaStructuralSearchProfile.java +++ b/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaStructuralSearchProfile.java @@ -32,6 +32,7 @@ import com.intellij.structuralsearch.plugin.replace.impl.Replacer; import com.intellij.structuralsearch.plugin.ui.Configuration; import com.intellij.structuralsearch.plugin.ui.SearchContext; import com.intellij.structuralsearch.plugin.ui.UIUtil; +import com.intellij.util.ArrayUtil; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -382,7 +383,7 @@ public class JavaStructuralSearchProfile extends StructuralSearchProfile { private void checkModifier(final String name) { if (!MatchOptions.INSTANCE_MODIFIER_NAME.equals(name) && !PsiModifier.PACKAGE_LOCAL.equals(name) && - Arrays.binarySearch(JavaMatchingVisitor.MODIFIERS, name) < 0 + ArrayUtil.find(JavaMatchingVisitor.MODIFIERS, name) < 0 ) { throw new MalformedPatternException(SSRBundle.message("invalid.modifier.type",name)); } diff --git a/plugins/eclipse/src/org/jetbrains/idea/eclipse/conversion/EclipseClasspathWriter.java b/plugins/eclipse/src/org/jetbrains/idea/eclipse/conversion/EclipseClasspathWriter.java index 27e576979158..892b7e55291f 100644 --- a/plugins/eclipse/src/org/jetbrains/idea/eclipse/conversion/EclipseClasspathWriter.java +++ b/plugins/eclipse/src/org/jetbrains/idea/eclipse/conversion/EclipseClasspathWriter.java @@ -28,6 +28,7 @@ import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.ArrayUtil; import com.intellij.util.Function; import gnu.trove.THashMap; import org.jdom.Element; @@ -39,7 +40,6 @@ import org.jetbrains.idea.eclipse.EclipseXml; import org.jetbrains.idea.eclipse.IdeaXml; import org.jetbrains.idea.eclipse.config.EclipseModuleManagerImpl; -import java.util.Arrays; import java.util.Map; public class EclipseClasspathWriter { @@ -90,7 +90,7 @@ public class EclipseClasspathWriter { private void createClasspathEntry(@NotNull OrderEntry entry, @NotNull Element classpathRoot, @NotNull final ModuleRootModel model) throws ConversionException { EclipseModuleManager eclipseModuleManager = EclipseModuleManagerImpl.getInstance(entry.getOwnerModule()); if (entry instanceof ModuleSourceOrderEntry) { - boolean shouldPlaceSeparately = eclipseModuleManager.isExpectedModuleSourcePlace(Arrays.binarySearch(model.getOrderEntries(), entry)); + boolean shouldPlaceSeparately = eclipseModuleManager.isExpectedModuleSourcePlace(ArrayUtil.find(model.getOrderEntries(), entry)); for (ContentEntry contentEntry : model.getContentEntries()) { VirtualFile contentRoot = contentEntry.getFile(); for (SourceFolder sourceFolder : contentEntry.getSourceFolders()) { From 1d9b58e0fbd289c07e2b8ba83850e15855869a93 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Fri, 6 Nov 2015 18:29:37 +0300 Subject: [PATCH 054/124] [git] Substitute trilead-ssh2 library with the patched one * Adds from no to 5 times speedup on git fetch * The patch is made by TeamCity dev Dmitry Neverov as part of TW-14598. --- plugins/git4idea/lib/trilead-ssh2-src.zip | Bin 214101 -> 201910 bytes plugins/git4idea/lib/trilead-ssh2.jar | Bin 252914 -> 247561 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/plugins/git4idea/lib/trilead-ssh2-src.zip b/plugins/git4idea/lib/trilead-ssh2-src.zip index 02c3bfa5538fe18bf29a5d0451d9eb0b2a090956..2a8472b2d245ebb4e5de8bdc0efd3d099978ae0f 100644 GIT binary patch delta 25284 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 LnJFN%o$~(x^cq-j diff --git a/plugins/git4idea/lib/trilead-ssh2.jar b/plugins/git4idea/lib/trilead-ssh2.jar index d22178a73746eea64c7741308f73896cd63a7271..e19bd37f74294117e63d07695735ba428cd6e1d9 100644 GIT binary patch literal 247561 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%0Ao7#nU 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

qkrG)0z+@Y{a$M21C!P2r3-?qLbbHQMzV3H!L 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≪>` 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

Z<_?pc0;hu0JWhecLbx;dJ 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

Od8z#INoy4y#KIQ zJiD@F;C#Jv+ktUeV@F0u&ziq;73Kq10^+~SyS7QwDhn=Q-HpoxHzprW`?RSUUMQ%= zIvW3C9E@&HZtD?_R{O>`-?%+cT<_kt$*{2C9ZxR0CNZFA|6gon!$6x?e6MTqK(9X9r4820S^ zo8~jwdgIPO!!@rq+1Q){G9x$|OS;m-_|sUKH0tLw`SM1^K=n1xHcP|%1=GCk##)Tc z(N-jMw{Un=dFi!_zb=99TIpA-Sin!+&iSm8PaDDUG5$tcn|UAUvT`KZu5K& zMdXJ6Y6$-Ye;0;FWQPB03@^JJ9#It@@hIGJ)Aojnp6lg3TkiE-FYc*;Klge*R`fL7 z>1n9!F~8jtRotUi({sJFXG>L2V0q8Snw~esJzL6plJ4|WRQAkzR9@O$=^I!%>0eoE zTj?8GQDXJ>jYnEryJtaRO+n$!g2MPS8h=l_Ciq7tAfpn3@CgI>gy^UQ56 zer)2>OZ*+HUFDvL>JG{34%_Mui|US~YER2*&+XNo#A?s@>JC~^(VL*6hM*$PI;&88 zYI}65h&`54(fhHy*PPmWn%0|ix3_`%r8DjC3Vgzc=mh`hgnLm5Yew6>M?J8k9&?NT zMKm2ROFyoC|G!rsMhIOa`aL5ApOJFTcAEuGr&E?p&+PunF5m7gTZi0~h!;;;T(K*3 z@-Dkk9>1r%L3=30aA>Cj@!TnkllFz$#qGM@zdkH_77iA-7ZrO{m0t?%ZrD1cuS`61 z+Ty!?A-=dB?Om2x9`D%gtT(hmk!X-(k!n|{Ufk~MtzB2%7255rJ@iAKc>J`*CA-3> z#qH|eWtYk?Id#v5bUSYuA}ABzpRyRYFAOjCNb)W_S6&<3ZEi5MLW#Kjj76_>F9maF9l3#jI-<_Ly1JjPkcTKTj%XYglJ&2+01Uw_|o@Aw5MrZJiaO2~(6Fn(5hW__nOS zk~2Cp^t&-l`tJ(i#UZtsyWK_;u9Xq}*StMhhLxI4p&q-^ni!;+G>N|xsec8RX0CLX zOzTxTjt6+l@o4unpM<*aI^NVs8c9R_WiJ#AU6`-y-Y|`?lpN!D=Y6JCYCfXztOgh6 z7-~W%UTzwK=ay#6Yfan0(@zWIRi!EL2x-2&ku)RTnzVS{%`{ow{xnzKmoz=z&NMua zk%s1_qy_VYPf3?lCO%Ip3oIv;|5*M}p0fO{{JUrVc6nb`eZE#p@R#wo!OzBD2EQL~ z4}P0BuywR@+F7khJ2o(sS^sX9ne=WxHBoOSHA!!7AyIF3AxUq38^cd1#_(I%$BP#2 z<_(F~^3+8*UV&&8FG%FY`y|5fEJSg++gx(9!ZE|bdM{X!MDv~iSn$zpaoerqD z-oJP^ytpZ-EkdMjd`VarZ8goQn0*#X8*n9O6uc2R82bv{qo4jUt(^VTR~&w?$*;{+ zWMbSm_qoSyGNF97y{{s?vB|Y5huo z=hn0V&&62doCVqFt1~J+`hN{80tZ62J(j%}pHngWyv;_||Lw8^YoH(^Ta-p6m&KD9mMs_+|&c5TNOD+)A3M#h#4 zzoL)N8g`FNEqd3!B3Fdd7G2t`7V8QYL}+74VSV(DVdN{B>Z-Rs;VBpFM*qU^E#XP!?jCJpIo+G`$8GdY zw!~blWGbj`>E@wwFGr6{IOx_*BR151lB8U47=6xis+{u1-SM3_!@RFdl~+~kwnF9R zMi)sqY_97-Y^eRDLb+f+YE8M|H~NnCx^&79cPL=q0`p&as)DL{&r?+H{^&jlhnTu? z#D=_2a+C`Jqpw)6%clBRueBQ9>#TD0!=2xvhv8q=P|bWRy~5=u5?LW5nO%IQ=}y%* z+Lo%B9GA*O3ia_BE!DS`%PCaW8L1VU{GYMB4sDWIaoGPG%PTU8LhW{uS3R@U8gn^# z4^HRtMP&9xy+E8!<3-8r2YU869fl7w`@NnYPUoqQBseU0oDS(a(|P{~`l;TH)9IFheyY82Iv-#e|5ZETbhu}rpXz-$olj?=pK3dt&KDQx zr+P0=hvx$QRJ-AH`rkr7HT!Wo-`+w$H8wb%AG**_jSo&|Ko|O{alz^E??FE`K{%bE zd(cmf15Rfo8v3d6$LWkkLq9bhIGu?h=!b^I>HHajehjx`6iFy?+X@Z_qnLaaVcWpj zh*3;&N7%mM=wlR9+Yq)NIqNZsXdF zbr{8T4TS9$?iP$W;-#L^EQavikWYJ)7Jg=4U6rC%yv>!wKCWHuid07aB_Cy?1v z>Z&%8xKmWhx>Lw(9d*@b07@w9&cissMBz@|rL4<`aex6(Mp<_o#sMZ8cdCN2t{lbz z20$fc9UaC229G;cOx2J(&Tf%Ki<7ptV zKtjv;EbQb7HeM4*TN_%^KE81tkls|zPH6cG$V@i=7LdL`!k8UE1_B8!e*qaw-OD#F0x}**Xt@Z3xx&Xyf&v=UJIlsDRU)+|Ks_wq*cwPjDn}T=w|C-atrI*` zB#BW~uCir=`B@tT&y+~3l}W2T`SvMP73oZ@ofOkaN3i|^JLiRs;ZCZGb0&7i#!wtS zWMMZdkS^@!+sjZ@wq#-N$dfJv@$J>ADp3G{!Sd~qR28)>>>*$R`S!|Gl|TT%gz)WG zQdP{eus?ta=G$vhRgwSz6Uw)zyuP9{qeb%G*O{~a3|7%kP@G?^(xSxFp$^(RyBoSh zk-USta<&&>FZT$FZMI~`1iF7w4L3Q7*9Bctr@Ig?V zSE`Z<)yoF$$?k>+cQ939x>cnr2xF$|oxv8IyJ2=DX&VfDpa8pqBRH5@s6hsfvOzbH=SJ$GHHTQZv}10$(ZyTMoG!mPV3(Unx}y z#gn%Ab>+nFV9vm_qkx9i$J`B{LhI~O6(eJ2KJ-s;HynVW1G;jwb};jyMqU9{2vbUN zH%$8=_@?4+s2oYU@70wPYRudR<*`7+XjjVeyvUB`w z3`O#!`$7B`Fa>-Twn~9?AIon6Q$S~73BUyMTfh{80RR)iZvj)V%)*WU6U=V`Q%D8? zOentv%u+H7yGEXLbRWNEHC4qCfCB00etwHIRYf}sdlMKKM~$iy0RR{nr_aXFK#KWT zNAT?;JLjE^VGRIX!M6f-&ajPP41g_yZ&%qlpKT1s0O$$6-D2m=+Zbv}F%zK;nE5Lk z!&?BL&2@IpFB?Ow6m!Or-{MMDp=Dwj%B0^8{FY#<$~XWO((gU|7DuYeq72jDiC?#Z z%GsWUm9?QAmS$evDhN8q#y8l|l$1%;iSQ+qUneic^ar=FNs&}-XG6QPk6*Ww%5hmQ z2ztuKOF+S1e%(cBrvHCXxK0oRmrCyn8-Ewt?*P)DU-uqJ5|#6Itsn^QmEI*b{xFdG zK>G3P9sqe9NN5RHOYa&R{}afaKnC#Z{s5Uq<>*37i46fkSt47SpIs+j$xjf}qR8|= zYESdC>BL{@76jeh!Ss)Er};T_;ji=vf_?%_0=TCO?+5G^fQJFv0|d4QAQ7N#7rqDB zI)Fz2IsydtFThlHno`AJoq8mxI=cW{d7+dOT{T!&0I(F`b$~U4bwL2H0=xpSda&*j zz()WJ0n!HREC8MZc&U^#1Z^7u>bTQ-{JQYOE>kb zIe=*Zn@TxnIt4)pm`znFN4s1ac3RV*xEsW?_dkOos9}ZJFjbQx&P_KZE4^bgiqk;70*Tn#N1jr47padXq zvGKh?O4`u=dhzQtfefQ^NYK&~NC@-0fK&kzrpbi66#yTD_;oy(NifvY76gq$JqYuu zK$5etmKz11vf20>HZ&BK^C%PhS($XikzW@=<*bxt9)~M=&QS0PVxOfAzfM7hd3-&U z>dvzf71fK?hWU}!QK;{DJ z%&#*7QklwWhn63Ke8R^60`ex1uKc=qAT@!6ma{-MvGFQErrXd$bpE>=GGi_HWUs_L zzRjK%vcD65%}elU6TmI*w2+`K{IyQOr^Cj~(F@8=w^Tw0KwvJ08|Ee7vSB& zx?q4N0ILClZGQ&15@1OwXAIg}0yHSVTDo-M6M6)ndUr67C%Drz;C?4Zl16Vq#cNOz z;5@*m0E+;^br0LYoLUAID+lW&VK#dTu*vjNjwalJlK>$|CO-xU*ZtpIy#d1Q7lG~P z!Ac-bPMNvW7GS=b(3Ljye7XQTZ{$wf<=llQgR5zR<%dGUH_-45G=$laVGdm$l{`r!m`_|o zLuerIB}pR$KHt|ApmQ8~^!0*lj7a-Tg6@%EA(pO`}Bz%|ycfGP^4!XHp* z!zcR4FgIVNk1u0wDMBiQ9qPOy#_R&I5t0WDkR2EgS*TmQVZ-NCP0D zWfG7y_AqGHLZJ=KcQ>CX1LQg?XUm#~_gnsGkqQr`%NV7cira%kU4SkC9{?;KB;ErU4X_a)b&wbhFbLoyfY5dbAPFEuhSS{w z3)Bv#hpjuU%c*O4#|MFhJ3wE6ZU8v~i>&}%0lIVzKLqv&z+iwL0D;v2=m^lcYxo$j zApkFzat7}W5<$oojul|FgSv(VY=OltW2T28R15~#DX;)7>tPKrv}^c9B&kpgD*AT~ zuYlQP>|nOz+-XL30DA-$&jH2(wCNho1-1lWq&saAY+nsl@)A~Zv;g}H=4*uQ8g_$$ zK-9KJ6ksDRmU3qIcMYe&@}EM(OHix`4M82u!j#;g>pmDb7K(R3F{p&=HBb|l1iw72 z-3|J4?HX={CB*~W4>dBNM%f@S4f?W%rOm>q5m1~{$_a%1SB8mzz-?a-MK@rGkgj1N zj4XoMIZ!O`POIJ9HLTwyuy_Yh2A~h0=r7G|hitMoh)?_=#cYRcGEiG!0oi0k278#G zNGgPEvNn)Ud;}z9lOHz=EItEyl07^EBxIAdV8~NILN@skTFz%-f1O|tuK^OW$@qPI z;yEB8n>2@(uYk;C58nh5vdMTDvmHptCe5McFCZbCY*;I>P=SvZ*~9ylNrjM2#{2P! zH84%cCL7iXEKGsC${zj#BxIBE0es>ZkdRF#K}$IxFR+Jq0twmV|q96OvolDv3#NxkdRHzLVqxEycDx$i=c58Da4gegaA&=#B!8K zy>#~QO9fKzj1BDu+>{NOSW_x{c(XjI_k|5@Seh9lPv!j0!kVrk_1=LhZhYb;S!Rq3 zmE#V5RY2`J_HgNHQtv|`J@~{fAdyr~n~tFII*_&O;cy_UfOO{*Yk^z|B(!V*vYtIW z03-uQPd;%HNHHpBE40kY#MZ;Kluz#;R9=u{#()A2w&@(cx>wM6SCJVL1<;{u_-c=! z5fpF?DB$2dUBmv}f<{olF`$5h?EwM{3OEK7aIkIH@CRT)0mpy>4t4|xEGXa@P{8Pl zK_WVm)C&r@9wNe#szKrnfS`cuK>;5D>kS473b-C@{7Cg6@iRbB!1Z9;M`(jYOMsw& z>p=mJLfa<*K>>gE>l!}ZC1?Z%90RUp6pS`Gn$!ylxE>VnDBQ7mfS`cuK>?rb6f`1W zHlTnt$_I&(QKa7H0&D^(U=6tOCjov12ntvO=IRI#6!0`CU`yDAbFh-{JD6jTekOp^ zDuhd;4Lx^2(MEULd_yT`0q%GjG}OkEdbdDBJt(e&n$UF<4BQ8`Aqkzfg#O@qrNNRS zU=7!yzpGFS7W@lf1Jsa&8lGLlBA6oiy`XW@m^sz~#VYQ!C%e0b4Pb|xpf7tUGKC?Y zz{s%iA{bc(M&1PdLF5l99VA`@s00v{O2{TbBUzd`7ER@ZY!Ea;N}5o}9|v}Tsn-?ifs3F?F~|I<9Oh<0 zBL~QA_An2~U?9Ooi~|X}l&LLfoCcD@9<~C~(S|k;E}{rXUn(aRT6O@L#U2*HV21GV z3VZmeGO5=T>iP4DeK3<`DraG>piv9RP^u~9)X%foXp<}+CX+|sB*;EOH64*+9thy0 zPG<4qc0!F%K1zEP>G^7#STiac?Xgjitsu)h;0dLxNzb3M(JM1~aXwVjn{H5|LVCUh zpbJ13KB`Qa^gIe+5I_%rz^Vas0O-s|MF1NJ&>x^XKw!-QdH{6gqkaLK1P}`l#`*=U z1i(F1)BR3-lnSu+06Sk_`FikO&!S^V+-a}ZjS-gz-YMCBw7p_eZF|Mm*VfM_*~ZUS z%cdvy8Fk2^-U}5LQ(k&>{oZ$W<&Oe&_r4lI-@}XK??v2_>v4SVwNd?~djAbC+cmPr z4;WrydfU5S6v#(MYseVaZm?+^wV*0b-SKiwjxE3PJv+#<$M(ogG3uH2+g`~L8_BJ5 z#JKisi$-bN!Y{hi_A$1XNgw;d&(|N%%y#^Os>@4UrLOc_e~0dY>ui2z&SP@s%gy_nwO-kLmv5kYE;dco2o3Mu zJ8Ru>-7?`E4wJhg-AKht@n<_7g?X?t{nX=)L1V7eZx(%O~w7c&=m(@S)t*Y-Cs&1YBV)^`M`(aUL+GF^=pI{{uO{ru)o!iOKze4?oG7!EduBupeWqKotnzHaGxhJ6yuxer>r3AZHOJ}$!fqt`c^J-jrqD~tO8HTy z=YasF9hpVh)!`?O45V;lYBDtjt{o_w^^DAYO$k};dLY5hXyo*a*wk@PN@}kPOEf0g zzk6EiYu0N*?g@t37n+Ph~y_YVH*)Xj-|coGpr($5Op)y_KVy6PtViRsunW>GTqGd^s@u9N+t^85bgHb&xSkW zzn8!t&C^w{lKJUp$&%UF2$GPji>wD}9mpSQ-OYwC4 zpRmN>Kf$UO-=l1OH&eGAMrYsM@8}z?e%v)x^|^28p4ttn8`jKDJSkbVLBp17tW~mR z{{G4D=!bVcvI|TkvmW-U7EUR>yffXx6Viv?l&PQdms;vDSAV&(z$k%r8RcApRSFnf}E>zm=Jb zm~7p5*;GvOr!np*&v?yUXPdw)k$A^1x~TsbP7E zso@{`;Wck7>Sg?@l&Zs1uUvSm3Ql9?!4afBla|RhgkLHuLYy_E{yD%A}eC zTccR~k;i{8s_bui@kZ9ecEeuGK16_lSZy}V?LVK|J>}&mRlRrkCSim5GvQ7LKQ-)6 z^0{)!#6~gxnB}ocnmgzL2jm_^+}xXfkuu}rtjH)&&x|hhyW4}@fo@HCUTyq=^!mr0 zPK9Ig`{f3sPF_Fr)TAQIL%+H-vNSt8IP`V+MGmUoz+v#l<=Mw_Rr-yVyYrr`RiEB1 zK6Y|%irD_d2CRVm|CCBp-T1Y2$VWFT2JO{ZhQ=V}hY|MRa~&X*`}8@8o;Ps{PE)L!gYY#SE+jIKrhGVys#}lNUS+7-G-0OYWyF#o)IHlw2V<&|U6RVy$d*MaU zpeE<60pSmAi@5HhSxeLW;QFE?#U1_;JEGrS;QN(Yv3Zn^gJfJFyFx$~t?T!W5S9XonkXKNi> zTYcSo&&7wHw5c68vgDjrsX7H+bKCzW>Z=JMn7QFCcgQa+XRFr*oj$kmtopmHy$SgH z7Exz|s#V^Np7hi1rF9)7z6aXSzfkL{W8-+|{|B#@ZRoabe(~ba+Ko!NFPaCeQ2#kw z4a4&asg6>{0JVl^|!${TmHt(pQ`)au!2gu*uzo=-hMW$DlmZw|JG8 zdT;-R+dJkMH|3W54mw;v;r8A%J@t}#ujO@iIPuM`2f5WDmO-mO4wa9oEs!qUyA`}? zPOV`f_e+`sQMa?By#3#w*Cp}`xjWMwG(S3_C*+kUsBvhumohPC8_$2HT5mbrVscUG zlg{Iu>W=s~k^9_UvRt++N53(PT&sZ7x-O;tdShatTlTv{E{-g!`xe%tsS`$TRN@}r zSuQ+!oOBscWBpo&!_qlIs~11EGQ{T!P4i3DE9YJHrn1D9%J!wFWIJHlanXe_Nh^t`EGsEd(o7FH`J+_}aO<``)_z5|8#A z@3LnTk(g*>)fi)B@~$#o&R6dP-O-pY>bVw54#s=77@LuMvyY}a86DOfd&pz*&-*VfFH@e}?>EK#il`bFe$Yo( z{rOPM_&P96F0=b}d6~CY?9`Qqk-x@tohvwm>BF07pT;XE?Zkg)bW5iHKmrVE;7}O7HDW&|plqS9z?Lm*!MHe4zh;=c)LVFFo?%~lO%;Rt40UAJ^1x*?8g?=;6*r-LM85KQO+~s7s$H}G z>z<>#ao~8P=`ZWoRPfa5FBj&db->yJZn&g%W~S2f9EWz?pMja5frS5ippy0Jmy*pg z6>A#|Mf1CSEBB0pA?(1R3x7aK;hl<@$=*DiNS2?D5pqG?qMVS$%5NiVE@2COXv^hz z(_QSnU{`g|Fs=~&0vJLyOyQ+{w7p*P3Tnc~7phg?$BIp{tYJta!lv3Mz`C%&*h!*{ z#?4U_hDfH^*$Qk?ixH!`%*|DP9%4>sZ}EH^p4H-Y@uzbglS^_3zGqB#KS*LwHbnEi z;P`+IrKRKq6B|PI0c?Xyc?Y#dqy{oc{s>!gw4upIYGBKxLcRJrBrSzxf7zr$JPCD( zHwsDqv^t~-)ntHz^%Ixv-yRg25Cwv6betFUfM4=$hFYR-0R@O`>>&IHEoU87U+dQS z*DY{TuCG()y-v;79XL|YBgf7Kp2h>--~Wda)#EPsy;JGeukiSPqD1}Q$lod{{9p37 zO52VY%1B={HGCsY(g_OdB=khm1Xf~n{Dzuu{r=(+b1IMq2y?aLbv;cr<5ZF&UQTbY z53}f|SlMrLsHQ}^sqmyPLRkWKC)A}|wRfJ)ChUxD3Hsuka7b}Rb5^+z` z5q-1y+4BV2^vz)z0T^qbL1f7%ch+a5qwLb8xSqcy3($hcxF#@l&y;8-?FTg&2SLJ{ z(TFC`QUkq%&13IHnMPcP8#i*2W-|&)qw*{;xm-}aWj4(i zg<|%OU_#xn%Qc!L2Wq51t_3?Khjovbsu(J;)XxT4Bu}ZQ*c+aLiXuENe{C71qHFOt z&CXa_?6+y3Gda(*OF{KUgho21l0eL=*@HnH8%OS-i8?X}py31uHX8}S8^&6;CE!RU zHW|6^`9rmK8_N&bXMo}L+IiS{Wns`;p2{?qt@BecLYYRynG|0Njd>6Wy-7I0T+;>S zx2Cuj8VG0AQtWeU<-nI#Cflf>4dt({P>y~QD)4I=upyGWVs~PjtC?7HAS`k;NmsJA z?e&azY#_(apTm4y*DZ@N(|3KhMKUo!@eiLB(`AHrwb3K@5ygAaoihM{IXEc}!TIBR zg=+o6{XCZ(bzP6%O0E}f;3|XLFn6lfb zRj!wgw+tW8Uz=6nko>MC=-!ky-Vn~Js<&3G%dSwaR8TX&m-VjzOXEiv*TmMGUxu#o zSWUV|IQBEQn3RkG;{7y|tKRt|SVf8rF3SL)B}DKM8tUC}O(ZfJE$~>>iARWLy`*Moo76X^-l?LqXd2#hJ<-(OspP(rka=tNPBPDE(vHp7eCIev z_6%?5#tn}kzrU-phkw{$4K3BCZYo~F!F8X)UHNd3C<0^zU^nMW6sK+wsq8I;zB%V< z`*+LC@M!h!AOBs^IexXbqn+p8P^39XQr=)=45j!P1_iZ24jQ=bh?OB?FByAiRUueb zaod4=J1%D=b26!%X)%2qKNhn|${CW%S29l+%|Id}x^sfyc)i+B)_;*u%ep{r0RM>4 zzW)$W|98e^+8;h3Mse{)br#b4Ua$^EeK zKmvp8OEF@TxC`q7iN=U95`2R`Jm14r+eF1$DMbGw> z?4c$}pYin`_ZK|DE(ocU-PKY9+o)##<*pyCxYj{bPsIbjuY3HVuh zpE6v;c^`5tJGDseP{V{#&VQ&JSjjF*oxU|1qp3x5;R)d}TATc8k$G&TbD%s9NC9CB zC2T$1o%>Xi!I-G$mxqxu+tto>)v7){&e41^`@$^#2Ksra3}Q?wz}FktBUwv_oN^cc5e%6- zZ!$3)r#=}<(^PujT@gNN`(J-wSsgAg{*OGz@{hjzfB*ab7ZM%+U(J^P=(MPqt70mn z`G5d`pDN8c#R+RxXp2dN6{=9?h>=yAo0k_#12=G_X^kZ6$CC)cFSqS?Ef!ummrFh_ ztN~ICAO1al!Cc_ob$x7Q#0L_q#M(77x$@k8bkBaD`gmJ@<^?btQq@T$U&$*LC2(1y z3rdbWa41a<&BC5uISsWjQXs$#OE>p!8F$|*J$2#Wyb2QK-zjm?ibzdoMq15gqj1vn zTW%a72YX^`&u`Kf*%QEMB)@4qFVaVUl7<+=6toA3JL{KLN?bW4wAgk_3pfjaiundOQgszMkpwdJt zJ?lsP-AKmN*f^*ftJZ94KQBiv0cYf9F*{JGGV1h?N)gKrjl3-IgT;)nkUilE4DTC# zEXuQU=yaE1BM+;|)Jz~a2HDQj`y}?iKDj~`-|b)W*B4Ng+cZ=&*gg>xFoLxJR}?!c zaGs2`R2Qtm&c!`clW1BY4_H`Rt3Me^@T3e5>=cBu$S=CIc|>Ce{hsOR3m$c8EN_7~ zDkC-Bpv3AM>S%F?xzx5U#ZsOP!iFddTwjqHcBX2mX;nU$mO*Z}i=Z;&B7`tCwgJFi zp;m7)#Sw;x%xgSVs_78=fUxz+3BlFibGQb7ye!&T05Dp!Iw00*dUKxJ}hH5pH> zHLKhiS+g}jH#5Ji6}qX@(GzI$451wB z+~?4<19Wn{gMq^3YYZr_6S?m|5Su!VA{T?{fWt~%L=VMhQFTEc7sS}RrE&|iMNG7} zQetvMbJukKyz6b^G=d=$qYj%mkWks0iDuGM9?!ZfZYMPQ=-dQSs75uXPiSk87i z_DVdMH9C#J^ZIgq7}F|;wO9Y~?v3%)MP9O<^Tt(HTw6ig!UYG$1f(jndndjy38t#3 z#;Ci(r?1y#XWb*Z+t%6#UFgM`cxhS_JpLx`^c89B+5b3ya$?!$dqqCr zfvcG4q5Ax=-5oNG+_%UM-I=^-CCCi8NUubg-Atb-mFuVfu@Z@M;fw&GkNdJ#wR=E3?Y-@j01BLx{`>_3I3I#ndWElpFoki)_duq zV=Z;(+_Gh6kY&P1xV&>ITSND{|I?_xzw*rGLQc&3mYD}5yAQb?SBBSIA5 z0mOM?w*1uZzdaFdqqze>IzyB&Du`^O#SU*W?4LJueefOO%b^O`Fni7&y`4}Nb`Z7> z%e37Zcbgn(r1DBGmd^0bMCNKcn#FRnPF1Pwe~{?hY;iywU!737EhmWlJWg8T&*_Bx zWFu3nOCz-$Ik9@?0J3HF1H6Lew~Ui~R?oAfQEzrv1&F%q9TVe%BU<*SJ*#%QA4osF z9PIy?9=(sxT&;A!QT884PolD&UpSWCKNEX>|IB-!VDtVIG5J3hm_5ut&4c9sV1-E< zyG!dk89SKkTm5_HOH$IdRZ>RMHtjl|qORN#7U|;6gnCz35C_JQ8@4msdF9cdlM;wR%V&0%?6KfU$y z@;Kl3^VPp#`ojqDYL+dQ>az@&3)H9DY@Ep~*)x-uC$f?<9g9e@*DHkK5zy4=Y|~fM zS4)g&CuqgS5mzi&tzw?yz3Yt@tyXU&bm|Wzj*Fat032V7wc9|p3(u))gjp))@-8ZB zJysts%CKGf6Of0WIL<3Rv-|7e2}nO1WWa$G0~i5vYfaQGzzq08qIvwj$lLL!o6qm( z(pZiy74-I%<{2y*Ne*{9M1woZE+HBR zRdE#S#Pp%dcA6D> z3e7}yU-WS}o4$qie zPG2&Z?V?_+u+b>D8qXT6UCgp*x;UK%h;Wurv}(eZlv(+DXQ+{A>i0oenZye4>LkQc z$B4UuR5Yw$9rDay!bG%yLb$cwcLg+6kM=iY`~3B}jRW7y ze`Ross?Ix-E%I`_Vn@^&sOlh3XeCq~GA7cH9D!b|TjR|p(;xlNOMD@NtI_xM@I(w% zlz`u7#3iO#gf?Lgg32>6tL48TM~6<&M0g8FibgFz74*6Kn1M2O`fTS+tVFl$3j29# zv~hyD_fXHH|A79sN%|*YR{20#AKH7fCHu5*CTeAq^f^B6I$7ARCThD9$&gccr8jFm zD08L1*oIbNB?Ri}zLLF%l_;n=ZU}9=oV;$iq%4fEWNxj8zQxPUW*3Mj_xKpAyN|AG zNZc!+`36vCS2SbD_Q5-{1L0%5s-z(c0EuJrMIcw+1X1oMx#15Hl>kZZ1cF$G`PIYu zA(Hxdol1mieDy4k7hdacdrLD_$2oKZe4n`!C$p=VK`5aIPn3P0zUZ?~ z=-x-G+1;Gk#E439+71nM(!J=v1tVn+m`rhifBo_S|2ODD{J`t4U!X32Z2#xtKL^a8 z^M7-Fjm&8OyVvqh!c9L93Ym#I*gD$@yBV74+n5^v2eg%~RS`vzd_V*Q_VUEYlTa*c zGz8tk40PoxDnt3005F8e8(WAHjP&dO+OUXOz31w_jb_h0Nq+Nr%J^k@$b7CizU6zo zO<0ANNxFVv|b#_qw!okvZ)iSV%aBH2=|fp0<#r!eH&zSl(k_ zi|Q`Ui{%yRr2;aLRz3Pq7e$QtiFI9NOM(m;zmeTs4^FV4<>KggGXx;vJ7({5acnr$&qdg>{P+O)O(%)< zl>DbDyQg;Gw=cXG-(6Ot!djE@Y(st5sbn1$W!E9cE!8)%(Rv~~ z2a*F?x8aR-P9NMGTBe+Z*dY3)NM*=r^$^KNrWl50daTd`O1%Ox1)|yXO+Hm733?uE zf7P;9K07yF5*X(l9Jd}O>K+PJv2oS1LU&kV&izCOD8|aN)9K3#$(P4XOhr)7kkze+ z0X9udt1=>XQHB=mmV3CVYAYHgvT~&sywMk=bE4?U!&B^e{b_;rsw2jGQqCrv>Q-2( zO$$q+Pr|9O50CwRBbEb*>>SH@xa@wA{Rn0QqPhbrpyL+ac924PR;I`^$yo^e{W~pK zjjlF)Na7^N(^{K}K<%j<7q5Ak#ZkK|L(+cu2z;=GU`c3qwWDeCjWEZQ>};tcBcp!Sbm6m0fhAuV z?$e}6$xET%P@|*` zjVDq-z@rio9~hh2dQW1OXux9L9*WR|O?rQ3%m#w0?{Z!g$LAjRPRgMSF zT-orX-~A>3>2Y-t{|nsdesaTcn%i;en(L~S_51Z&6c-R}xLZ+;a3@QF>2HK)qlX&R z@!BQDc#?+WB->b0IeYb4HkEQjltijPwr}rn#Bf9_$E4$X3^z`)!EeiRdEuT*Mao1t zURGpf3Vlm~p7bIry?dp*S1bCeqYMq=?a=;@_v6g&vji5!a+i{e&Sv53Ta-SiZi~p=bk9=2oX| zoLhn%Q*qI*o7l9f!zr7SdXzS@yDYyktLw=3U^c`{O!Ahx_NeqbOfi@bb+;Y~!WsqVP1>v6!+I^*nBcFpW zU1|lISfOJon6mg$2nj@L1$){yJAF4gFvbMYFNA1sm}>L8E#`@;-4|Ng-sOFnFM}3b$^fHk+(v^Lo`*3plQu{tNe`{f3O#BNC^H8RNce0V##ZFH{F)4->KEC}tT zKIECF@E=3dXdI-&MdlaO*v|kl8b9HD3py zS?^7$M?t)-jLm-IekG;7Y_$ETJSoqW5_eu@xW>Q_LnKjPT3(blURC4{kydMlUo+Wb zScYl#n|c-?AJ%&Ci7I|xozFMT$O6L=Yy6ohdEsxNCdaG3SXEwWmjx#cau~))a9Ml& z=~~?=Sdu{BLBW)lu&ejrE%G=k)RBVmt5P;su#zjwz4mBLns~Imo}Um*JBB0mv}yD? zP}^WcgoR2im2@N2ax=Abv$r%!jZ}*CIFyxm0ZziW)q11#W(UVMxmv@$>Ukl0 zD%vimb@NY3#mj@&7AQOasD12fItFX6uPO9*!Mt7RHpA47uu-hc?ma-A>gAoc{Klm! zsiZz*l`ynLtYV``OEse>l@<1mw?xm3k`l!dEV3pu&ow=0`kmqB01c{|Ul0anCIELB z)RF-%Xjhnrn^t8bu$AtrwhCvFm@MwKTc8))cH~-OO}}s zDTcZ&gQocpOBG9idF0KqAwgFpLF17@Jvz(Sf=9?bWxJc|GSGJpQQidSAC72<&Ks-IZgq)@>8x{&) zq)fOS=xQIe>M3mX%t`A30-*xn2U7VQh;hUL6xa8r^TLohvEnG&o#b6hGTB{9fGe%I zG6Ai~{z9(8TV@XD&a!11ow8Uf!tnYIA&WteOC_}~%79|JxyEMFsAAwql(In;wJC%; z6*SU2M<$Y2tZ^0rjr7r}1&zzp=!Y&BG*EyhEkd1-Q07}}`0ZXtCv!HP3fI0*My;=2 z%a_4JUAS8UoxBc(NmlT2zY`9WJM#{KPrPlsLuQ!DO(@C6G>q0E#2an+9}ev|nILL~ zgxpN^vjuXo1OOH&TxXikC@g0)XL5&2Bpt*WYI^ku2T;tPL^68gUd;uognU}rP2J>; z;qO*Un`sSVtKrsBgLVv|N&)?N>{QF(OC}$IREUJ8jNbE(bk{v=c;3P3k#mi8+nXYJ znX*?gjN-7Fic;unXRy4H3Ku>-*Q9mQ%Qfc z(-{hT(<1r>s%f7PavAR`FABDoZq$3}9S>o&rg6DW(?l2?pJ2C>_`-m7~^(7)9I46WM;>HLhQuy&gh$!Z~Xc z(v{pkb=$X!#@w^*(v(d$KG=$ZG~a3B%QxRJQlf);7?Pm(ayl}EciMZ~Zp>h^k{G6M z--@5h_3gLW^pT`*OVu-;^kZN^n%26%DQ>v9og_oHIKN@BWcLmU8^v(3#I&Q*dEEjG zP5D8WdImp~3a8Eso&mUI_6rG|2LwR2Tw~#gnaI@bdGnFX0huELFwl#OT;c8Kymq4X zgQ0bjnkilvJ-*+7^^VV~XQnnY@h|Lb`o$nVd4lxYcX>IN@9xdp#?B z@l8F=Qwf5x#w9ezJFeHH_}66La7QBOAFR}CdvRZ6ob9;n$)c0m#WO*q_LpYyCJ;?7 zvm~rO6{~fJ78iwdwfR=-9z;H;z*&hk;N&u46^6S#)R9^1gwL_6ENZkAJpSdb3@UG& zid}**udFP4)O0HtbwPodi#A6(v? z+mMDe(Ry6_6Mz16ci?QDf%ADmTdJK&?ei)B$^A;!n(WYCLh;NFLFc+q*J4+wPp{wI z8N<~fKBBZ`>Fyu;>SqC23o8@~noDu#$4wQOl3Sb!&&gd^GucpFZue?pp{lg-L4m2m zqT{Wz=79bV9)MXz9-biWH&l<0$7Gt*`O&CkanYjFqUqeaOCMH zCSVBvPv#`iKbVsO`i{mdO#iP-uWhAhjONponUz&_-Xy5*rw@84+T0}etO#NFO-aWA ziO9+_Y_M^9s!!=;ZQWj3Zi3E00EZ}qD8*z#NHm3+Z%~JhM(BnQek+mBI)sUcXc#$5 ziD=mK%(*!hEMbt~xb>ZV?VWx7u=R;4`O76=QQ&t!3Nz21I4PmLG`Oci>8?ghdWKlR zewGVy;cEv16x1ELvDB?l(n@SGrIUo>JQN9WI+}_AMlCR)Pdw(L84-#&DQ+EXI<|Ph?dlGdg-;FDxa# z^xD0 zAAGbWO}xGlIgH4GhWva&eCpNwz&wlqW;E3#v+DRrJ9l++s|8uTU|(qzE8j4M!Vp4o z5Yd}kMT;Cg>Y}-@uu=@O;x~jQI;(~Er~&TRtGD>LhGeFE02mzu%xjjNi^Fhil#2rh z`;2!xY4U)AAwzTOqL|i9oijE;_Z!|h1xx{=41K-d9&Ax^y!zDJsoSFosjwzW)N#=R zhUDOlOhrjfepMZVK(qnea8VY55(~Ks*rG&7V5h~-H(u?NC4Mp4`m_O+6fY+x7#W=; z3y59O!wpjYbooKpNzzH*6LY>K;8B*YoN*GCgeXk;LAi3fpi2ATYZaExnOI1e0N;5K zc0dw@8We?4v!l?tvk9bOfsIP(l3{F@N_+8B^hsIt>Dmf}qZ`<`(q(J8U?D>CHr?&+ z;8uiU;7-nHEcROProP|^+zZ6wvWSP>0_E;F$+G&Nfq?*tv+GhwWW>t`D^Aq1_4v4F z_+tUW%K$7qP>g3|TA{?pz7AGL%r`(6t$Hp2Z*bzz%hE~@l2wKJhEBgV0|XLgs9vBP zN7lCe7L6GfD*FS()u))I^@}&@BI?3B<`UBgti^Tc7rC^1E{4>ZTB`ds@HOkV+^wc> zlPfkDUgemokR3Z_n5^|!0xVC@0vtOM&+W|*iayq9rt+@-Bu)fP?T^OXGfK{B`96~6 zmX5A~QA%4S@KAGZIF**w0$bbRg{a`ABVA-te_JF)zeMY+V8DZqu+f6xpoR zU!ASH5QA6b8cv5>m7=HgFByKO9#&V~qoTC;0NKw+KTt+Dny1)xm~I%cBH;h}%9*S& zTcf=~7!&R_d4YN#9}IcvkU{$eGt&e+SH&q8*dLfIQwMx%f*TYgrygTybSgp{O&G}& znTtD*h9}kK`+P&do|Gxw;mTZMtd)pglO^LeQxWSj(XK2BbZL)!B=*L{Wf9 z!%>!xM4;tSZobw)<(_vi9fx34lE*e6H^mBDjV2v79Oyoj&g;&k@H8-1q6?6?U&ov|@rox!=?6!OKDn-P zn?7GueN1=TZUdr)ko5G&Qk^6fn3oum&x;5D*FYj_gDY-TkI>3TyF)3BIZ*8^wGa>$0*Ee>YCU&sc<1V5dc=*yar3sV`VU zBcaK+k<9|QjxzZ>dOV`4NXEqL0nXeUpANRi@dmuXMi_5Rx`zlQcXkKsT&iUmQ0JTx zaS72fYIhvpV^zc-_<=@%yo8Di)-q}Lj=)+6X@G|R+jX=>Jc~TVSeT+1s!%76+3~d4 zUyE5elfx)6x0*Y~>2rsVH#dROD219UYSuUAqsXwR6}vS$cjPhEr@a6S+2&xN8lrwg=E|XRa)M*6igCTb?prU1BYy zPT=jQE6OX1`ZqhmB>^P-dd`ht(Gq3 zc7%^T-=^LS9af0Dx-rnUW^aXI_ko48A0jPI5!g=L6U~CgU%Wrk3e8Zk-oAPtsaXTt zCm#teI8O7fDTk|oxP3;LxyUo7n)?))y&CpPCi)^+6S^mnnw9nwLN6MC-rai^A4mb5 z!!5!{-TDmhUkltgMf;pfw>{({E;9DEq*&Y{T(doDfZ5oFZ-R^^nnFMi3UbS{VLnhZ zra-Lb0>LFp{nY$bt^8HHzfCIec!w(x4AKAjK_Wt% z0eGVk59T$*r~?T$l}p0)8gk+5;kp;blGqNlFXU?2F~Qh}3t{SiTy``$w%uGECvn9^hA7ZNEjp3rh+;b(NU|8B z-yfn6KsKsiQ`sC)$ru=L+w%?>lLpqbwapG$z;R3*^nxrq$qTn}`RjI;Q-rnfYuIzC z=ia3@OO9HB+U_?h4WAt+%0|`VF_z8J+C2;@xJ=FPR9Lr=%Q#AwnI?x@WK4MggEz_{ zXYjUmBFwqTqW}=NJE;D=IOQHe$Gxe0_C2E0<1}*W`vl` zXt+IaTfo65sC%USdlb4}Whvi1e{42A%qg=_m2Q}l$~H_fKDFu9YHdh2Oi~hXq0s)4XrWRPAS_Zsqb#aky2-gCxsxC0))$VJiy*5s zFmNXbl?VVR_v6r|ESjyW`PB#rMbiGvF`A7G!=t{kkiwEz)j%TMca1Klf8n4nX)p1BCa4jN5d7|GpMJimGfz<%sTnIQAVs z7QwA-$)%Qc#k%t2KfUx0%e?z-GN7ZVQ98?Fc_TPAYeM8ke})z2P(W}mUld*HsHVzv z>P0sy5Ni{PtghA=fbAIrdZXbvQD{d9=#TILbsBUU>;UP66GqO1OzElR+Ri(0rTWTYeo(+JzZ(7_q|!PW*@SNWOBi^6gTEZS7%4vt3~v*5Hm=9 zjpDX1cs}eRXHMNtGkoef8ZN*bf?esFflVMeD?b|1L^7lizS7|TVcMM7-f=JwzbdSO)rmH3PW2G!7BheX1B991UK0iIG?^+{m~Q zfS*AqJT;hwIj|QJ@fyqHClL={!{wtzquOT zuh)UYy9Y|LV{v{_XCw0llKRR9i(DxbE4>j-FGpurDGx(JPC)?;aY^B1qdq87b=r zRZ(R+pFm-FGsd)}ff}6(Y#wk=V8a6hEI<(hnm2dT{93JbL!ZaiP`uTAIH- zQl=XcP+pZmd~W0%9t~9Wb+-8ZVXHnlmn)c{5FM>wlvv&$w0jZyl)NSvSZpb-t`py; zbeCC12pa^1*{q}__BBK zTDfN$5E-DLyWVRfK~67~c%!AUMu;qZpUu_H1sJ$GP${q0Y@K}1RdNwy=^*|bteIHE%5x@f^MJ)w*3oi@T5ZpHPShkk=#_G(J>(i23um5%c%?Sc zYhFee8IMzfrIv2;&IHY6sH);3gU3qSt!JTcFK(`0vjGx4Q=-^Qd|9p%q={Y9PX@Y_ zHya#`U%n}HY9_!qU!sm}K^-lIs#K6X#;>aov@o{8^fYHNd~Qr6*n`6 zG1{RyytvYbxUZ~ThmT;BK&6D74S9JEj`Xi=d=S7Fptu~m`}(um=Lpb!oT2?^NC=VQaK^0jdB zu@}F`M@L$X*RE%wqhc=OW3F$muClt&#{kW1@UXDaSL&x{W8-3;Q$R(^tEQlZH9<`? zMMFC=K1B|71bpvs4_P->&wOFv^o87qL|1Qh zVa91J@hzZy_qd}hxP*qbsst+8*sR60WERU@soz`hmL2c~Gy$sIj7#f>au&s4(G2u z`dofzmq}}&ifL#j(t6QcP9Z9K&c6I%a&IDLG6U&am$^6_%;T4QZ}^Rl5a2iBB}oiA z)%-jl_-TvtN}qDb<&yxxmXCbL$(HHbg#N+Ih=`pUMExP`#w}5UShx~}XS18}1aY(j zMsXvG^NxSCt2i-y{L$!w1!)fuL53Vbp2>T5XOEwxM?Tp`}%(BD0ITM6d~mlN1hAZ-N@0UyHv3)07B<3Le2VX~T zOLL8AM}X!aXp6Lbt*ZU5%c0hVBFT=-q1Q%X!G5s>$rIV{2Ml#15>xCcc2Y(}NfVQJ zg`nC$V&*iG5E)kHIFb~W-93qsP%7xsp{_N{#x4-)@LBkR=gc?^9a%2~o)$%2DXewx zEnmM(k3i!BLfq419Qber(chpb45jx!#aTv_j_wz%q#UyN2dQ~`^Ak1)5>hx92bij- znLYNWh|P5x*Nz>~GRYK&SEe717G2C4 z5i@Jd8WVGC*pEsSRY1LNwPbYD`|8#+>Ktso6YHRN8y908Eq@^E6m%Q@`37x2W!4H_ zhVNT9>){NwTMgs2CvZza?D1TQcz$($@m-$Ry`d`hO}T~N8qj6O|CqGV8DX$Urt(O))W34t zMU<3V7FZWFMHF%JB+`q5$d!N`rEeW+g2_|aZ|b`$Vj54;#x38lC{%ABrb4Xo=*Da^ zV%9Wwy3eker}q~;>&mbqCYMomTqYtQa~uPfJB6CYhlU!*pT=_nN;}$(jATGqJ|-rQ zktRH>RuKyYR#;UFDP&l578`XC-ZXFIqfL56ELhtC#ACCIjE)?F3%k+A7Kv>PC@V|3 znKYbhSSTwQu0D)F^zTT0oOpE7L~CvQ?SRw}CL_A8mC?|E#8HRZXk=8{L`&*uWK7gV zpxUTZWYR=I>Znw7+Qh3V!Tf2GcrR-#x&m6~M`W7cy?-+=Yk|nF=?HWNI@jlFukGG+ zDmEMINZc&E`B5k%5m*{dWbQ2d=}{;exNKOAok&I?<333SGVAU|3)u01C>tE2W%0XEBJJ=r@w*Df`tRjxwm?vI zo}q4P-hQNyfImq%g6Lg4x`p2Z0A68(FA(E)Sd?b$Re6&3*xJ$W=D=@cfvjf4TlpGw z@~I+n*oSi#>HL;vz?H_OaV~O*mw6~2@l`p;B~d&%VBR9<17sSsQ~A(&fh^(f4dP7m zNqGS*5x9yeFYL|{+cS%M&TS$e302BK*2*NaEW`m#lo4hjbs08tEb~!gE^DP+e7s6o zd4Ci08zkLho=PY-D>zP7oFO)gj^=e91=_TsXL+0%A4}FxX&!Cf!rs6>rM!bY7Fkbi z9wpm`^Jcu0Z=Je{18^FY<^+=?PT|KnJQnKGo-}QWc_eAM_1&|w8nB80lVwkG4kD@|5>8N;6y6FOAN-wZJI%Pox@)`mXf?m3x*Kuw`&m#s4J3=U zS50Q&*Reb%mxQXIv;-8(KsyLT|LI1Ks_`GJwzR6vKy#8R4EId8;~DNt(m=Z zHu?U{+7!k#n4TJ562JX*iR78>%IjVqo~3Wk=BcMG__LBSd;B!{5aiA2ZT=^X~g{_ zLtGv$l2502!Rh%Rl6UjS%r%_)8zX_{AAX>RXW^=^(h*k}RA8BGGA9{C;VB0CO?5&O zHp~I4V;K7NR>?#*T*SgDQ{kCcQTeM6xe4(FA>lncdfHh+3PjSd*RV7LeuKCY38--4 zq0=z}_pTH*9ByrSxybRBAUAH(J%@d#!oF8#6*Oze3|+mh*`}3O^0Fwz6yvFG0;7zU z3cIeDBr0{gs*mNxlh?Jb6Y*^;*Ot3qXUW|E4`W{$9Osg3X^WXz7Be$5Gcz+YOBPwo z%*>2!F;k0~nHem$Sn_J_%-h|!J9BpBR#zA<{HsZ}yZA>UrgK z`A=9Ko1GviwI&5WC-Fw3#D~Q^;oCS94{%Z`8xE7}V)OOBPCS)y?erl0@T|;9sZD@v zdcFk+@<%SPJ|6MwE{566c`9!!xHv>Dl{(6ew%iLVxP-ja`$mN%(q5i>%ll-eRy!NK zptcr_FpKfmj8@XxUJ{^LT@qldZgQY=CDM&*6S!{&0wo-)USs+1?}>#XyJ*REl74~a zcp$oN(eT)f#s*BiLUI%E>Kyk{>6b-!l?RabJ4UKGMsY`D)L>DpF={oEs8oy8o(Lwa z{8-hULdOLt+V(3ukzs5!4 zI!Rstdm;#S>sz7ykveW_S4>20NnB4oc%vl_{y_C9@s2eR$IhR7Mi)^|#~BRzrJ_X- z$()!-iG3BvQff4$vhUshW&%q;sLtD$n4+<(=9x%_d&b$X04O%16F|JSlVDkMiYI#} z0Lf+daXRt;tGmfs-lk^~@ynOG&z$*xuFs_Wf2UCX7mKK-qoE^)_7NIP8Z3g_Um~bo z(wM9ZMWw1ugFN;*t6Dpgoo%o(EQyFKUMC4Ph5zY5`=!#M`&7kXt+qWCJi*NO@#?Ae zGQ$Px>mG<^#zn^S(famQ!{b4nzn?#>A($9NCKg1aF~4#0?{6CO3DRUd7_(zKWJOp~ z=h*s8#4_^@@+;W9xM!Hwq-7Y)2^}`Lx-3|>UTP*-k$Jt06g}iv7wGTU7KTx9mv9`Z zs&us);br3lnlS`36ya6z$WN=rnLM-ZBW-Qx{aO%YG9dja)!aDUUYjBAp{Z+;uy}Aa z&Y22v}~_ zaQxuMP64cnmL5;)*_fiH@H1%LIi{*u+&H0=t{iA^l&!(za0nlbl}FSPtrIlqP`vJY zFq^x5L&o&OEY|kz*%e1#ed&Ls_sK*UFtV?cUW&HNE6>k6FNEU@-i?eJp3DjiCe0$v zHb;(LH?jKb0~y67#Z(zih7SISCZo+%!H6@7D>kX_g|H4dlAHj@RQiJrJr(*mYv<{( z#a!YF=KbHmj3Ak0rC6J#Z`W`Ru604Tt5}4~;gyi*!&JLJ1m_~CLS-n>9AzJR??-z@ zZND$X=!Ca3MR4t!=Mr5Am<3f&(LyBBsY^EYt3TwhmRwKwl`&778 z95Eluq07}L!Ks&{6H=tK&~Pqk9Q(-u*AH~yTUPe;skjw02(O4n5UMVS?;bCrGIsq_(^)NfQuPgG<}T5^PH-#Mi#n@8b= z=Yi_F24zeX+LK1zl%`K+#DfL!;92?k-%2H&@}-M-l&VwNy7QwTJQ8k^m1tDE!1B`o z5&X&i;R0h{W9aV-!3#%qtlUxE+m_GYK&8iy_>v@7yK+S)!wJ)9KPQsvx~IL*hxJXY zTj!1OxUL1d=jR183(vBcK0gJ>LxThImm6ZD1p0SReUR^SD;jv{)-6bw)abb2}Up8sTRo>oDHKDkSPqq$$;8;XU(|A%6}$ z^)3v5rxYPRtPA8xhtk6F?cc03i2W_lq^>i%Y#=Z)W_sPaywcZfZhNU|k*Vuy}iOj%Nu+d|_{D_NxfK7*1{ zm@j7342@WDhv^P5uXEW=MROXPPArDY+`%!!okOEY!l1Y%x2j1pBjLa{rQ;Z9#cWfS z<>;8P8}6(|y7kl3Pszjt=NgYP_OdEV?Y3}|IMKOaLwy{JB9Y6grr9))iYH=F3i)S^ zk+KUnc-LoUMf7hoEB`-7qA1%xS<{*{FIO}*jG>-04Vf|(q7-KMOjle%q`3srAL6M< z#KCeTBg{&otU0czIKten-075|NJ3DpMD(rswm4uLpBYYs{nm--aZY>3Y?h+^@S@nD zVQ?oB7YDa8smkMT?U|qU$qcEbA2mSxe5%Ez_8)$Fb;zDiAo9l>ASPe^yx!EW(m;9z~N#pyJ-wt6w343A?eO zWDhPj6|^fhiUwk3>ktXy6Ci-85EjHCpq`@4jf=STRm4P91}12IRIcTNHSp^Gs;jw{ z5cVPPs2s!?0{Wo@0(w{lWeAF+Gx@#a|kF#byaD_>;dF7wnW^V zu2?S&jo!egv|6Ig05V9iD9J~AsMqcY@e9G@WX%qC^g==3=#nKK6_ZUgg2n_+6$!fh z%~qhD9Pg+T_tYTaOb1V{o9CNA*jB2KIjMB^=$fL{fF+yaOW|Ak~??Qsq1Btb~={CYj~qO-TxAZLmS@ec{E9AFgumH zdDTM~x{iPEe4KOa8lJc0fI}7NV%|e&KX1?_;)?(02m;_dxWOUj z={?Tsbk=D?5MDF)B+Imz0nqZ{Xeg262Pj9Jx0WH& z56E&mkwj%fok{@SEW0;H!B2nuPG$_9)D|9J(Im*<$S1?+rEd`yx^SSi>ClltrYD6u z44YHDszYdZB*33>^pA7RS=~T_r=J5LBhDe*NDzM{rAL%vWs_V>MJ^zZC!+BVgCX5lzc z01ycS=zVb!mPqrXDWT4;nKmXX~-42Dx;mqaCK9HJwSH; zGWD}FAF=@@ZkjYs^p{q*@5lp_31TPz0O!eC(6?>P`w90$f-XK1G6w*lH} z{Gb^^P`Z-j;G3^Y%KkBHep;)!skRbXEhUR|8tsc?W3yWJB~;@l=jtFbIt?@)tE`x_ zt_+PkNhV)#maOEO2;eUpAub^E&=s3+M^IAD;>mQDyiBQ5*@9_Pf)71VOI@Mwnms#X zn+<5H(}QE4dthlKp>)vW($k2Sj_h9D3WsLRvA5-tIf%xxkPhX-Z^=cyPzyVum9~P* z`-96LJR6;V@~)y)Eg4YRFz=SRCZ#0B|KA@mY@9Uo0{#vE9}Mda_Nfdywf9(4=PSx1 z%(OCO=dwR9c)Y0f%9Pmk#9vD1S2+jfRyl?S9BGzUxCLrmzR=gZX1?u3#?|2f z^^!y3jOk5bukY9OPc)3_Q02C4n3?GH1M`L=hp#Y)_evtRO}|^+1pS=EVG_Es z>2k{I5&&P#I%U@ zN+oaMydbZRwP6XF#J;HelVJJt-)HNYvv?)_B-!kY-Q4VJ#J9iu{;+l@&z80}LLKBF z3DSYJVGKDAr=JSu&fL04&y_Peo-{(8w0>bK@89B8gjd7l6_S%Zc97!!vwtTmv6l)? z-z>nl;ner4W+MpMHl}dE5m6kVb)h~&Yn}u_+(7DdAz5@X@|F5zr7c^!i>AChD~3N^ zYk~gbEL~B%nMc5+Iow!EN=m zUzz5t#JgVe`#0oMF;-~_fanX#GB+zLSEr>r+@M?RXzP{}d@47NQ;-R~_O~p+1OTxn zb{Vj7gS_@_dtcnhFa#@D&6rg^3fmHss2aIOljagQX$)zP9OhKT8MqF_Y}Lciq{s{5 zIS{T+qu7yurrsdq*s*WJdmKaD<*A5M$rHK?4*ODOHK>XI4ntr6 zPF-K?j$L2%&RttUX(NDj3vtzW4MuA0=tdx`FF3WOvS4e#~bKFMYW!xN;c+`hJ)DFa&}@TF=fl-xqKTIfZys_FV>cUjh z8?JuQ0_sTaVFHKH<4xB}Scg2#SRpiM*lE@txbiLWVm3q4m`3^Dn@CG!Sv^g)>ERwe z4quFLLmv#y`DtaVA0eME-=fDds!Vv(R!Vg_C<|p=b8pUZM1;%u*DJpbnUHuLc4;ls z+%Pov-uap^ol<(}-}qzYOrp@qSS86rxIB5he0eBU%-%6DTO5*qvaWaNA}@GU(Ys}u z)|8@$UX$hhhiQETp?@P+UMooF#{uGBLT@72j_*udBq!SN5eJ)5w0_-KH|8eBwJ0+X z+lJebMGhQ!exon+zD(I0NA(JOFphf9I(PYgu)UeeMaHBF1J1drePpK>Qk*Ov=$Vm< zI~6olAp$n6Zl~WxfQUG|!rr-j2cK0H1E3RQ4sixz6yuOkO5!=<$So)@KC^y@Z4q|% z5eeQcUV^!S`p!CCq~;u8oe`S!YcIW~L9hQFf7@GZN#i7q^nxbwg>7o6C0Un(@`Iux z^H1*C5y2_=18P^fU#VtJzcP$L6{(gAeS{o2)8U~yADxyuuNnXi?*J8;9rH`wN9F|e zNQp*`i&ZZHA6G#phPVrp$JQy8(mrvGZc5u&k&fRI!hILOX$#dvD}pt2>VTf2msqu) zRvj)v`u(?K9mNOiKk5+t{Scd8Kl?wu(Eg5N_}d=Pf7W=4{`K`wOidR%4%5$wBzE;= z=_9}|T#gIs7Z|RHqzh%QJLp~>scluXQ`dG4`bO!L$R3q_;2g%az5NPm7zz-MVT@>~ zYJNWLC!ZB_%0B1x-?S@DQW*`>*oMQJrV5$?1o}u%Y$QBfgr)n({ zt&I30FJGVr&;#tRicL2d9QwkUDo-5N8r}b;ASx^?`_cbNt{{Buo2nM$#Y-7{!szEk8zWXtr@CB@b6H%jHvf|MQ|yO@MGn=YI9bzf%SDsp zfm=6QR|?8SxEO=tZ#U{V3tbbAHagYSg<41T8~5AhOp7&_bUQdKScXZiTHlN(dadB* zQ>D=F`JHG)mwYB%xlg!2;mqjGf0#VLa>`>7$R0zGn!~jX>@eo%-yb$;>#j0j5rus% zg9AvcU%ILQ9k#TbSM#vDNm+le&tkyZYw5VR--37sq6I;@vH^R?AlG39KnrHNg) zkumGJ0Vz|#UX|#d4Zv|ch%vUWnI93fdQwm2Rjn}@TVWh-P|b`m}V(V9qh4TeRPm1X4W8-!+Np=sPAt&4-w z`l0t0>3V~k8m392Nw9~|*F}UMZ4_qc5H4Xt>06Ktl{=G3!9^H@l`2IjVt{czVw7ZV zgIIOHU*aT4@uUf1#*3%7w;I0t?C_6`_<9wFhxRGym-n}le$;)VQDEA*R-8b@ouIu0&FNdRH9W0rcz} zb@_-L!o}llgc=_-gSYE{(f)z(0Q2fs!2R^~A8Rhl6884(b9ZO{w;ewBf7EGG{JS+* z5m!}oXA%FD^^`QSH?{rOf`=%L%l9iH@y!=X)&zod6CmjcGO^E=426&a!Ie;v@-`E?TKdE2QlDA1T()}Iw-)X%%^+URH;4}4|G3u{qP5X|9k&*2=z^@Puq zL>B>=gUZha9G;)3#O6sMfUX#aNPy0l_FX)oOye1#YI?vN&FqXm61N;pVhHLwrDMDh zio(LRk2fC54UAO6CbszopWtt%-^ZP2Qw?sKAegCkt7%R?o&awSTlC%5nC3Du>Qy4_C_{sh)f4e#C!R7d*AF zC*sqx1E0Ily3wCS^I z@t1E;8AJQ32578P_Gz_gEE|vciEFLf5^GD2D_>4++mw&c&yB+rQhuU$Y15)pJI0ua z1hNlBTHL#;n|$xe--PxSqbt!shQg(sPN8{$V^~A-_Azc&oHb-FIX`90j&WMDxSN0O zui%|9zpJoS8VC4rx>IXN%DJ>Nx7nU7lxn6{<|6XFroKzTaE*N=RS}~L!Z`f+gou}!`wR0lmOA)I93qkJ!-u|Mw z&7-SxwGPYg>Qc@Wd6CiflkVX@%L#nYwa}89o=6?&j2)6f^c7V)o?m@KgY_6RLwQQ1 zPL^&M6nuqu3g?9FT7V5T>o8eWtzguV9eaRU%cDf9N#sT_q2W77@dl@|JM|jsywAU$ z$k5$bGn@G8{Xwa|Vbe^zetU)4c(zlJ6sUejiItD-=@$bJs;bFOEUaDN7a|>KKe^^M z&gyeop})*()G=#!vvS&4?7-E0#;V#wrB+6w7ZgDP15eFLQ(n7Tx%>Ka^G0o3NiUkR z$;8vIUU%&`bQ#lZ?}0J{PVO4}*=_k*>prbpiS-Tuuj$v$pY}szbFNEb_dX6!l=8a{ zdR(2d87mrpi!F=L}j$uTm>Y2{RtvB1_A)X44b!ewE z*ba_kK)p%za>i3pMDMjThEGB@mc(|qB(@f}yRT~(7XvZE+_7?m_dB}sdhbSPT^QO+ zC!ueJY-$q-vk8Mjz#v`-IbuKKMg3$!8YELAp882tpgW-1Q(9XIujm{DU@lxxCz^x% z3}e@Yau_1si8)Sz{vBo6Zd&M}qosZswuSm$PRMUiCI`y|A;}{`Dcdq1_l!t|R`oO#MW~WNJ?|7+&mj738yCKEdWW8Y{6c@RccR^9#f%4d zj+yT)+cJ|bDHy%C5FcmyS$u0N$Dy(V#S#!YZWB0Kn3>}>Y5`5+L3Ph3L{aO+Z`&t{ zPg`oGXmpE`NzzGyx_3yP|7;(Ui@BiGbbTA*z1tXp8-JB9+E+ta&(tk$x4>poM@P&f zlrJP!i2&g|enNGohQr?@>xA;5FhXa z0`OkuI)|-uCE;IzwKszyS7VEzeAy%i$1kK6pF zH~Jl4>5>q(;<>+}@GB#jBkJA3dn!IW+(=ZS+NI2l7jL z2ls~u#Wns;7j!kqmCVk2@8|1bKM+Z;<$6t^eUP3MLAK$1I0J?QC{UiDu1!IuI}SZj6(x3#IgYfuWbSQl&N>hL)iM&}{-^~9=PHwX~RGdsZm zGsDwO_Kc7~k)2W_Bm^mumCW``2t&QSttZka?%AcxaVGBF*)jm>*wN{C6OHLwxJ>LU z2rTEsM<6WpEF#GJEc0gOzCc~mBNP@~;-mcupTLY5+xA{!BW|JM1k~LytI)E4KdFD)o3$;JDZM&asx=XPs(??Hjuk(=DI2?Va#4 zX!geZef^M34>xesURVLIhXaMXW#-B-0`JAQ{$;G^uba+y!AkDnPXMfe{&!r)zrE@F zg@uJ&KSvlCi`yDm{Hy;qB*{QwUJ&FYx+Z?3H7lK*<9YM$yshkbz-;Nx0(>T3)3Ov6U0 zr;gB3tMNxlO{pav)naXI5{7nb%4{**2p+{olckk14l2ndpK2wU7A^8Iy@eN8L6C?g z(A9C|O>uTr^G8!)6ojWH$0G%qW@q>U;r{IIYD?E7N4F<%lJn)EMpl(kIWiPM#u&va zj;9spIgImSX7aU-^+?lvHg~jU@qQV76NtIyZgZ?`uFa)*aBG#PSSuErEQ^g%VdeBP zrB3q)(4iWo1DeciZj~0~Z_YxOdYn*6k6_F^9eN;IcAofXgrG6R7kw-scjBB-6E|)Q zSZ#g`Fi@(|M%!`iACw0^4HLBvk!-Gez|S->@|?gc z8DY7Kd3z34cBwazTYvay><~Lk?Rbye{c+UV0Y8ZBeM}&L>J0BBy=J}@38;FihU$#$ zB){gq4eiYuVGB4Pi38gb-okidxm)qm+_x^E%`bB=X7@Q5HS9I~m1D zM{e{p`fMcwX{A=1rc4=-&}`kJDYEQ@wTuzFRQJ=CT5HF7wAD3*$7s!ftX}0%#R$=% zkv^b{I>t#y)_3q5-6hIO-Gu=DbD-4ovX94ltuM9d>Jv>s(Acw2o)g8)Y+>Z7`t(Vx zH~|{p-93j5rM=qmq@63y$u~7FX+?Uz$_*yObfogS!Yv=vGN+qV!7hJZqM7=JyK;Cp zPR$@ZJelFB`EZ6hi&^2222$esU9&sJjNmBEJ2`-o?hse#$@>*fH~CEJsxwm@1VDe~ z`SDEEKz?PQz%|%rCJ5bc!&K~FQ}=<{+jO~womWi6~ci~fbogwmL!NH zfdKantj*$DrPu<(fk=SEvx8TALXm(`y*lx$x_tM*M~kvoz_hv6M(}|1c*z%rUCBQN zGYmERf3?-xa~v6Ne_rU%{+1&9w>@+J^AJ-t^K_N8vi~oyiAk829uPzt>S430YHDiw zs0pVeE)Rp~q!zBJpbN#w)clRsd}`fN96_pc)5Hsn@AHK~dZRiJ9laCoHS7IoJ!5sb zTTu?CITZPl zqERQ<)b;3!R>uF{W!Q^g%l) zii9bT*{>lmkyV~V`k7-(`P-U;4!J)#*h;zXT}Gd4KSZFH;LwxZE~jM2vmxoY^Xf9! z<>6rYia_9NJ~V?gqljTuo^JUnVKm4eQMvhsH0u|x4%JgLq!!{otaJgw`RMet8dK}pMp@VD5TDf9)AV6ZqItr)EXQ!o`A|u6K8W}JQiVoN1 z1>Pi{BY@(M-m&DpHi_6+0%3BnRB~p!ECh}Yj62%nAS6KOAq}zHumx0;U_QSRg@pcU ztuBL@%{~(Z2de^VEEhwk3r)<7;n9~j%!}q@4J8z{QsD>22 z0%uP_ir1XwrWQt#cFliSqU)fNwV1!%2dPs&(7mZ;8VeT$P(`q-6(BSyic&{F_o<#c z%Iq=U+C|We+@UZKYLL|uZ6|mlKi2{u#q|?B(c9>6aOT>9j|m*4TcTTup15s9 zH=qY$C|3v5v3SG3p~V-nznVYx3|zKs{EV|7DpZ?{r{WTxtH>)g@=IQ-( zvL({J&y^%LLWj=SHRnq)YuA*7fV4=W(CNbK1r;9yuhPXs#dZYNfo_YR=DGtuPHG=E zV~|ky8e&)irZ`<4$1SQSo?hi8P~Qkv2=1HIs^+zGL2&=-Y7(_jGO~(X8KC&P?9~`2r+t6hiOCoZ=!uj~%c7!as~zG46i{88qncLc7I^ z2wcsBQ|1xE60O4~UEGhKY`zqyVu+EK6wSAHwwRfd5`ymeGh+PdV#)Cxo6osKEVVs%&r4@o}wbU0*Ccv z(X8HLZT&(x3=T$gZom_a5GrpeAq7G8e1Q4nWn1rm;q1f6_B+W>zvTFo&H2x$=KqDW z|2LhRki=>EbwQ*se-UAjuhRL+Jt3)cBI}^3t<9CmnQWR&?9Q@l*@beNy(24>?$o~l z-z$LukUIs67NB7%C=ugh+Y>Df`#HXzogI+%adB$0$nLMJF=}voqN6S}({%{dZ-uQ* zIN-zIXY+JYG?d5}>JA;O$e6nt1Gk#aFoR>%&s)!1bDs{w>v7%W#W>I;Ec8i8<7G7K z8(0}kwHwWtRmu31pmg@L5H=N8l#tvTnb`pLRW5sNek!mfqx}{2o1tYPx1zff4ljKQ z2C(zNzoF4VI;eX4d;?;e~;F7P9pZD8rtpn3M^5aX(_mf(!sHk@@SW>&R?4|TGK z20esN=a1P7Y%Pu}Ls6QK0ReLTg_vby1Y7qDgo$0E$f;e`3`x!3fSGwghkMjh(B4~7 z18>shO+R<@>#{Yks&U(V`AjYXJ7zbXAm_^&)qd+T4)EGI#&}H`Zr%j;)um&?*Rn8R zcTT*m?VulVK-4kUVRud$6gz}0)5U6%969+thqd@ijK$_|eb#|{bWRCCdrk`s)*%vz zFKzk%Bjo8m>Bi)JhCGnJg(Y(+Gqm=nX@emX*MA+&AChd1J|TN&G8& z$Fnj;JXpVqz+;ahWpK^I5li5)`NZ$#9*0udR4clW;6yt>IMr`N$$Nu&`NHez$e^Q8 zn8Rq=wJ!Z@t%|80W?+U%3>BXg{?bDXC;w;chGKB|GJaNQ*ik^kTFTx}Xj}~0mHO>q zhV$ddSZLf**_HU;Cwdz4;qRsJSF-cZW<^`1rQsRA*dqr&h`QA5899e{b4G|_7I{-u z4M^0m!=voW$O^d~o&$}lahlt??cQo}|`Qeh92#!U{K#!(NX##Iii##s&u54Gm9 z54~;!55?XkX2efvl?E3fUYfT7x1}UDuI8?QA8vd<5ez}I&N_@`%EtbREIfv8`!1i> z9Qkhm=KstIlKeYs{xc^iVryk)|F6)p>Fw>Ky14kzFlBZ$ad05q|Ah%G)Z3nv8jB4| znoyAStF$m-es8>NVuC3O3#vWFAk5%*o2bITd`-pb!S6x9$jHUWMQw(rCjFV^S3RZk zP4%s&N3M(vQ}Q3%uYTJEc>*~N7I|IE`rb7beBL#DHxUGv-bjK4iTlCABegbmR4^@& zneW{%g^J~;z`{za#fG%FthsO3kOT6T!Hq7y-HhJAR`*$e*AWKDk z33>aq0a)o_zCet$PfaiyJ%NJEj52=`mP_eo$B4%{V2WCQKX!W(*&Y14L|IWgx{QAt zX7Qr^7JMIB4)9zQtWTiel7|HY-IWSXa*nmE55^d&A!;30UwU2#rpKcOX|;@OS%__2 zmsfl=yZh%b(886-S=Bst6!hB|BZVR_WN+YLLXpUl_Mz1%k-rdaMljj_Xzgle!qI1< zo)(38iBb=MMw}C?ngM=+bKUdozdrFB&&qm_={_3$6@y0?ofB>jAx{dIy9W!QGoWvf zbMhO4Co`*y-}``(Ba%`7#0!Ooonk9E^@t*CW*4bOMXq&+y|`=R~>P4gj?J2g~2r2ivTn1g)Jm4bXwlW}N)dh*3B4(=p0I( zMJd!OI#6AG0D{edoub8IBnp0laW~j#M;4g`-l*9f+?-oU3Tt7R7qubSoyyrk4Ns=( zAQcGAOHU7?4y>A;=BaS_wetmU1cwv`3Gk$gIx6X8j8C)1SK3%q(6@bA7Z-y`)UgBv zp(Vviz4+o_uNZxTzk4VSKZUHX3na=*@|0~m93vxFPB1s5GE#O!Ww?M3?&N2XIG!{2 zkMa;B+&F;ecwS8~Rv%ekBkXYpJAeN*Sru%-b+!UNc`-*D?a?6F69Ez6A_v5Qv=$>g z$@>)ITiDkBWl})Qs&no$$=3bw!$j!>vMd=g9S0ST3;erPIm$vsLG1~o)b%wV1ZOLIz9cM|tztuB~N ztUiQ$ZB2VU12H&7JySDe5f0TTpQ<|+sZJHCL)lHm`y9q7^>Xn0Z|hq5zjBgK#z@cK{?Uh1@>A zO{i()@0A_kH1t3$_Xd!RGwr!e{`+cgNiY?hgac^YHTx*h7CJvWO;LP}V9!Tt##YOVRtG-Vs*k}zXNm>@*!b-jWppqg{P|78PmPK(Hy&o+d<##*3i-(n%jtg`m@7YaJA~NXDc(%@cP*plhh{O z`Tj1c>i>wx?YQx#u#e-L3uLO?3gGclW8y8;Yzyds7CE{V+8F8^);D5-3Pj?yMinmz z;PY{wjF}5ryn=6RWa_D}^94!lf05C_whFwJEll=lZ{*Fv@ zZd(&lV$AR=yAfI=&)d5y?trCZYHcV$G|!Jl_iN3^ZJd*Pm61%J;}R3-CVjS{zDPTgqk$?ps(iEu3?ihu!B@ypC8sL>iG$Z)fQ{}nKoPFg zE``8V$)xBI-#4uN*4{9Fq?)RsmNK2GMONA>Cyk<#xc2so?rR2h2%NNeq-6Q+0aZ#v zsd}15>ZvZ+F5@4P;CmJ-y%j+VeaoAu+z)auQ-!D#rR7`0APA=+G=?TyKeyG13Nw{1 zE(p9~3PXBGD)^)F(hGeG+vx^gCD$Gq5xLvQ8L3n9(Mv3i{$CP^Ah=V!?R^qhF45(w za91{H6U)68SS$vEOnA-1l({B3&T?;Xn0KR+&*bQakVOqd#G{1#9}sFxucO6!nw}pQ zgY%V@6dITqW7Y2v=$enwNUntu-ZzjzSaX-B+4~bzS$ax3l(ZVOy${8fImUAp#Ie!# zxHv%XZ&U~dRdf3i@ixf(UjxU*5_b>%aX~(gUW5TaQPjG9_#kg|UY(8p^CN8h9qnvB;2;%OzPX5t2+CIA9ns-25x* zeaCRE?x4vwg}0^sTPxJiYA~M2Nux7NhSz+OsKafjx>ge@jCz0fGG~b5i*U*_o_y=` z>T+i;v%Ou2yv?uxd_d5Vqv3s3+;lOQuciGQ7$0wCfV$+*Hl@Ov1zL)L7ZYkV|RS>jAC84|7B0PU1@=M)Gd1f z5>yv|%3KkrksEMFW3Et}YgB`|hphsdjUTGBt`XsQs7ig*UoPIAzEcd_UN>#rzS#(& zA4D&mUnID)aLd&hI`)j5$9cX|+t6l=5(KwbNIr>sfRo^&&mJ!T1kG`k+Qya=9c0Gu z8I!}^ahru`pC}$@Qf!U3fbuH5lTPxZ;?|q=IUBzzd|W2CD^7@pGGGN1u(>u#Wu4&6 z>KPcAmn?ME+E-TzpLU;Po%UCeZ81UE8QtQLAmCg=iP29O*9^s0AU38!NBH6!@^K8Q zBo2bhBF2$I-G`Jwypsp4T1*~+>Sk`{=Va%EyOg|cMvt`}4%u0+2JluU#564Hk(+{GD;j-qZF&E>dahPk%7h5DO43g?P0 zepToU`_&%$M`vsUWiL+1x2DeomH*oSy;;w!m#e42$s6U zlRdo+HosHcjz~aPs4c;4ZbI-4y(Xr(NqF;sHh8IBjmOX4w@N9@7>IUJ*pJIgeNz33 zu~*C|b(>U1)s+d}2PjKNR_2mRZqbIP7IN(&?h!6KTuC4F%4qyR9iKgIy219~aD7=D zAusIWJFhvS+Pd@#^L6s_Q~aXwz^NFR@2ka_VimQlVX>ZLgAkcBCq1(53C&SU=j1sG z0_Zgya&KbUAo2(z=i-q~aBi$&V%(k4JcDB2Z7A!V-B}NhQr2~B#Q{erzv!IH=YD33 zHL)*Gr$TnKoER82Z4jG+GfZTNaXt^{K0iA7kxIOu_2TpPg*90N_1u2! zynlw*jUhBDF2U=SvAr3V%R3=!S;5zV;r7mwVdzL8^uU+0Qcj=%cK_k{@Jh@{zfV6~ z+3`zl;C-Tec52#o#HcqDp95lPS(?XQHSg>h@S>~SynwA~Y5Dmb&UN>qOLJno3bA)G zZcy1%-LAb3*6md*@1;YN2|VVFOTxY;buq91D7_DY@|Z3MoPnAN1~wt8;gdjfgu!r8 zJ0CEm9dunV!FWrbMmd`aPT|B97-oKhp=-qvy8JqwmL>6HTc|nsMyfe@72T@S>@6B6 zZZdSgEnR&(h=-6yp`h5 zpnd!+uuM6#G)PWmCITIi$foCa?r}Rd^eN}|l3}apWZmabwXJ@&w+C*&j*wXZI*HTg z<#s5&=2(n%d;n(%R)S^!6hxP@r5gkDrfjBK@(k|eq8#8M-fXja#!fZU2(bb(KiDO@ z0g+|f5i_wJXA;PtEen^5$SUv_vH z<5z#v9fAH{e>64DUP1q8jyH?!Vdy~|-Uzp+D%K%58y94g>S1?wu+b&C4Q11Fjuj%` z9(uiBPiY*VXroy^@E52p^udaiNn|{4(Y~D zS-DAbK!!G}B%L@XFw$oT;t!_7sm#`%MtYP({g-VfwGSTis*e%%_h`ml#u(_|7+a0~ zB=Yqw?Y-_fD`)$j{pJx~Z+ck3Bn_P#NBv*;2MjZ**SiUSMlRnZ9`0x+`K#wvFHe!d zRlvSQU=oXi2o%}wMbtxEOgTMthOdK|6g~Y9%HA7_Ui@^)Hcl~!%q^fEWwA%Ntq=y$BlgumBI zYw|YkSzq_lUWH}W?<_dZ6Hben?!jD_wwr!!{^=U^=7i(O+9RR}5m5GhlE3xyP&m%& zF?z<4fY+7RGUTWb)MV6rI>OGN(7L}Agk0*3!`S7xfYBID@d{=O=&=~d8h$dqagA2n zW0SYV1dc{yoYwSWnlEomK;%rTlaDaK1B4qW?PK}e*rM;~{UK}#kav+dewECJrSk35 z#S9hrNeeS(g~KK3LQC}=GJ&hiqOb5L)Fp`9(Ms(?Sa5tvAG(H3^_?sB9xqwSo57$f z3XLjCnSE>u+!w@__-$4f`!PiZH()}G7r|Gewx@3}iSvIE7wb{Bg$dt_&8?qy8>rD- zxzW>hN7%db*~1=|?Fj%Xq*r$z`qgD6OK_Bt(N2cqu>?e4=OcIhg zW+~>IoMk!M*9G8Spq31?zX%tCMUUhnj7CQ{_Bcz|GCb07TuOf(b;A?3u@eQ5fVZ&g zZ<3Ix^+kF)3Rl7DoYA+HTKWuFMF<*;J!0`e+bSUbwgS*r52j!6MQJYC)xLh?j=m=k37*Q9tWI(CqkNp72#h+rAim&;r5msvRAB~NecYytd)xy%k6XBoK?Nkd z@kFIG+9=;xUbOCLe5Yb0SY#_sh*hdre)%WMsS)dB2YA&!7ZJM|2%5{1b7qj9Eya9K zI&l8tV{T+z=6qS`-rcDD;W#yOHuS`Fg#%#`N2r+5Z^8#h=m=09?RR5|W%WxgsuYp` z>S`TS+^tUtetNS(BKAFwKtzYOp`BmRV*EGpo$1a8_5%swjg|4T3!U$l0E<`8!7V<- zDPpF0PJSYf2)kGB!7VY$4C~Fj%f$P)@zyu2@+_?C@KBeeT&>)!ZC1WP$lkzZIHpG; z(TA4U(73oc6b5go>mkrOCC64Y)?v*Gk$kv@6~e7Srxd|tYY#~robn1$eVo?{@$8Fz zqV#}{=75_Uk^~(1E9kmflE|IXuXghz)m<{H%G#W(*#`GlF$qKOs+QM7%aEVIpf#<& z-v&XDSlpU)VG2rQpL%3KvE@+w#qr=Z3}}DH;E>3*GYg^mfsNRT$qD7kBKad2K=FxD zDU-M=_HpdZ8MYw9t5@XaN+LN*#>}h{Wh{lNmr+}rOs{ZOgb_h-H=|}y zJk$-}>p!1dS;Pco76_E>a!-Y5sQE$};a}fcB9TS7#z@e~-RhOg$E=D29Z^KlzgLD` zGz{@L{WZE)_;@XEnue+tYkx-1Umd>c^$-1xh@j2p?D83N(F=ENjqG8|>~Z6{wTbbx z6V%b(bkQ5J8gRZEzvFiwc0*<01c)q3Y6x?Q2~lJN8m?nS9mx5ub2W_O(3ncrI!Na)^yHZJQS5peulMwW7wP=-rsTFqYS-Uf z<+jwWYlF9~;fGIv`RA|il7}oB@BGtCqpc7cg3!KqQz zzMRi%qo9jxE9Y#J(RH}0ei{^MC$W<1n6mzlcT*snJyhZ=NtfdO-~sKn#^Dx9hD$>S z+Rt*l`AsnuwLKA`L7nkE#!ZhC`Q$9V3_{9E2kfWTX6&uD^N;{u8o9?-CKkuuEHC0p z4Z8FUpS^~&>BtsRG#j5@*~1#NDz2#gBoo{EJFH?d+FX9Ouv=%iW3rlDZ8zwuF-+C! zjv(f-^;T84-zpT>dI@*GnkjJUw|Iv7$MCtzJ%dXUeRgy2KzL-k`clT0U$kG7kq$XA z$~c>SvFV zel?C9B|(hUA#N$pT?V?ad)FdvF~6)yySD66gejwD^HW(KC#Ndq&A_7WMU5u(UR5?U1j{}Rx2{?UG4y??eR(*1igBdoZ z%%Dz=dVu5+*iuPm;PcFtD?dAsbRnTAWE~iC=M@Z+8&@ySgplgNH87~US*;YIyH>3f zgSSD=6hB2~ld4cW6HOD)XoczlSh6jR7_xh-&nU&IU2eYVfLex$X{aWyA3{ zCPzE$mJ|**0TPoZEe7a`z3_W&Gc2Kx7!o_(uhi`u2&TT-`=c}1NNUWrBoIl=_dBMh z9$}k{*58M%E*4gzA_l#VJi88IdZU7A#2(I+|CFxb7_Wv7eg2qIVO}pFJ^?PRHg?( z%o&#|s8_0+_mrEW2zA-B4(h6E982C6~{B1W`tkRC( zVI@WIsnC<5X(q+I`z_*LwtS6r#%x=@JTyW_zyLExX;)@h(9sUcAUO7AUL-oElR?h2 z9r{Wy`IVgi1q$QzThfX2t&DYegVaQjpD17}{$p2n>m{i&QIhS{iih$gHP6M=edCVv zQnIb}T76^`Keh}S#V+}Tt!yh~fAO8Y6*qJ=DS{9K zbsZyOsr`v~3Or7eoiv`ZJ7tG;GU8I=jovF$*lbj!tyl%uzzEmG{Ww6!3!#6ZgihUy zW2n-AKs-9{*-9M;C+~3IQk~>&=UcF8fw26EpyG+4!Z}vSBT304O39-Wc5#ct-yD~u zG|Re{o2Sbr232rD@_Kw*Kv1(Bw=O%Uwi~vtn|ILm(SZlMyNB&@98D)C=7b}gr{0S@ zdvv)xBAlQL2mAJs)RC-LDQ(G1saOuxYwf&TQUF)Q=z3knNC!);m@rQAo{XVe63>Bu zV){AjLCGd=Yk+riIP`-=`oPgT0#`}P?bS>S1pEOD^}eE=l3>9I5}CT9i{$O86vJm( z;{{!0_GP`mG&4zbzuaI!72b!yYL{<07I)#GOI7h6M9 zQ^MUd91LC%Zu-frQH%srR(+Z?K-tF#8vr5aq$+0_UWSnBy#mBQL&DdlSO_(}wuGdy z-^*GV8J8jxbA=f=O2Y{9saS)t(MrP{2l8fik{&C2VLnORXfX?Ja5I4QrDdUM1l=Ev zaLX!~ekR`VM$pLlblH3mIx&r4h$?j6S^v`6HQQ)sob*PxWDD$8QH|*FCZ$$!jVR2< z9Q_vOUu}($x3$i8P)=MZ^v?!!BYWyr-Cl`px4wI^yQQJs(-GsTTZg{LK4gxfvLba$ zlh~O(BCP_b$AZP#tSn#FVs=A{z%Vf+cQ-5XJ@^uUA!Oj0Y0`0G=pVHZ>@iCfBy@sO zvFj>QwXo+F_kof4TH)u?I6n^=-QF4C-&74rN@}rqC%*V$Y#)Ix)I}VctegTiJF*8*>+t3SO-6)^k}R4w%s#XyjD{8b$Wwo-Cd!SMv&&Jw!)t5ML^ZLaC$?ga zt-u@`dtW;Tdqm!~{gN@Kc2E2w^6LA}uPOR+x2N>T1(_)qVqG}aGWElC^VyXTDRj0D zNd+G9oJqg34>qYNemTeQ)y`APuSZ|toWn#`S6rZkrz97OS{Av+d+45HMCu#xf@pbw zo~|`ueNF2HKEWcHP8;|?$qX$*rsj19s;%)YnAhlrJz=CbvCiam1~sj5uH<%xP&Pf+ ziM{*UJ;FPi<Ux2qD)Z9a~VsC_iUX zcbU6w<0Cy6b1cv1H#spwh*(zhj@b}Ybll#Q4~j3tBCQ>%qEgEWU(!|c4YOk%2ebq} z6!+wi`=cEu1BCrjGEnkkx-1+h!Nj~N9WX(t9tc3lAyK#?BhJtmO$@U`C>wPQj#@xk z+T}13#gdP3dt}nqNf6x(vf+lYtLyRI1P|bi$U-O*W);^;tIj5K5=(3&Ldfi-*-Ol; zW5tAti94;&J$qzZekX}Qmk4)?>EExUb$0AurrteAxse)^M7Uvo)zcd?c<`@D19LFO zIy(43k{Lr`bJp{XRacLvs7pE%gJ0R3;j$ETXwJC}gWQDFI=0lp1y{h0`g%h%Jo}4Q zeoQDr+cWy6D!BkjFTjh_@PH^+5z~**iAMcK4t7ecS|!sX^!BrU^-p%|)Rws6&y z;r1_sX1*Dj!Ku=y3A^SgxaMD5@;(HWJ)aO*QB7h!%4BiPw2f}rJ&Lqd8i{;zkeqc> zaS(Dsgb%Y_qo-|Y6uT}x#!b;)$GvNa7TrJDf1sBw+G7>dYAy$jK;91pK7JWds6_P> zz@SlAKRr6+o<_u$(+&c3;`Bd|KrI8I734%{dZV0;>oZj6gMFf|3KJML#+F3>(`(Og z>OGl&4*-BF`ae}#|E}@)k3wQmMMYUzdmC4`pVV_BTgM-{&cCn@^0V^uKhE!U6m<(Y zjNH&Fgg-=Peq=RHo^W=N^L)bQCZ3Y(kWq;CjI3pQv@fhY0E}lZzdoXPcUpha+iKbN z1z6gjvl~2~uCzZt?y!4coFhiym)`Fdq?F(we0E4iZI``fPqA<)+@9>dD{1$bV&&jL z`aU?nJFh|K9<@LJ;!P0qgLtnXQ|!J(JxBhb1!weN5SQl_Z}(BOCCq4cMh zoPTK&)$c+DZpbo%{yZ7r)<>Qdix|ads7X}xuRWP3`<~P>=qh-9hPK@Km6te1A6Tm^gP>t_AlLcJ-ykUSI)TGmtG*-Iy#hx6)j-YXYJv=1)IoL(#(%i4DxJXg_O99CJED~{>a9Fd`j z!~n(l$bH-4D{?X2q+DD9miPw7xM6p`&|MDZ5&A@Z*8T|)1iDT8Epk%J(FZZgIclp_ z{omz-X-y*szefp6mh|IV%tr?%9+R?`m2}D9$#p|UtaAGe9L=u-7^H`nE`Ag91Z4M( zky!7r4OB7S|4{jb;@yOv{%C~A{tw01zu!MU)K&lk8!Or$=ZvM1o*}J+gDC^;523+G z&q~BbU*FQm{-3u_lCp&jk`kJCar^uwO@ORp+*$;(`0CV>7KEy`|C+jEoot?}m7H!n zr`7KkP9qZ(G7A48*LPjXNLGY}KSU%^b>->;4ke}GNA$mC=bYC#L6ha}N&4Hue!vj}o#MZ)8D44+*}p`+t= zKveT$@Z!XzD>EhIjB)(+0wFH0!du~)-f{*BFTk7gc3O9GbJO*W5c6m9V9P=qQ8l|y zjFYP+FyTa&c^2VxkHG*BF;SeiK3@^~%?&Xo+0JaVDlG4}&6Y+Nj5RNgIGAYa1%R7l!ykMIg%P3=Rw=KDVZ@P4N}2>U%Wh1)U$3*90kBtIs-Q# z1;LdUOoLmFL`56T;VZ8AlDA_F?F}6091%=B6WA==KbP68-0!4H(&&VdT%c(RjiJ2b zo)^Tt5j$_an47;4QtChSt*`^&u|?#+`KKmN$h{vcs74CIlMHdh7&@aa$f+Ls_^Oqj z4B`^{k;yS^(h8$F0;9AUak}0oC*4ih@m-&SGYw5x3z z`HBHAj5Q(iEkwKdTRmEviH%X!HF}1$i&z7q^`n=Phk8jagJOHL^1J|Q=sJM$)v{e_ zEZLoXaVipfIU~Bh*#Hb2gy;{mar*b*Yw;rBc6TN&-waRJ)}HGvOA4oMBZ%t;Zy>f% z2wa$kzgGYWL!;4^^RvtPM)P9pPH%7&fG0w8A%ee5I76(4(H3-bWeVd)2SN~+W@-Vs z9S^-CCmWCum-`JK;jhHdD?=zOdNEODh@jT1HEMM4_dYaqYhO4+=BIpjQ^VK;q=?R% zFsL#~QmAjl7pTqiM2MWx>u%NIpzUW4;4`XE*9MOOS|-aTv0x+gM;TOnGir!?QZeg{ zq&LfT$MbjGhAZjNP8#de0_(;TS-Sy{;L)VtR5`2+)fMd4S=fFhqd-w?^i}NbvW~?d z(4Unih0+rd|1M3$%8{p;l!%rlXJ;!qSV_DCB~O{xhogM$h_l(hvH!hNBcq$d6E=1Q zt{9Ui{2ZC5%%yxjhIaOF$Ka{V66{`wgaE4r8{8YN=P45Q}M-Xd1czq@)%zMh_Qf7$#r&D8FBN2mw));@P%C2R8j_B>~KA0y#zni)qF!%o#ozw^cz zIA9kq!680Y++5ZNdbWFblp99H4VCqfLuo%G*uGG{c79Sy9rScAbWQ&68bq(5Bu}m! zPgpPK+8|=d=P$Q--l2uTS0|8BT53^k)KlVnaxjuAJ-nS7?J>;}N;RP!E|+cNk!!jG z$PI2^6KBP ztSifT5VG5RjS`P{Y9M5^kW651C*n@eSo7S8Fxy+)?#WrSqB@O`wOPFut@Ls!#-Y5~?Em)p89d|vv(|vYYo{Xi$)EzN%+rGmibJ97PuPW{lugW1G&OQ z{-(sE@#QwftNV_0-3AZ{r_UwPDFyQtcf!>cqovyaqMl-6t>uwfmG6u{z@p|a)*3O$ z421mqQ!1v}{j!Rl3i5ToZF11;xlr=W)6cyG#2F3)i9dMG?P3#isU&6JLZy-^MLT_R zJ2MyUL_3wfr}q{{iEOS$V`qw>>P5VB!;p~=|E_@lngaO#$9s;5PslDA6aat`=Krlu z`j2q1|INqwr@Yz8@xPHMQSuTth$={5)*s@T;46N?L?j(!{VdiK87QV0qM{bI0L*6j z^_ZNf$9=9O6OnPc@aj!Ui{hb9sG=8bqku$UU_{MHZ$52SZ<}eoXz_}cQ|!-NUH4fI zSKHrR?m)UoD)J`?Y_cxtM%zlsOsHeoEv}VZjLaUFQ@7;qQ}0j<>Rk`=p^%2w=`IuX zMr%=bi)&J9&meo*ZKUXBU64xH?RLs|OY)F_>l}c{>nYHuXQ~3j?kR=qirFPt>xiPM zUFHZBvrtZVne|D$LkFIE(NQFsAZfx-YCv8qb3po-qIhLhGEjvxRaMxa?)(-be>fU{ z(m47%;DJEn0W~Vdl2z0v(;ZDF(+90Te}VuqLlRb{qge*zk8)R#G0TDf&jR$id~-lA2iYRpSUqq9XLTAp(1iR$9%lv&Eg_mL0r zIO>>gw&HIxNfTrYq3SNBJ$nnK8tr6eQ<{mj@6w)K&;#k{Wzsm9iLG&Y(eT!FnT2{Q zqiW88AOaSBxSM}#xXQ_>9+7CBo>o*>pq$*90|sRHfuX%kIBKR;3qbWo6q;lvYoxqk zeW+q$`zZG7(O&l%5sFRLh)JBppr2%mmJn`Y4o3YUHNDkPus)Q?i$J+Cy9Hqoy2bib zw_Mi$6TwFv+_dtVXr{Fy^p_TZ1x_S+5)>@CpCwWcE&;8VcnJCeh5^v@0$)o?7x%LE z(s6-B#WT3KJ2te+)ByRtVPEwNDC|YtvS`y+_&xgah%?v0>O>#24TBHX2W->F z74b(GbS{{TJ<@M=FeifN(+qxx5NCt9x(?@tbO`p!Ua_};N@#d{Kz$c?DETabRn;{# zdabkb;7H=+ikw3m`5D$Fe>6hTmHExy%yMUXnS=0od@NCs>N!V3KQ<3EPGpxuXc<;1l{7@i_+1h+cdBa%%?WWv8)+lsBq+#Jyc;tK`h{{V#P?8z%Xfmfm! z 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 V@~jwGhz0*JfkIYI9!NKk{{vi2irWAH From a41bf5475da4d1ad5a38dace6f969b8affcf2a39 Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 6 Nov 2015 16:19:37 +0100 Subject: [PATCH 055/124] [^cdr] fix data race in DumbService.runWhenSmart --- .../intellij/openapi/project/DumbService.java | 4 +++- .../openapi/project/DumbServiceImpl.java | 18 +++++++++++------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/platform/core-api/src/com/intellij/openapi/project/DumbService.java b/platform/core-api/src/com/intellij/openapi/project/DumbService.java index 8062d86390b8..fcd2ec68fa29 100644 --- a/platform/core-api/src/com/intellij/openapi/project/DumbService.java +++ b/platform/core-api/src/com/intellij/openapi/project/DumbService.java @@ -64,7 +64,9 @@ public abstract class DumbService { } /** - * Executes the runnable immediately if not in dumb mode, or on AWT Event Dispatch thread when the dumb mode ends. + * Executes the runnable immediately if not in dumb mode, or on AWT Event Dispatch thread after the dumb mode ends. + * Note that it's not guaranteed that the dumb mode won't start again during this runnable execution, it should manage that situation explicitly + * (e.g. by starting a read action; it's still necessary to check isDumb inside the read action). * @param runnable runnable to run */ public abstract void runWhenSmart(@NotNull Runnable runnable); diff --git a/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java b/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java index 788864eaabb4..a1d1cc15b81e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/project/DumbServiceImpl.java @@ -151,14 +151,14 @@ public class DumbServiceImpl extends DumbService implements Disposable, Modifica @Override public void runWhenSmart(@NotNull Runnable runnable) { - if (!isDumb()) { - runnable.run(); - } - else { - synchronized (myRunWhenSmartQueue) { + synchronized (myRunWhenSmartQueue) { + if (isDumb()) { myRunWhenSmartQueue.addLast(runnable); + return; } } + + runnable.run(); } private void scheduleCacheUpdate(@NotNull final DumbModeTask task, boolean forceDumbMode) { @@ -220,7 +220,9 @@ public class DumbServiceImpl extends DumbService implements Disposable, Modifica application.runWriteAction(new Runnable() { @Override public void run() { - myDumb = true; + synchronized (myRunWhenSmartQueue) { + myDumb = true; + } myDumbStart = trace; myModificationCount++; try { @@ -286,7 +288,9 @@ public class DumbServiceImpl extends DumbService implements Disposable, Modifica } private void updateFinished(boolean modal) { - myDumb = false; + synchronized (myRunWhenSmartQueue) { + myDumb = false; + } myDumbStart = null; myModificationCount++; if (myProject.isDisposed()) return; From cbbe838d324cb48d8aa018a10954d78a4ca40dda Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 6 Nov 2015 16:22:15 +0100 Subject: [PATCH 056/124] add 'appendable' to dictionary --- spellchecker/src/com/intellij/spellchecker/english.dic | 1 + 1 file changed, 1 insertion(+) diff --git a/spellchecker/src/com/intellij/spellchecker/english.dic b/spellchecker/src/com/intellij/spellchecker/english.dic index 914f996cb13b..424511cd9f28 100644 --- a/spellchecker/src/com/intellij/spellchecker/english.dic +++ b/spellchecker/src/com/intellij/spellchecker/english.dic @@ -35234,6 +35234,7 @@ appellation's appellations append appendage +appendable appendage's appendages appendectomies From 2b9e895827478521a427cb812a1069fba473ac85 Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 6 Nov 2015 16:46:16 +0100 Subject: [PATCH 057/124] IDEA-147534 Inspection "@NotNull/@Nullable problems" - "Require @NotNull fileds to be initialized explicitly", does not trigger when using @NonnullByDefault --- .../nullable/NullableStuffInspectionBase.java | 27 +++++++++---------- .../NotNullByDefaultFieldNotInitialized.java | 15 +++++++++++ .../NullableStuffInspectionTest.java | 5 ++++ 3 files changed, 32 insertions(+), 15 deletions(-) create mode 100644 java/java-tests/testData/inspection/nullableProblems/NotNullByDefaultFieldNotInitialized.java diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspectionBase.java b/java/java-analysis-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspectionBase.java index db8e62a1ea52..897eed80e468 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspectionBase.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspectionBase.java @@ -105,12 +105,12 @@ public class NullableStuffInspectionBase extends BaseJavaBatchLocalInspectionToo checkAccessors(field, annotated, project, manager, anno, annoToRemove, holder); - if (REQUIRE_NOTNULL_FIELDS_INITIALIZED) { - checkNotNullFieldsInitialized(field, annotated, manager, holder); - } - checkConstructorParameters(field, annotated, manager, anno, annoToRemove, holder); } + + if (REQUIRE_NOTNULL_FIELDS_INITIALIZED && !annotated.isDeclaredNullable) { + checkNotNullFieldsInitialized(field, manager, holder); + } } @Override @@ -259,17 +259,14 @@ public class NullableStuffInspectionBase extends BaseJavaBatchLocalInspectionToo LOG.assertTrue(parameter.isPhysical(), setter.getText()); } - private static void checkNotNullFieldsInitialized(PsiField field, - Annotated annotated, - NullableNotNullManager manager, @NotNull ProblemsHolder holder) { - if (annotated.isDeclaredNotNull && !HighlightControlFlowUtil.isFieldInitializedAfterObjectConstruction(field)) { - final PsiAnnotation annotation = AnnotationUtil.findAnnotation(field, manager.getNotNulls()); - if (annotation != null) { - holder.registerProblem(annotation.isPhysical() ? annotation : field.getNameIdentifier(), - "Not-null fields must be initialized", - ProblemHighlightType.GENERIC_ERROR_OR_WARNING); - } - } + private static void checkNotNullFieldsInitialized(PsiField field, NullableNotNullManager manager, @NotNull ProblemsHolder holder) { + PsiAnnotation annotation = manager.getNotNullAnnotation(field, false); + if (annotation == null || HighlightControlFlowUtil.isFieldInitializedAfterObjectConstruction(field)) return; + + boolean byDefault = manager.isContainerAnnotation(annotation); + PsiJavaCodeReferenceElement name = annotation.getNameReferenceElement(); + holder.registerProblem(annotation.isPhysical() && !byDefault ? annotation : field.getNameIdentifier(), + (byDefault && name != null ? "@" + name.getReferenceName() : "Not-null") + " fields must be initialized"); } private void checkConstructorParameters(PsiField field, diff --git a/java/java-tests/testData/inspection/nullableProblems/NotNullByDefaultFieldNotInitialized.java b/java/java-tests/testData/inspection/nullableProblems/NotNullByDefaultFieldNotInitialized.java new file mode 100644 index 000000000000..07427362783f --- /dev/null +++ b/java/java-tests/testData/inspection/nullableProblems/NotNullByDefaultFieldNotInitialized.java @@ -0,0 +1,15 @@ +import javax.annotation.*; + +@NonnullByDefault +class Test { + Object member; + + private void accessMember() { + member = new Object(); + } +} + + +@Nonnull +@javax.annotation.meta.TypeQualifierDefault(java.lang.annotation.ElementType.FIELD) +@interface NonnullByDefault {} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/NullableStuffInspectionTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/NullableStuffInspectionTest.java index e0c38a3913f4..4a27815e27d2 100644 --- a/java/java-tests/testSrc/com/intellij/codeInspection/NullableStuffInspectionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInspection/NullableStuffInspectionTest.java @@ -59,6 +59,11 @@ public class NullableStuffInspectionTest extends LightCodeInsightFixtureTestCase doTest(); } + public void testNotNullByDefaultFieldNotInitialized() { + DataFlowInspectionTest.addJavaxNullabilityAnnotations(myFixture); + doTest(); + } + public void testNotNullAnnotationChecksInChildClassMethods() { doTest(); } public void testGetterSetterProblems() throws Exception{ doTest(); } From 26c978ef37a69875b5082cc72af654809e73dc28 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Fri, 6 Nov 2015 18:57:56 +0300 Subject: [PATCH 058/124] use LanguageUtil --- .../engine/evaluation/TextWithImportsImpl.java | 6 +++--- .../handlers/XDebuggerEvaluateActionHandler.java | 6 +++--- .../xdebugger/impl/ui/XDebuggerEditorBase.java | 15 +++------------ 3 files changed, 9 insertions(+), 18 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/TextWithImportsImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/TextWithImportsImpl.java index a73169ac02ea..cf0786258b34 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/TextWithImportsImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/TextWithImportsImpl.java @@ -16,6 +16,7 @@ package com.intellij.debugger.engine.evaluation; import com.intellij.debugger.ui.DebuggerEditorImpl; +import com.intellij.lang.LanguageUtil; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.fileTypes.FileTypeManager; import com.intellij.openapi.fileTypes.StdFileTypes; @@ -26,7 +27,6 @@ import com.intellij.psi.*; import com.intellij.xdebugger.XExpression; import com.intellij.xdebugger.evaluation.EvaluationMode; import com.intellij.xdebugger.impl.breakpoints.XExpressionImpl; -import com.intellij.xdebugger.impl.ui.XDebuggerEditorBase; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -136,7 +136,7 @@ public final class TextWithImportsImpl implements TextWithImports{ public static XExpression toXExpression(@Nullable TextWithImports text) { if (text != null && !text.getText().isEmpty()) { return new XExpressionImpl(text.getText(), - XDebuggerEditorBase.getFileTypeLanguage(text.getFileType()), + LanguageUtil.getFileTypeLanguage(text.getFileType()), StringUtil.nullize(text.getImports()), getMode(text.getKind())); } @@ -169,7 +169,7 @@ public final class TextWithImportsImpl implements TextWithImports{ return new TextWithImportsImpl(getKind(expression.getMode()), expression.getExpression(), StringUtil.notNullize(expression.getCustomInfo()), - expression.getLanguage() != null ? expression.getLanguage().getAssociatedFileType() : null); + LanguageUtil.getLanguageFileType(expression.getLanguage())); } } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/handlers/XDebuggerEvaluateActionHandler.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/handlers/XDebuggerEvaluateActionHandler.java index 9afff78ef6e5..65f0aeadde50 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/handlers/XDebuggerEvaluateActionHandler.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/handlers/XDebuggerEvaluateActionHandler.java @@ -16,6 +16,7 @@ package com.intellij.xdebugger.impl.actions.handlers; import com.intellij.lang.Language; +import com.intellij.lang.LanguageUtil; import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.editor.Document; @@ -36,7 +37,6 @@ import com.intellij.xdebugger.frame.XStackFrame; import com.intellij.xdebugger.frame.XValue; import com.intellij.xdebugger.impl.breakpoints.XExpressionImpl; import com.intellij.xdebugger.impl.evaluate.XDebuggerEvaluationDialog; -import com.intellij.xdebugger.impl.ui.XDebuggerEditorBase; import com.intellij.xdebugger.impl.ui.tree.actions.XDebuggerTreeActionBase; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -108,11 +108,11 @@ public class XDebuggerEvaluateActionHandler extends XDebuggerActionHandler { if (stackFrame != null) { XSourcePosition position = stackFrame.getSourcePosition(); if (position != null) { - language = XDebuggerEditorBase.getFileTypeLanguage(position.getFile().getFileType()); + language = LanguageUtil.getFileLanguage(position.getFile()); } } if (language == null && file != null) { - language = XDebuggerEditorBase.getFileTypeLanguage(file.getFileType()); + language = LanguageUtil.getFileTypeLanguage(file.getFileType()); } expression = new XExpressionImpl(expression.getExpression(), language, expression.getCustomInfo(), expression.getMode()); } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebuggerEditorBase.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebuggerEditorBase.java index 81ac51d23337..d9a4573d0ea4 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebuggerEditorBase.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebuggerEditorBase.java @@ -17,14 +17,13 @@ package com.intellij.xdebugger.impl.ui; import com.intellij.ide.DataManager; import com.intellij.lang.Language; +import com.intellij.lang.LanguageUtil; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.actionSystem.DefaultActionGroup; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.fileTypes.FileType; -import com.intellij.openapi.fileTypes.LanguageFileType; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.popup.JBPopupFactory; import com.intellij.openapi.ui.popup.ListPopup; @@ -156,10 +155,10 @@ public abstract class XDebuggerEditorBase { Language language = text.getLanguage(); if (language == null) { if (mySourcePosition != null) { - language = getFileTypeLanguage(mySourcePosition.getFile().getFileType()); + language = LanguageUtil.getFileLanguage(mySourcePosition.getFile()); } if (language == null) { - language = getFileTypeLanguage(getEditorsProvider().getFileType()); + language = LanguageUtil.getFileTypeLanguage(getEditorsProvider().getFileType()); } } text = new XExpressionImpl(text.getExpression(), language, text.getCustomInfo(), getMode()); @@ -182,14 +181,6 @@ public abstract class XDebuggerEditorBase { doSetText(text); } - @Nullable - public static Language getFileTypeLanguage(@Nullable FileType fileType) { - if (fileType instanceof LanguageFileType) { - return ((LanguageFileType)fileType).getLanguage(); - } - return null; - } - public abstract XExpression getExpression(); @Nullable From 0f12a3995f617a24607ed79f9825ee942421d9fb Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Fri, 6 Nov 2015 19:19:07 +0300 Subject: [PATCH 059/124] proper capitalization --- .../src/com/intellij/xdebugger/impl/ui/XDebuggerEditorBase.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebuggerEditorBase.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebuggerEditorBase.java index d9a4573d0ea4..a0900ffccb1f 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebuggerEditorBase.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebuggerEditorBase.java @@ -110,7 +110,7 @@ public abstract class XDebuggerEditorBase { } DataContext dataContext = DataManager.getInstance().getDataContext(getComponent()); - return JBPopupFactory.getInstance().createActionGroupPopup("Choose language", actions, dataContext, + return JBPopupFactory.getInstance().createActionGroupPopup("Choose Language", actions, dataContext, JBPopupFactory.ActionSelectionAid.SPEEDSEARCH, false); } From 563b8ab1b6329c77dda651d1f6c4fd0fea748cc8 Mon Sep 17 00:00:00 2001 From: Sergey Simonchik Date: Fri, 6 Nov 2015 19:40:49 +0300 Subject: [PATCH 060/124] vfs: support uri with custom protocol, like temp://, in VfsUtilCore#findRelativeFile(uri, null) --- .../com/intellij/openapi/vfs/VfsUtilCore.java | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/platform/core-api/src/com/intellij/openapi/vfs/VfsUtilCore.java b/platform/core-api/src/com/intellij/openapi/vfs/VfsUtilCore.java index 539a8da7341c..975495669f9a 100644 --- a/platform/core-api/src/com/intellij/openapi/vfs/VfsUtilCore.java +++ b/platform/core-api/src/com/intellij/openapi/vfs/VfsUtilCore.java @@ -584,11 +584,18 @@ public class VfsUtilCore { } if (file == null) { - if (base == null) return StandardFileSystems.local().findFileByPath(uri); - if (!base.isDirectory()) base = base.getParent(); - if (base == null) return StandardFileSystems.local().findFileByPath(uri); - file = VirtualFileManager.getInstance().findFileByUrl(base.getUrl() + "/" + uri); - if (file == null) return null; + if (base != null && !base.isDirectory()) { + base = base.getParent(); + } + if (base == null) { + file = StandardFileSystems.local().findFileByPath(uri); + if (file == null) { + file = VirtualFileManager.getInstance().findFileByUrl(uri); + } + } + else { + file = VirtualFileManager.getInstance().findFileByUrl(base.getUrl() + "/" + uri); + } } return file; From 7aa9dd9539911382744c7fc96435d0506e95f05e Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Fri, 6 Nov 2015 19:12:10 +0300 Subject: [PATCH 061/124] IDEA-146427 Do not create a Keymap copy if dialog is cancelled --- .../openapi/keymap/impl/ui/KeymapPanel.java | 36 +++++++++++++------ .../keymap/impl/ui/ShortcutDialog.java | 4 +++ 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapPanel.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapPanel.java index 3083d4f6508b..702ac30fb01d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapPanel.java +++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapPanel.java @@ -467,25 +467,25 @@ public class KeymapPanel extends JPanel implements SearchableConfigurable, Confi } private void addKeyboardShortcut(@NotNull String actionId, @Nullable Shortcut shortcut) { - Keymap keymap = createKeymapCopyIfNeeded(); - addKeyboardShortcut(actionId, shortcut, keymap, this, myQuickLists); + Keymap keymapSelected = myEditor.getModel().getSelected(); + addKeyboardShortcut(actionId, shortcut, keymapSelected, this, myQuickLists); repaintLists(); currentKeymapChanged(); } public static void addKeyboardShortcut(@NotNull String actionId, @Nullable Shortcut shortcut, - @NotNull Keymap keymap, + @NotNull Keymap keymapSelected, @NotNull Component parent, @NotNull QuickList[] quickLists) { KeyboardShortcutDialog dialog = new KeyboardShortcutDialog(parent); - KeyboardShortcut keyboardShortcut = dialog.showAndGet(shortcut, actionId, keymap, quickLists); + KeyboardShortcut keyboardShortcut = dialog.showAndGet(shortcut, actionId, keymapSelected, quickLists); if (keyboardShortcut == null) { return; } - Map> conflicts = keymap.getConflicts(actionId, keyboardShortcut); - if (!conflicts.isEmpty()) { + Keymap keymap = null; + if (dialog.hasConflicts()) { int result = Messages.showYesNoCancelDialog( parent, KeyMapBundle.message("conflict.shortcut.dialog.message"), @@ -496,6 +496,8 @@ public class KeymapPanel extends JPanel implements SearchableConfigurable, Confi Messages.getWarningIcon()); if (result == Messages.YES) { + keymap = createKeymapCopyIfNeededAndPossible(parent, keymapSelected); + Map> conflicts = keymap.getConflicts(actionId, keyboardShortcut); for (String id : conflicts.keySet()) { for (KeyboardShortcut s : conflicts.get(id)) { keymap.removeShortcut(id, s); @@ -508,6 +510,8 @@ public class KeymapPanel extends JPanel implements SearchableConfigurable, Confi } // if shortcut is already registered to this action, just select it in the list + + if (keymap == null) keymap = createKeymapCopyIfNeededAndPossible(parent, keymapSelected); Shortcut[] shortcuts = keymap.getShortcuts(actionId); for (Shortcut s : shortcuts) { if (s.equals(keyboardShortcut)) { @@ -527,16 +531,16 @@ public class KeymapPanel extends JPanel implements SearchableConfigurable, Confi return; } - Keymap keymap = createKeymapCopyIfNeeded(); + Keymap keymapSelected = myEditor.getModel().getSelected(); MouseShortcutDialog dialog = new MouseShortcutDialog(this, restrictions.allowMouseDoubleClick); - MouseShortcut mouseShortcut = dialog.showAndGet(shortcut, actionId, keymap, myQuickLists); + MouseShortcut mouseShortcut = dialog.showAndGet(shortcut, actionId, keymapSelected, myQuickLists); if (mouseShortcut == null) { return; } - String[] actionIds = keymap.getActionIds(mouseShortcut); - if (actionIds.length > 1 || (actionIds.length == 1 && !actionId.equals(actionIds[0]))) { + Keymap keymap = null; + if (dialog.hasConflicts()) { int result = Messages.showYesNoCancelDialog( this, KeyMapBundle.message("conflict.shortcut.dialog.message"), @@ -547,6 +551,8 @@ public class KeymapPanel extends JPanel implements SearchableConfigurable, Confi Messages.getWarningIcon()); if (result == Messages.YES) { + keymap = createKeymapCopyIfNeededAndPossible(this, keymapSelected); + String[] actionIds = keymap.getActionIds(mouseShortcut); for (String id : actionIds) { keymap.removeShortcut(id, mouseShortcut); } @@ -558,6 +564,7 @@ public class KeymapPanel extends JPanel implements SearchableConfigurable, Confi // if shortcut is already registered to this action, just select it in the list + if (keymap == null) keymap = createKeymapCopyIfNeededAndPossible(this, keymapSelected); Shortcut[] shortcuts = keymap.getShortcuts(actionId); for (Shortcut shortcut1 : shortcuts) { if (shortcut1.equals(mouseShortcut)) { @@ -578,6 +585,15 @@ public class KeymapPanel extends JPanel implements SearchableConfigurable, Confi myActionsTree.getComponent().repaint(); } + @NotNull + private static Keymap createKeymapCopyIfNeededAndPossible(Component parent, Keymap keymap) { + if (parent instanceof KeymapPanel) { + KeymapPanel panel = (KeymapPanel)parent; + keymap = panel.createKeymapCopyIfNeeded(); + } + return keymap; + } + @NotNull private Keymap createKeymapCopyIfNeeded() { Keymap keymap = myEditor.getModel().getSelected(); diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ShortcutDialog.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ShortcutDialog.java index c3ade8b94c5e..b0713fe96cfc 100644 --- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ShortcutDialog.java +++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ShortcutDialog.java @@ -74,6 +74,10 @@ abstract class ShortcutDialog extends DialogWrapper { return myGroup == null ? null : myGroup.getActionQualifiedPath(actionId); } + boolean hasConflicts() { + return myConflictsPanel.isVisible(); + } + abstract Collection getConflicts(T shortcut, String actionId, Keymap keymap); abstract T toShortcut(Object value); From b35bceb20451bc3ff6eb6b4d99cb87a7d7018e61 Mon Sep 17 00:00:00 2001 From: Sergey Malenkov Date: Fri, 6 Nov 2015 19:19:49 +0300 Subject: [PATCH 062/124] IDEA-146427 duplicated code --- .../openapi/keymap/impl/ui/KeymapPanel.java | 32 ++++++++----------- 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapPanel.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapPanel.java index 702ac30fb01d..113703b4c9cd 100644 --- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapPanel.java +++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapPanel.java @@ -468,6 +468,7 @@ public class KeymapPanel extends JPanel implements SearchableConfigurable, Confi private void addKeyboardShortcut(@NotNull String actionId, @Nullable Shortcut shortcut) { Keymap keymapSelected = myEditor.getModel().getSelected(); + assert keymapSelected != null; addKeyboardShortcut(actionId, shortcut, keymapSelected, this, myQuickLists); repaintLists(); currentKeymapChanged(); @@ -486,15 +487,7 @@ public class KeymapPanel extends JPanel implements SearchableConfigurable, Confi Keymap keymap = null; if (dialog.hasConflicts()) { - int result = Messages.showYesNoCancelDialog( - parent, - KeyMapBundle.message("conflict.shortcut.dialog.message"), - KeyMapBundle.message("conflict.shortcut.dialog.title"), - KeyMapBundle.message("conflict.shortcut.dialog.remove.button"), - KeyMapBundle.message("conflict.shortcut.dialog.leave.button"), - KeyMapBundle.message("conflict.shortcut.dialog.cancel.button"), - Messages.getWarningIcon()); - + int result = showConfirmationDialog(parent); if (result == Messages.YES) { keymap = createKeymapCopyIfNeededAndPossible(parent, keymapSelected); Map> conflicts = keymap.getConflicts(actionId, keyboardShortcut); @@ -541,15 +534,7 @@ public class KeymapPanel extends JPanel implements SearchableConfigurable, Confi Keymap keymap = null; if (dialog.hasConflicts()) { - int result = Messages.showYesNoCancelDialog( - this, - KeyMapBundle.message("conflict.shortcut.dialog.message"), - KeyMapBundle.message("conflict.shortcut.dialog.title"), - KeyMapBundle.message("conflict.shortcut.dialog.remove.button"), - KeyMapBundle.message("conflict.shortcut.dialog.leave.button"), - KeyMapBundle.message("conflict.shortcut.dialog.cancel.button"), - Messages.getWarningIcon()); - + int result = showConfirmationDialog(this); if (result == Messages.YES) { keymap = createKeymapCopyIfNeededAndPossible(this, keymapSelected); String[] actionIds = keymap.getActionIds(mouseShortcut); @@ -927,4 +912,15 @@ public class KeymapPanel extends JPanel implements SearchableConfigurable, Confi return group; } + + private static int showConfirmationDialog(Component parent) { + return Messages.showYesNoCancelDialog( + parent, + KeyMapBundle.message("conflict.shortcut.dialog.message"), + KeyMapBundle.message("conflict.shortcut.dialog.title"), + KeyMapBundle.message("conflict.shortcut.dialog.remove.button"), + KeyMapBundle.message("conflict.shortcut.dialog.leave.button"), + KeyMapBundle.message("conflict.shortcut.dialog.cancel.button"), + Messages.getWarningIcon()); + } } From 79a80b7ec9a37491aaf47d21d86166eb7b3425d5 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 6 Nov 2015 16:36:27 +0100 Subject: [PATCH 063/124] equality -> .equals cleanup --- .../ReplaceEqualityWithEqualsIntention.java | 40 +++++++------------ 1 file changed, 14 insertions(+), 26 deletions(-) diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/equality/ReplaceEqualityWithEqualsIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/equality/ReplaceEqualityWithEqualsIntention.java index d0f56b8cc305..cc4014728475 100644 --- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/equality/ReplaceEqualityWithEqualsIntention.java +++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/equality/ReplaceEqualityWithEqualsIntention.java @@ -15,7 +15,10 @@ */ package com.siyeh.ipp.equality; -import com.intellij.psi.*; +import com.intellij.psi.JavaTokenType; +import com.intellij.psi.PsiBinaryExpression; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiExpression; import com.intellij.psi.tree.IElementType; import com.siyeh.IntentionPowerPackBundle; import com.siyeh.ig.PsiReplacementUtil; @@ -44,46 +47,31 @@ public class ReplaceEqualityWithEqualsIntention extends MutablyNamedIntention { return new ObjectEqualityPredicate(); } - public void processIntention(PsiElement element) { + public void processIntention(@NotNull PsiElement element) { final PsiBinaryExpression exp = (PsiBinaryExpression)element; final PsiExpression lhs = exp.getLOperand(); final PsiExpression rhs = exp.getROperand(); if (rhs == null) { return; } - final PsiExpression strippedLhs = - ParenthesesUtils.stripParentheses(lhs); + final PsiExpression strippedLhs = ParenthesesUtils.stripParentheses(lhs); if (strippedLhs == null) { return; } - final PsiExpression strippedRhs = - ParenthesesUtils.stripParentheses(rhs); + final PsiExpression strippedRhs = ParenthesesUtils.stripParentheses(rhs); if (strippedRhs == null) { return; } - final IElementType tokenType = exp.getOperationTokenType(); + final String lhText = strippedLhs.getText(); + final String rhText = strippedRhs.getText(); + + final String prefix = exp.getOperationTokenType().equals(JavaTokenType.EQEQ) ? "" : "!"; @NonNls final String expString; - if (tokenType.equals(JavaTokenType.EQEQ)) { - if (ParenthesesUtils.getPrecedence(strippedLhs) > - ParenthesesUtils.METHOD_CALL_PRECEDENCE) { - expString = '(' + strippedLhs.getText() + ").equals(" + - strippedRhs.getText() + ')'; - } - else { - expString = strippedLhs.getText() + ".equals(" + - strippedRhs.getText() + ')'; - } + if (ParenthesesUtils.getPrecedence(strippedLhs) > ParenthesesUtils.METHOD_CALL_PRECEDENCE) { + expString = prefix + '(' + lhText + ").equals(" + rhText + ')'; } else { - if (ParenthesesUtils.getPrecedence(strippedLhs) > - ParenthesesUtils.METHOD_CALL_PRECEDENCE) { - expString = "!(" + strippedLhs.getText() + ").equals(" + - strippedRhs.getText() + ')'; - } - else { - expString = '!' + strippedLhs.getText() + ".equals(" + - strippedRhs.getText() + ')'; - } + expString = prefix + lhText + ".equals(" + rhText + ')'; } PsiReplacementUtil.replaceExpression(exp, expString); } From ed6044e6ff278719e730851286c5c6e695f93476 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 6 Nov 2015 17:36:36 +0100 Subject: [PATCH 064/124] primitive type comparison internal inspection --- plugins/devkit/resources/META-INF/plugin.xml | 4 + .../UsePrimitiveTypes.html | 5 + .../internal/UsePrimitiveTypesInspection.java | 131 ++++++++++++++++++ 3 files changed, 140 insertions(+) create mode 100644 plugins/devkit/resources/inspectionDescriptions/UsePrimitiveTypes.html create mode 100644 plugins/devkit/src/inspections/internal/UsePrimitiveTypesInspection.java diff --git a/plugins/devkit/resources/META-INF/plugin.xml b/plugins/devkit/resources/META-INF/plugin.xml index e1918e6fc5fa..1ee6118bbf06 100644 --- a/plugins/devkit/resources/META-INF/plugin.xml +++ b/plugins/devkit/resources/META-INF/plugin.xml @@ -133,6 +133,10 @@ groupKey="inspections.group.name" enabledByDefault="true" level="WARNING" implementationClass="org.jetbrains.idea.devkit.inspections.StatefulEpInspection"/> + diff --git a/plugins/devkit/resources/inspectionDescriptions/UsePrimitiveTypes.html b/plugins/devkit/resources/inspectionDescriptions/UsePrimitiveTypes.html new file mode 100644 index 000000000000..aadc3c90ab8c --- /dev/null +++ b/plugins/devkit/resources/inspectionDescriptions/UsePrimitiveTypes.html @@ -0,0 +1,5 @@ + + +Primitive types should be compared with .equals due to java 8 type annotations also applicable to primitive types + + \ No newline at end of file diff --git a/plugins/devkit/src/inspections/internal/UsePrimitiveTypesInspection.java b/plugins/devkit/src/inspections/internal/UsePrimitiveTypesInspection.java new file mode 100644 index 000000000000..46a8e5c928ba --- /dev/null +++ b/plugins/devkit/src/inspections/internal/UsePrimitiveTypesInspection.java @@ -0,0 +1,131 @@ +/* + * 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.idea.devkit.inspections.internal; + +import com.intellij.codeInspection.LocalQuickFix; +import com.intellij.codeInspection.ProblemDescriptor; +import com.intellij.codeInspection.ProblemsHolder; +import com.intellij.openapi.project.Project; +import com.intellij.psi.*; +import com.intellij.psi.tree.IElementType; +import com.intellij.psi.util.PsiUtil; +import com.siyeh.IntentionPowerPackBundle; +import com.siyeh.ig.PsiReplacementUtil; +import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; + +public class UsePrimitiveTypesInspection extends InternalInspection { + @Override + public PsiElementVisitor buildInternalVisitor(@NotNull final ProblemsHolder holder, final boolean isOnTheFly) { + return new JavaElementVisitor() { + @Override + public void visitBinaryExpression(PsiBinaryExpression expression) { + super.visitBinaryExpression(expression); + final IElementType tokenType = expression.getOperationTokenType(); + if (tokenType.equals(JavaTokenType.EQEQ) || tokenType.equals(JavaTokenType.NE)) { + final PsiExpression lOperand = expression.getLOperand(); + final PsiExpression rOperand = expression.getROperand(); + if (rOperand != null && (isPrimitiveTypeRef(lOperand) || isPrimitiveTypeRef(rOperand))) { + final String name; + if (JavaTokenType.NE.equals(tokenType)) { + name = IntentionPowerPackBundle.message("replace.equality.with.not.equals.intention.name"); + } + else { + name = IntentionPowerPackBundle.message("replace.equality.with.equals.intention.name"); + } + holder.registerProblem(expression.getOperationSign(), + "Primitive types should be compared with .equals", + new ReplaceEqualityWithEqualsFix(name)); + } + } + } + }; + } + + private static boolean isPrimitiveTypeRef(PsiExpression expression) { + if (expression instanceof PsiReferenceExpression) { + final PsiElement target = ((PsiReferenceExpression)expression).resolve(); + if (target instanceof PsiField) { + final PsiClass containingClass = ((PsiField)target).getContainingClass(); + return containingClass != null && + PsiType.class.getName().equals(containingClass.getQualifiedName()) && + !"NULL".equals(((PsiField)target).getName()); + } + } + return false; + } + + private static class ReplaceEqualityWithEqualsFix implements LocalQuickFix { + private final String myName; + + public ReplaceEqualityWithEqualsFix(String name) { + myName = name; + } + + @Nls + @NotNull + @Override + public String getName() { + return myName; + } + + @Nls + @NotNull + @Override + public String getFamilyName() { + return "Replace equality with .equals"; + } + + @Override + public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { + final PsiElement psiElement = descriptor.getPsiElement(); + if (psiElement instanceof PsiJavaToken) { + + final IElementType tokenType = ((PsiJavaToken)psiElement).getTokenType(); + final String prefix; + if (tokenType.equals(JavaTokenType.EQEQ)) { + prefix = ""; + } + else if (tokenType.equals(JavaTokenType.NE)) { + prefix = "!"; + } + else { + return; + } + + final PsiElement parent = psiElement.getParent(); + if (parent instanceof PsiBinaryExpression) { + final PsiExpression rOperand = ((PsiBinaryExpression)parent).getROperand(); + final PsiExpression lOperand = ((PsiBinaryExpression)parent).getLOperand(); + if (rOperand != null) { + final boolean flip = isPrimitiveTypeRef(rOperand); + if (flip || isPrimitiveTypeRef(lOperand)) { + final String rText = PsiUtil.skipParenthesizedExprUp(rOperand).getText(); + final String lText = PsiUtil.skipParenthesizedExprUp(lOperand).getText(); + + final String lhText = flip ? rText : lText; + final String rhText = flip ? lText : rText; + + @NonNls final String expString = prefix + lhText + ".equals(" + rhText + ')'; + PsiReplacementUtil.replaceExpression((PsiBinaryExpression)parent, expString); + } + } + } + } + } + } +} From 911100e0b5cb2296bbb165ed326a47e6c8042921 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 6 Nov 2015 18:18:57 +0100 Subject: [PATCH 065/124] replace primitive == comparisons with .equals --- .../debugger/jdi/LocalVariablesUtil.java | 2 +- .../SimplifyBooleanExpressionFix.java | 4 ++-- .../dataFlow/ControlFlowAnalyzer.java | 2 +- .../dataFlow/DataFlowInspectionBase.java | 2 +- .../dataFlow/PurityInference.java | 2 +- .../dataFlow/StandardInstructionVisitor.java | 20 +++++++++---------- .../reference/RefJavaUtilImpl.java | 4 ++-- .../UncheckedWarningLocalInspectionBase.java | 4 +--- .../extractMethod/ParametersFolder.java | 2 +- .../FunctionalInterfaceSuggester.java | 2 +- .../JavaRegExpModifierProvider.java | 2 +- .../completion/JavaCompletionUtil.java | 2 +- .../completion/JavaKeywordCompletion.java | 2 +- .../JavaMemberNameCompletionContributor.java | 2 +- .../JavaMethodMergingContributor.java | 2 +- .../completion/SmartCastProvider.java | 2 +- ...eWithDefaultParamValueIntentionAction.java | 2 +- .../MissingReturnExpressionFixer.java | 6 +++--- .../generation/GenerateDelegateHandler.java | 2 +- .../generation/OverrideImplementUtil.java | 2 +- .../IntroduceVariableIntentionAction.java | 2 +- .../lang/java/JavaDocumentationProvider.java | 2 +- .../extractMethod/ExtractMethodProcessor.java | 8 ++++---- .../ExtractLightMethodObjectHandler.java | 2 +- .../InheritanceToDelegationProcessor.java | 2 +- .../inline/InlineMethodProcessor.java | 2 +- .../IntroduceVariableBase.java | 2 +- .../WrapReturnValueAction.java | 2 +- .../src/com/intellij/psi/LambdaUtil.java | 4 ++-- .../intellij/psi/PsiMethodReferenceUtil.java | 2 +- .../psi/util/PsiConcatenationUtil.java | 2 +- .../com/intellij/psi/util/PsiMethodUtil.java | 8 ++++---- .../daemon/lambda/InferredTypeTest.java | 2 +- .../ConvertFieldToThreadLocalIntention.java | 4 ++-- .../rules/AtomicConversionRule.java | 6 +++--- ...nMethodIsAlwaysInvertedInspectionBase.java | 2 +- ...leBigDecimalConstructorCallInspection.java | 2 +- .../siyeh/ig/psiutils/ParenthesesUtils.java | 4 ++-- ...ngBufferReplaceableByStringInspection.java | 2 +- ...lassIsPublicStaticVoidNoArgInspection.java | 2 +- ...SubstitutedExpressionEvaluationHelper.java | 2 +- .../src/dom/impl/ExtensionDomExtender.java | 2 +- .../DevKitImplicitUsageProvider.java | 2 +- .../groovy/annotator/GroovyAnnotator.java | 2 +- .../MissingReturnInspection.java | 4 ++-- .../type/GroovyTypeCheckVisitor.java | 3 +-- .../LiteralConstructorReference.java | 2 +- .../controlFlow/impl/ControlFlowBuilder.java | 4 ++-- .../impl/MaybeReturnInstruction.java | 2 +- .../groovy/lang/psi/impl/GrRangeType.java | 2 +- .../expressions/GrReferenceResolveRunner.java | 2 +- .../statements/expressions/TypesUtil.java | 2 +- .../typeEnhancers/GrBooleanTypeConverter.java | 2 +- .../psi/typeEnhancers/GrCharConverter.java | 8 ++++---- .../typeEnhancers/GrNullVoidConverter.java | 12 +++++------ .../lang/psi/util/GroovyPropertyUtils.java | 2 +- .../plugins/groovy/lang/psi/util/PsiUtil.java | 2 +- .../processors/AccessorResolverProcessor.java | 2 +- .../groovy/util/GroovyStdTypeCalculators.java | 2 +- ...onvertSimpleGetterToPropertyIntention.java | 2 +- .../GrIntroduceLocalVariableIntention.java | 2 +- .../CompleteReferenceExpression.java | 2 +- .../lang/completion/GroovyCompletionData.java | 2 +- .../lang/completion/GroovyCompletionUtil.java | 2 +- .../GroovyDocumentationProvider.java | 3 +-- .../GroovyOverrideImplementUtil.java | 2 +- .../convertToJava/ClassItemGeneratorImpl.java | 2 +- .../convertToJava/ClosureGenerator.java | 2 +- .../convertToJava/CodeBlockGenerator.java | 9 +++++---- .../convertToJava/ExpressionGenerator.java | 6 +++--- .../refactoring/extract/ExtractUtil.java | 4 ++-- .../method/GroovyExtractMethodDialog.java | 2 +- .../inline/GroovyMethodInliner.java | 4 ++-- .../introduce/GrIntroduceHandlerBase.java | 2 +- .../parameter/GrIntroduceParameterDialog.java | 2 +- ...troduceParameterMethodUsagesProcessor.java | 4 ++-- .../intellij/uiDesigner/wizard/Generator.java | 5 ++--- 77 files changed, 120 insertions(+), 126 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/jdi/LocalVariablesUtil.java b/java/debugger/impl/src/com/intellij/debugger/jdi/LocalVariablesUtil.java index 4dfb02456bbc..50a03a53fd3d 100644 --- a/java/debugger/impl/src/com/intellij/debugger/jdi/LocalVariablesUtil.java +++ b/java/debugger/impl/src/com/intellij/debugger/jdi/LocalVariablesUtil.java @@ -494,7 +494,7 @@ public class LocalVariablesUtil { } private static int getTypeSlotSize(PsiType varType) { - if (varType == PsiType.DOUBLE || varType == PsiType.LONG) { + if (PsiType.DOUBLE.equals(varType) || PsiType.LONG.equals(varType)) { return 2; } return 1; diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/SimplifyBooleanExpressionFix.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/SimplifyBooleanExpressionFix.java index 612c6c6a9837..dab31757f128 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/SimplifyBooleanExpressionFix.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/SimplifyBooleanExpressionFix.java @@ -109,7 +109,7 @@ public class SimplifyBooleanExpressionFix extends LocalQuickFixOnPsiElement { public static void simplifyIfStatement(final PsiExpression expression) throws IncorrectOperationException { PsiElement parent = expression.getParent(); if (!(parent instanceof PsiIfStatement) || ((PsiIfStatement)parent).getCondition() != expression) return; - if (!(expression instanceof PsiLiteralExpression) || expression.getType() != PsiType.BOOLEAN) return; + if (!(expression instanceof PsiLiteralExpression) || !PsiType.BOOLEAN.equals(expression.getType())) return; boolean condition = Boolean.parseBoolean(expression.getText()); PsiIfStatement ifStatement = (PsiIfStatement)parent; if (condition) { @@ -210,7 +210,7 @@ public class SimplifyBooleanExpressionFix extends LocalQuickFixOnPsiElement { } public static boolean canBeSimplified(@NotNull PsiExpression expression) { - if (!(expression instanceof PsiConditionalExpression) && expression.getType() != PsiType.BOOLEAN) return false; + if (!(expression instanceof PsiConditionalExpression) && !PsiType.BOOLEAN.equals(expression.getType())) return false; final ExpressionVisitor expressionVisitor = new ExpressionVisitor(expression.getManager(), false); final Ref canBeSimplified = new Ref(Boolean.FALSE); diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java index 209d0e91634c..6880a6645710 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java @@ -1218,7 +1218,7 @@ public class ControlFlowAnalyzer extends JavaElementVisitor { } private void generateBoxingUnboxingInstructionFor(@NotNull PsiExpression expression, PsiType expectedType) { - if (expectedType == PsiType.VOID) return; + if (PsiType.VOID.equals(expectedType)) return; PsiType exprType = expression.getType(); diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java index aecfbc1e3bca..15e6d6b2e4c0 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java @@ -572,7 +572,7 @@ public class DataFlowInspectionBase extends BaseJavaBatchLocalInspectionTool { PsiType returnType = method.getReturnType(); // no warnings in void lambdas, where the expression is not returned anyway - if (block instanceof PsiExpression && block.getParent() instanceof PsiLambdaExpression && returnType == PsiType.VOID) return; + if (block instanceof PsiExpression && block.getParent() instanceof PsiLambdaExpression && PsiType.VOID.equals(returnType)) return; // no warnings for Void methods, where only null can be possibly returned if (returnType == null || returnType.equalsToText(CommonClassNames.JAVA_LANG_VOID)) return; diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/PurityInference.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/PurityInference.java index c626a96f8222..38c921825469 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/PurityInference.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/PurityInference.java @@ -36,7 +36,7 @@ public class PurityInference { public static boolean inferPurity(@NotNull final PsiMethod method) { if (!InferenceFromSourceUtil.shouldInferFromSource(method) || - method.getReturnType() == PsiType.VOID || + PsiType.VOID.equals(method.getReturnType()) || method.getBody() == null || method.isConstructor() || PropertyUtil.isSimpleGetter(method)) { diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java index a7894bf8e020..ed52d2c5e78b 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java @@ -517,18 +517,16 @@ public class StandardInstructionVisitor extends InstructionVisitor { PsiType varType = var.getVariableType(); if (!(varType instanceof PsiPrimitiveType)) return null; - if (varType == PsiType.FLOAT || varType == PsiType.DOUBLE) return null; + if (PsiType.FLOAT.equals(varType) || PsiType.DOUBLE.equals(varType)) return null; - double minValue = varType == PsiType.BYTE ? Byte.MIN_VALUE : - varType == PsiType.SHORT ? Short.MIN_VALUE : - varType == PsiType.INT ? Integer.MIN_VALUE : - varType == PsiType.CHAR ? Character.MIN_VALUE : - Long.MIN_VALUE; - double maxValue = varType == PsiType.BYTE ? Byte.MAX_VALUE : - varType == PsiType.SHORT ? Short.MAX_VALUE : - varType == PsiType.INT ? Integer.MAX_VALUE : - varType == PsiType.CHAR ? Character.MAX_VALUE : - Long.MAX_VALUE; + double minValue = PsiType.BYTE.equals(varType) ? Byte.MIN_VALUE : PsiType.SHORT.equals(varType) + ? Short.MIN_VALUE : PsiType.INT.equals(varType) + ? Integer.MIN_VALUE : PsiType.CHAR.equals(varType) ? Character.MIN_VALUE : + Long.MIN_VALUE; + double maxValue = PsiType.BYTE.equals(varType) ? Byte.MAX_VALUE : PsiType.SHORT.equals(varType) + ? Short.MAX_VALUE : PsiType.INT.equals(varType) + ? Integer.MAX_VALUE : PsiType.CHAR.equals(varType) ? Character.MAX_VALUE : + Long.MAX_VALUE; return checkComparisonWithKnownRange(instruction, runner, memState, opSign, comparedWith, minValue, maxValue); } diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaUtilImpl.java b/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaUtilImpl.java index ba105015a0f7..3d78588936d4 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaUtilImpl.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaUtilImpl.java @@ -251,7 +251,7 @@ public class RefJavaUtilImpl extends RefJavaUtil{ if (refExpression instanceof PsiMethodReferenceExpression) { PsiType returnType = psiMethod.getReturnType(); - if (!psiMethod.isConstructor() && returnType != PsiType.VOID) { + if (!psiMethod.isConstructor() && !PsiType.VOID.equals(returnType)) { refMethod.setReturnValueUsed(true); addTypeReference(psiFrom, returnType, refFrom.getRefManager()); } @@ -263,7 +263,7 @@ public class RefJavaUtilImpl extends RefJavaUtil{ ); if (call != null) { PsiType returnType = psiMethod.getReturnType(); - if (!psiMethod.isConstructor() && returnType != PsiType.VOID) { + if (!psiMethod.isConstructor() && !PsiType.VOID.equals(returnType)) { if (!(call.getParent() instanceof PsiExpressionStatement)) { refMethod.setReturnValueUsed(true); } diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/uncheckedWarnings/UncheckedWarningLocalInspectionBase.java b/java/java-analysis-impl/src/com/intellij/codeInspection/uncheckedWarnings/UncheckedWarningLocalInspectionBase.java index efcb53682b63..71016e8d6795 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/uncheckedWarnings/UncheckedWarningLocalInspectionBase.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/uncheckedWarnings/UncheckedWarningLocalInspectionBase.java @@ -27,11 +27,9 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.util.Pass; import com.intellij.openapi.util.WriteExternalException; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.*; import com.intellij.psi.util.*; -import com.intellij.xml.util.XmlUtil; import org.intellij.lang.annotations.Pattern; import org.jdom.Element; import org.jetbrains.annotations.NonNls; @@ -407,7 +405,7 @@ public class UncheckedWarningLocalInspectionBase extends BaseJavaBatchLocalInspe if (psiElement instanceof PsiMethod) { final PsiMethod method = (PsiMethod)psiElement; final PsiType returnType = method.getReturnType(); - if (returnType != null && returnType != PsiType.VOID) { + if (returnType != null && !PsiType.VOID.equals(returnType)) { final PsiExpression returnValue = statement.getReturnValue(); if (returnValue != null) { final PsiType valueType = returnValue.getType(); diff --git a/java/java-analysis-impl/src/com/intellij/refactoring/extractMethod/ParametersFolder.java b/java/java-analysis-impl/src/com/intellij/refactoring/extractMethod/ParametersFolder.java index 29c0f5806a8c..50a5e91903d0 100644 --- a/java/java-analysis-impl/src/com/intellij/refactoring/extractMethod/ParametersFolder.java +++ b/java/java-analysis-impl/src/com/intellij/refactoring/extractMethod/ParametersFolder.java @@ -221,7 +221,7 @@ public class ParametersFolder { if (expression == null) break; final PsiType expressionType = ((PsiExpression)expression).getType(); - if (expressionType != null && expressionType != PsiType.VOID && !(expression.getParent() instanceof PsiExpressionStatement)) { + if (expressionType != null && !PsiType.VOID.equals(expressionType) && !(expression.getParent() instanceof PsiExpressionStatement)) { if (dependsOnLocals(expression, inputVariables)) { break; } diff --git a/java/java-impl/src/com/intellij/codeInsight/FunctionalInterfaceSuggester.java b/java/java-impl/src/com/intellij/codeInsight/FunctionalInterfaceSuggester.java index c9373869f9ea..edde071f1ef4 100644 --- a/java/java-impl/src/com/intellij/codeInsight/FunctionalInterfaceSuggester.java +++ b/java/java-impl/src/com/intellij/codeInsight/FunctionalInterfaceSuggester.java @@ -123,7 +123,7 @@ public class FunctionalInterfaceSuggester { return null; } - if (returnType == PsiType.VOID && interfaceMethodReturnType != PsiType.VOID) { + if (PsiType.VOID.equals(returnType) && !PsiType.VOID.equals(interfaceMethodReturnType)) { return null; } diff --git a/java/java-impl/src/com/intellij/codeInsight/JavaRegExpModifierProvider.java b/java/java-impl/src/com/intellij/codeInsight/JavaRegExpModifierProvider.java index 3c31a01506a0..261b1998fa78 100644 --- a/java/java-impl/src/com/intellij/codeInsight/JavaRegExpModifierProvider.java +++ b/java/java-impl/src/com/intellij/codeInsight/JavaRegExpModifierProvider.java @@ -30,7 +30,7 @@ public class JavaRegExpModifierProvider implements RegExpModifierProvider { @Override public int getFlags(PsiElement elementInHost, PsiFile regexp) { final PsiExpressionList list = PsiTreeUtil.getParentOfType(elementInHost, PsiExpressionList.class); - if (list != null && list.getExpressions().length == 2 && list.getExpressionTypes()[1] == PsiType.INT) { + if (list != null && list.getExpressions().length == 2 && PsiType.INT.equals(list.getExpressionTypes()[1])) { final Object result = JavaConstantExpressionEvaluator.computeConstantExpression(list.getExpressions()[1], false); if (result instanceof Integer) { //noinspection MagicConstant diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java index dc12d45ad3fe..44cfd529b335 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java @@ -757,7 +757,7 @@ public class JavaCompletionUtil { TailType toInsert = tailType; LookupItem lookupItem = item.as(LookupItem.CLASS_CONDITION_KEY); if (lookupItem == null || lookupItem.getAttribute(LookupItem.TAIL_TYPE_ATTR) != TailType.UNKNOWN) { - if (!hasTail && item.getObject() instanceof PsiMethod && ((PsiMethod)item.getObject()).getReturnType() == PsiType.VOID) { + if (!hasTail && item.getObject() instanceof PsiMethod && PsiType.VOID.equals(((PsiMethod)item.getObject()).getReturnType())) { PsiDocumentManager.getInstance(context.getProject()).commitAllDocuments(); if (psiElement().beforeLeaf(psiElement().withText(".")).accepts(context.getFile().findElementAt(context.getTailOffset() - 1))) { return false; diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaKeywordCompletion.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaKeywordCompletion.java index 969dfdbcd6b7..e9d17e28612e 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaKeywordCompletion.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaKeywordCompletion.java @@ -491,7 +491,7 @@ public class JavaKeywordCompletion { private static boolean mayExpectBoolean(CompletionParameters parameters) { for (ExpectedTypeInfo info : JavaSmartCompletionContributor.getExpectedTypes(parameters)) { PsiType type = info.getType(); - if (type instanceof PsiClassType || type == PsiType.BOOLEAN) return true; + if (type instanceof PsiClassType || PsiType.BOOLEAN.equals(type)) return true; } return false; } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaMemberNameCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaMemberNameCompletionContributor.java index 5908a230a32d..a763fb55b630 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaMemberNameCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaMemberNameCompletionContributor.java @@ -325,7 +325,7 @@ public class JavaMemberNameCompletionContributor extends CompletionContributor { } } - if (!hasStartMatches(matcher, result) && PsiType.VOID != varType && includeOverlapped) { + if (!hasStartMatches(matcher, result) && !PsiType.VOID.equals(varType) && includeOverlapped) { // use suggested names as suffixes final String requiredSuffix = codeStyleManager.getSuffixByVariableKind(varKind); final String prefix = matcher.getPrefix(); diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaMethodMergingContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaMethodMergingContributor.java index c9e8ae1f78db..98029f6bcd2a 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaMethodMergingContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaMethodMergingContributor.java @@ -81,7 +81,7 @@ public class JavaMethodMergingContributor extends CompletionContributor { private static int getPriority(LookupElement element) { PsiMethod method = assertNotNull(getItemMethod(element)); - return (method.getReturnType() == PsiType.VOID ? 0 : 1) + + return (PsiType.VOID.equals(method.getReturnType()) ? 0 : 1) + (method.getParameterList().getParametersCount() > 0 ? 2 : 0); } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/SmartCastProvider.java b/java/java-impl/src/com/intellij/codeInsight/completion/SmartCastProvider.java index 5ac5057d8113..31de612c9ad3 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/SmartCastProvider.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/SmartCastProvider.java @@ -74,7 +74,7 @@ class SmartCastProvider extends CompletionProvider { type = ((PsiWildcardType)type).getBound(); } - if (type == null || type == PsiType.VOID) { + if (type == null || PsiType.VOID.equals(type)) { continue; } diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DelegateWithDefaultParamValueIntentionAction.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DelegateWithDefaultParamValueIntentionAction.java index fdec4a6b1910..a4b4a0965b36 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DelegateWithDefaultParamValueIntentionAction.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DelegateWithDefaultParamValueIntentionAction.java @@ -145,7 +145,7 @@ public class DelegateWithDefaultParamValueIntentionAction extends PsiElementBase final String methodCall; if (method.getReturnType() == null) { methodCall = "this"; - } else if (method.getReturnType() != PsiType.VOID) { + } else if (!PsiType.VOID.equals(method.getReturnType())) { methodCall = "return " + method.getName(); } else { methodCall = method.getName(); diff --git a/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/MissingReturnExpressionFixer.java b/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/MissingReturnExpressionFixer.java index eb68dd4979f7..cf236a6e3503 100644 --- a/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/MissingReturnExpressionFixer.java +++ b/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/MissingReturnExpressionFixer.java @@ -55,7 +55,7 @@ public class MissingReturnExpressionFixer implements Fixer { PsiElement parent = PsiTreeUtil.getParentOfType(psiElement, PsiClassInitializer.class, PsiMethod.class); if (parent instanceof PsiMethod) { final PsiType returnType = ((PsiMethod)parent).getReturnType(); - if (returnType != null && returnType != PsiType.VOID) { + if (returnType != null && !PsiType.VOID.equals(returnType)) { final int startOffset = retStatement.getTextRange().getStartOffset(); if (returnValue != null) { editor.getDocument().insertString(startOffset + "return".length(), ";"); @@ -84,7 +84,7 @@ public class MissingReturnExpressionFixer implements Fixer { if (!(prev instanceof PsiJavaToken)) { int offset = returnStatement.getTextRange().getEndOffset(); final PsiMethod method = PsiTreeUtil.getParentOfType(returnStatement, PsiMethod.class, true, PsiLambdaExpression.class); - if (method != null && method.getReturnType() == PsiType.VOID) { + if (method != null && PsiType.VOID.equals(method.getReturnType())) { offset = returnStatement.getTextRange().getStartOffset() + "return".length(); } editor.getDocument().insertString(offset, ";"); @@ -101,7 +101,7 @@ public class MissingReturnExpressionFixer implements Fixer { editor.getDocument().insertString(offset, ";"); if (prevToken.getTokenType() == JavaTokenType.RETURN_KEYWORD) { final PsiMethod method = PsiTreeUtil.getParentOfType(returnStatement, PsiMethod.class); - if (method != null && method.getReturnType() != PsiType.VOID) { + if (method != null && !PsiType.VOID.equals(method.getReturnType())) { editor.getCaretModel().moveToOffset(offset); processor.setSkipEnter(true); } diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateDelegateHandler.java b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateDelegateHandler.java index 9ec8d1a32f84..ce293e217f74 100644 --- a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateDelegateHandler.java +++ b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateDelegateHandler.java @@ -115,7 +115,7 @@ public class GenerateDelegateHandler implements LanguageCodeInsightActionHandler PsiModifierList modifierList = null; - if (method.getReturnType() != PsiType.VOID) { + if (!PsiType.VOID.equals(method.getReturnType())) { call.append("return "); } diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/OverrideImplementUtil.java b/java/java-impl/src/com/intellij/codeInsight/generation/OverrideImplementUtil.java index 291003c3f460..7756b0725055 100644 --- a/java/java-impl/src/com/intellij/codeInsight/generation/OverrideImplementUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/generation/OverrideImplementUtil.java @@ -337,7 +337,7 @@ public class OverrideImplementUtil extends OverrideImplementExploreUtil { @NotNull public static String callSuper(PsiMethod superMethod, PsiMethod overriding) { @NonNls StringBuilder buffer = new StringBuilder(); - if (!superMethod.isConstructor() && superMethod.getReturnType() != PsiType.VOID) { + if (!superMethod.isConstructor() && !PsiType.VOID.equals(superMethod.getReturnType())) { buffer.append("return "); } buffer.append("super"); diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/IntroduceVariableIntentionAction.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/IntroduceVariableIntentionAction.java index 2324cb2b6838..e45643fa52fb 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/IntroduceVariableIntentionAction.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/IntroduceVariableIntentionAction.java @@ -54,7 +54,7 @@ public class IntroduceVariableIntentionAction extends BaseRefactoringIntentionAc final PsiExpression expression = statement.getExpression(); - return expression.getType() != PsiType.VOID && !(expression instanceof PsiAssignmentExpression); + return !PsiType.VOID.equals(expression.getType()) && !(expression instanceof PsiAssignmentExpression); } @Override diff --git a/java/java-impl/src/com/intellij/lang/java/JavaDocumentationProvider.java b/java/java-impl/src/com/intellij/lang/java/JavaDocumentationProvider.java index 9d526d3d1aa2..dbfba1464c4c 100644 --- a/java/java-impl/src/com/intellij/lang/java/JavaDocumentationProvider.java +++ b/java/java-impl/src/com/intellij/lang/java/JavaDocumentationProvider.java @@ -406,7 +406,7 @@ public class JavaDocumentationProvider extends DocumentationProviderEx implement if (typeParameterList != null) { createTypeParamsListComment(builder, project, commenter, typeParameterList); } - if (psiMethod.getReturnType() != null && psiMethod.getReturnType() != PsiType.VOID) { + if (psiMethod.getReturnType() != null && !PsiType.VOID.equals(psiMethod.getReturnType())) { builder.append(CodeDocumentationUtil.createDocCommentLine(RETURN_TAG, project, commenter)); builder.append(LINE_SEPARATOR); } diff --git a/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java b/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java index 23b0a7bfef69..570d4d57f563 100644 --- a/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java @@ -267,10 +267,10 @@ public class ExtractMethodProcessor implements MatchProvider { if (expressionType == null) { expressionType = PsiType.VOID; } - myHasExpressionOutput = expressionType != PsiType.VOID; + myHasExpressionOutput = !PsiType.VOID.equals(expressionType); final PsiType returnStatementType = getExpectedReturnType(); - myHasReturnStatementOutput = myHasReturnStatement && returnStatementType != null && returnStatementType != PsiType.VOID; + myHasReturnStatementOutput = myHasReturnStatement && returnStatementType != null && !PsiType.VOID.equals(returnStatementType); if (myGenerateConditionalExit && myOutputVariables.length == 1) { if (!(myOutputVariables[0].getType() instanceof PsiPrimitiveType)) { @@ -381,7 +381,7 @@ public class ExtractMethodProcessor implements MatchProvider { private boolean areAllExitPointsAreNotNull(PsiType returnStatementType) { if (insertNotNullCheckIfPossible() && myControlFlowWrapper.getOutputVariables(false).length == 0) { - boolean isNotNull = returnStatementType != null && returnStatementType != PsiType.VOID; + boolean isNotNull = returnStatementType != null && !PsiType.VOID.equals(returnStatementType); for (PsiStatement statement : myExitStatements) { if (statement instanceof PsiReturnStatement) { final PsiExpression returnValue = ((PsiReturnStatement)statement).getReturnValue(); @@ -432,7 +432,7 @@ public class ExtractMethodProcessor implements MatchProvider { return; } final PsiMethod method = (PsiMethod)myCodeFragmentMember; - if (!method.isConstructor() || myReturnType != PsiType.VOID) { + if (!method.isConstructor() || !PsiType.VOID.equals(myReturnType)) { return; } final PsiCodeBlock body = method.getBody(); diff --git a/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractLightMethodObjectHandler.java b/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractLightMethodObjectHandler.java index f7686c8ad021..18beeac7a658 100644 --- a/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractLightMethodObjectHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/extractMethodObject/ExtractLightMethodObjectHandler.java @@ -277,7 +277,7 @@ public class ExtractLightMethodObjectHandler { private static boolean isValidVariableType(PsiType type) { if (type instanceof PsiClassType || type instanceof PsiArrayType || - type instanceof PsiPrimitiveType && type != PsiType.VOID) { + type instanceof PsiPrimitiveType && !PsiType.VOID.equals(type)) { return true; } return false; diff --git a/java/java-impl/src/com/intellij/refactoring/inheritanceToDelegation/InheritanceToDelegationProcessor.java b/java/java-impl/src/com/intellij/refactoring/inheritanceToDelegation/InheritanceToDelegationProcessor.java index c3d9cffb8638..22c8fd78f9db 100644 --- a/java/java-impl/src/com/intellij/refactoring/inheritanceToDelegation/InheritanceToDelegationProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/inheritanceToDelegation/InheritanceToDelegationProcessor.java @@ -549,7 +549,7 @@ public class InheritanceToDelegationProcessor extends BaseRefactoringProcessor { @NonNls final StringBuffer buffer = new StringBuffer(); buffer.append("{\n"); - if (methodToAdd.getReturnType() != PsiType.VOID) { + if (!PsiType.VOID.equals(methodToAdd.getReturnType())) { buffer.append("return "); } diff --git a/java/java-impl/src/com/intellij/refactoring/inline/InlineMethodProcessor.java b/java/java-impl/src/com/intellij/refactoring/inline/InlineMethodProcessor.java index ba9a4918a330..b2c82e29a2bb 100644 --- a/java/java-impl/src/com/intellij/refactoring/inline/InlineMethodProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/inline/InlineMethodProcessor.java @@ -747,7 +747,7 @@ public class InlineMethodProcessor extends BaseRefactoringProcessor { PsiType returnType = callSubstitutor.substitute(myMethod.getReturnType()); String resultName = null; final int applicabilityLevel = PsiUtil.getApplicabilityLevel(myMethod, callSubstitutor, argumentList); - if (returnType != null && returnType != PsiType.VOID && tailCallType == InlineUtil.TailCallType.None) { + if (returnType != null && !PsiType.VOID.equals(returnType) && tailCallType == InlineUtil.TailCallType.None) { resultName = myJavaCodeStyle.propertyNameToVariableName("result", VariableKind.LOCAL_VARIABLE); resultName = myJavaCodeStyle.suggestUniqueVariableName(resultName, block.getFirstChild(), true); PsiDeclarationStatement declaration = myFactory.createVariableDeclarationStatement(resultName, returnType, null); diff --git a/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java b/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java index b46589f451d6..e401a679f87d 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java @@ -236,7 +236,7 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase { PsiExpression expression = PsiTreeUtil.getParentOfType(elementAtCaret, PsiExpression.class); while (expression != null) { if (!expressions.contains(expression) && !(expression instanceof PsiParenthesizedExpression) && !(expression instanceof PsiSuperExpression) && - (acceptVoid || expression.getType() != PsiType.VOID)) { + (acceptVoid || !PsiType.VOID.equals(expression.getType()))) { if (expression instanceof PsiMethodReferenceExpression) { expressions.add(expression); } diff --git a/java/java-impl/src/com/intellij/refactoring/wrapreturnvalue/WrapReturnValueAction.java b/java/java-impl/src/com/intellij/refactoring/wrapreturnvalue/WrapReturnValueAction.java index 026fa135fdb3..741bf6dd82aa 100644 --- a/java/java-impl/src/com/intellij/refactoring/wrapreturnvalue/WrapReturnValueAction.java +++ b/java/java-impl/src/com/intellij/refactoring/wrapreturnvalue/WrapReturnValueAction.java @@ -38,7 +38,7 @@ public class WrapReturnValueAction extends BaseRefactoringAction{ final PsiMethod psiMethod = PsiTreeUtil.getParentOfType(element, PsiMethod.class, false); if (psiMethod != null && !(psiMethod instanceof PsiCompiledElement)) { final PsiType returnType = psiMethod.getReturnType(); - return returnType != null && returnType != PsiType.VOID; + return returnType != null && !PsiType.VOID.equals(returnType); } return false; } diff --git a/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java b/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java index d27e56a370a2..c602395895c2 100644 --- a/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java @@ -132,7 +132,7 @@ public class LambdaUtil { public static boolean isLambdaFullyInferred(PsiLambdaExpression expression, PsiType functionalInterfaceType) { final boolean hasParams = expression.getParameterList().getParametersCount() > 0; - if (hasParams || getFunctionalInterfaceReturnType(functionalInterfaceType) != PsiType.VOID) { //todo check that void lambdas without params check + if (hasParams || !PsiType.VOID.equals(getFunctionalInterfaceReturnType(functionalInterfaceType))) { //todo check that void lambdas without params check return !dependsOnTypeParams(functionalInterfaceType, functionalInterfaceType, expression); } @@ -570,7 +570,7 @@ public class LambdaUtil { } public static String checkReturnTypeCompatible(PsiLambdaExpression lambdaExpression, PsiType functionalInterfaceReturnType) { - if (functionalInterfaceReturnType == PsiType.VOID) { + if (PsiType.VOID.equals(functionalInterfaceReturnType)) { final PsiElement body = lambdaExpression.getBody(); if (body instanceof PsiCodeBlock) { if (!getReturnExpressions(lambdaExpression).isEmpty()) return "Unexpected return value"; diff --git a/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceUtil.java b/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceUtil.java index 6736b8581a22..7b73a8839259 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceUtil.java @@ -321,7 +321,7 @@ public class PsiMethodReferenceUtil { returnType = ((PsiMethod)resolve).getReturnType(); } PsiType methodReturnType = subst.substitute(returnType); - if (interfaceReturnType != null && interfaceReturnType != PsiType.VOID) { + if (interfaceReturnType != null && !PsiType.VOID.equals(interfaceReturnType)) { if (methodReturnType == null) { methodReturnType = JavaPsiFacade.getElementFactory(expression.getProject()).createType(containingClass, subst); } diff --git a/java/java-psi-api/src/com/intellij/psi/util/PsiConcatenationUtil.java b/java/java-psi-api/src/com/intellij/psi/util/PsiConcatenationUtil.java index 70c97495995b..1704fea347fd 100644 --- a/java/java-psi-api/src/com/intellij/psi/util/PsiConcatenationUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/util/PsiConcatenationUtil.java @@ -66,7 +66,7 @@ public class PsiConcatenationUtil { addFormatParameter(subExpression, formatString, formatParameters, printfFormat); } if (stringStarted) { - if (optype != null && (optype.equalsToText(JAVA_LANG_STRING) || optype == PsiType.CHAR)) { + if (optype != null && (optype.equalsToText(JAVA_LANG_STRING) || PsiType.CHAR.equals(optype))) { buildFormatString(op, formatString, formatParameters, printfFormat); } else { diff --git a/java/java-psi-api/src/com/intellij/psi/util/PsiMethodUtil.java b/java/java-psi-api/src/com/intellij/psi/util/PsiMethodUtil.java index a92ed0542b2c..7a4d333b15f5 100644 --- a/java/java-psi-api/src/com/intellij/psi/util/PsiMethodUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/util/PsiMethodUtil.java @@ -15,10 +15,10 @@ */ package com.intellij.psi.util; -import com.intellij.openapi.util.Condition; -import com.intellij.openapi.extensions.Extensions; -import com.intellij.psi.*; import com.intellij.codeInsight.runner.JavaMainMethodProvider; +import com.intellij.openapi.extensions.Extensions; +import com.intellij.openapi.util.Condition; +import com.intellij.psi.*; import org.jetbrains.annotations.Nullable; /** @@ -59,7 +59,7 @@ public class PsiMethodUtil { public static boolean isMainMethod(final PsiMethod method) { if (method == null || method.getContainingClass() == null) return false; - if (PsiType.VOID != method.getReturnType()) return false; + if (!PsiType.VOID.equals(method.getReturnType())) return false; if (!method.hasModifierProperty(PsiModifier.STATIC)) return false; if (!method.hasModifierProperty(PsiModifier.PUBLIC)) return false; final PsiParameter[] parameters = method.getParameterList().getParameters(); diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/InferredTypeTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/InferredTypeTest.java index b6a1729c4845..a377fe016026 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/InferredTypeTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/InferredTypeTest.java @@ -80,7 +80,7 @@ public class InferredTypeTest extends LightCodeInsightFixtureTestCase { final PsiJavaFile file = (PsiJavaFile)myFixture.addFileToProject("R.java", "public interface R {@D void run();}"); final PsiClass psiClass = file.getClasses()[0]; final PsiMethod method = psiClass.getMethods()[0]; - assertFalse(PsiType.VOID == method.getReturnType()); + assertFalse(PsiType.VOID.equals(method.getReturnType())); myFixture.configureByText("a.java", "class A {{R r = () -> {};}} "); myFixture.checkHighlighting(false, false, false); } diff --git a/java/typeMigration/src/com/intellij/refactoring/typeMigration/intentions/ConvertFieldToThreadLocalIntention.java b/java/typeMigration/src/com/intellij/refactoring/typeMigration/intentions/ConvertFieldToThreadLocalIntention.java index a0ca95579138..05c4afc2548f 100644 --- a/java/typeMigration/src/com/intellij/refactoring/typeMigration/intentions/ConvertFieldToThreadLocalIntention.java +++ b/java/typeMigration/src/com/intellij/refactoring/typeMigration/intentions/ConvertFieldToThreadLocalIntention.java @@ -61,7 +61,7 @@ public class ConvertFieldToThreadLocalIntention extends PsiElementBaseIntentionA if (psiField.getTypeElement() == null) return false; final PsiType fieldType = psiField.getType(); final PsiClass fieldTypeClass = PsiUtil.resolveClassInType(fieldType); - if (fieldType instanceof PsiPrimitiveType && fieldType != PsiType.VOID || fieldType instanceof PsiArrayType) return true; + if (fieldType instanceof PsiPrimitiveType && !PsiType.VOID.equals(fieldType) || fieldType instanceof PsiArrayType) return true; return fieldTypeClass != null && !Comparing.strEqual(fieldTypeClass.getQualifiedName(), ThreadLocal.class.getName()) && AllowedApiFilterExtension.isClassAllowed(ThreadLocal.class.getName(), element); } @@ -121,7 +121,7 @@ public class ConvertFieldToThreadLocalIntention extends PsiElementBaseIntentionA if (initializer == null) { final PsiType type = psiField.getType(); String initializerText = null; - if (type == PsiType.BOOLEAN) { + if (PsiType.BOOLEAN.equals(type)) { initializerText = "false"; } else if (type instanceof PsiPrimitiveType) { diff --git a/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/AtomicConversionRule.java b/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/AtomicConversionRule.java index a4ec46e44838..a6275b650266 100644 --- a/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/AtomicConversionRule.java +++ b/java/typeMigration/src/com/intellij/refactoring/typeMigration/rules/AtomicConversionRule.java @@ -39,19 +39,19 @@ public class AtomicConversionRule extends TypeConversionRule { } private static boolean isAtomicTypeMigration(PsiType from, PsiClassType to, PsiExpression context) { - if (from == PsiType.INT && to.getCanonicalText().equals(AtomicInteger.class.getName())) { + if (PsiType.INT.equals(from) && to.getCanonicalText().equals(AtomicInteger.class.getName())) { return true; } if (from.equals(PsiType.INT.createArrayType()) && to.getCanonicalText().equals(AtomicIntegerArray.class.getName())) { return true; } - if (from == PsiType.LONG && to.getCanonicalText().equals(AtomicLong.class.getName())) { + if (PsiType.LONG.equals(from) && to.getCanonicalText().equals(AtomicLong.class.getName())) { return true; } if (from.equals(PsiType.LONG.createArrayType()) && to.getCanonicalText().equals(AtomicLongArray.class.getName())) { return true; } - if (from == PsiType.BOOLEAN && to.getCanonicalText().equals(AtomicBoolean.class.getName())) { + if (PsiType.BOOLEAN.equals(from) && to.getCanonicalText().equals(AtomicBoolean.class.getName())) { return true; } final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(to); diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/intellij/codeInspection/booleanIsAlwaysInverted/BooleanMethodIsAlwaysInvertedInspectionBase.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/intellij/codeInspection/booleanIsAlwaysInverted/BooleanMethodIsAlwaysInvertedInspectionBase.java index ab9056eb86bb..7000ea80c1f4 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/intellij/codeInspection/booleanIsAlwaysInverted/BooleanMethodIsAlwaysInvertedInspectionBase.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/intellij/codeInspection/booleanIsAlwaysInverted/BooleanMethodIsAlwaysInvertedInspectionBase.java @@ -193,7 +193,7 @@ class BooleanMethodIsAlwaysInvertedInspectionBase extends GlobalJavaBatchInspect if (refElement instanceof RefMethod) { final PsiElement element = refElement.getElement(); if (!(element instanceof PsiMethod)) return; - if (((PsiMethod)element).getReturnType() != PsiType.BOOLEAN) return; + if (!PsiType.BOOLEAN.equals(((PsiMethod)element).getReturnType())) return; refElement.putUserData(ALWAYS_INVERTED, Boolean.TRUE); //initial mark boolean methods } } diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/UnpredictableBigDecimalConstructorCallInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/UnpredictableBigDecimalConstructorCallInspection.java index 144c50672847..60c761b1e01e 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/UnpredictableBigDecimalConstructorCallInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/UnpredictableBigDecimalConstructorCallInspection.java @@ -160,7 +160,7 @@ public class UnpredictableBigDecimalConstructorCallInspection final PsiParameter[] parameters = parameterList.getParameters(); final PsiParameter firstParameter = parameters[0]; final PsiType type = firstParameter.getType(); - if (type != PsiType.DOUBLE) { + if (!PsiType.DOUBLE.equals(type)) { return; } final PsiExpressionList argumentList = expression.getArgumentList(); diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ParenthesesUtils.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ParenthesesUtils.java index 357ff9b26fb5..d4be1fb565ff 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ParenthesesUtils.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ParenthesesUtils.java @@ -137,9 +137,9 @@ public class ParenthesesUtils { return false; } if (JavaTokenType.PLUS == tokenType || JavaTokenType.ASTERISK == tokenType) { - return primitiveType != PsiType.FLOAT && primitiveType != PsiType.DOUBLE; + return !PsiType.FLOAT.equals(primitiveType) && !PsiType.DOUBLE.equals(primitiveType); } else if (JavaTokenType.EQEQ == tokenType || JavaTokenType.NE == tokenType) { - return primitiveType == PsiType.BOOLEAN; + return PsiType.BOOLEAN.equals(primitiveType); } else if (JavaTokenType.AND == tokenType || JavaTokenType.OR == tokenType || JavaTokenType.XOR == tokenType) { return true; } else if (JavaTokenType.OROR == tokenType || JavaTokenType.ANDAND == tokenType) { diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/StringBufferReplaceableByStringInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/StringBufferReplaceableByStringInspection.java index 589d8d8b50d1..fed240173dda 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/StringBufferReplaceableByStringInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/StringBufferReplaceableByStringInspection.java @@ -445,7 +445,7 @@ public class StringBufferReplaceableByStringInspection extends BaseInspection { final PsiExpression[] arguments = argumentList.getExpressions(); if (arguments.length == 3) { return arguments[0].getType() instanceof PsiArrayType && - arguments[1].getType() == PsiType.INT && arguments[2].getType() == PsiType.INT; + PsiType.INT.equals(arguments[1].getType()) && PsiType.INT.equals(arguments[2].getType()); } return arguments.length == 1; } diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/junit/BeforeClassOrAfterClassIsPublicStaticVoidNoArgInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/junit/BeforeClassOrAfterClassIsPublicStaticVoidNoArgInspection.java index c51b0735d285..b160dea1970d 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/junit/BeforeClassOrAfterClassIsPublicStaticVoidNoArgInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/junit/BeforeClassOrAfterClassIsPublicStaticVoidNoArgInspection.java @@ -58,7 +58,7 @@ public class BeforeClassOrAfterClassIsPublicStaticVoidNoArgInspection modifierList.setModifierProperty(PsiModifier.STATIC, true); } - if (method.getReturnType() != PsiType.VOID) { + if (!PsiType.VOID.equals(method.getReturnType())) { ChangeSignatureProcessor csp = new ChangeSignatureProcessor(project, method, false, PsiModifier.PUBLIC, method.getName(), PsiType.VOID, new ParameterInfoImpl[0]); diff --git a/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/util/SubstitutedExpressionEvaluationHelper.java b/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/util/SubstitutedExpressionEvaluationHelper.java index 75c1ebc8a3c1..936efe6b485e 100644 --- a/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/util/SubstitutedExpressionEvaluationHelper.java +++ b/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/util/SubstitutedExpressionEvaluationHelper.java @@ -60,7 +60,7 @@ public class SubstitutedExpressionEvaluationHelper { final PsiMethodCallExpression c = (PsiMethodCallExpression)o; final PsiMethod m = (PsiMethod)c.getMethodExpression().resolve(); final PsiType returnType = m != null? m.getReturnType() : null; - if (returnType != null && returnType != PsiType.VOID) { + if (returnType != null && !PsiType.VOID.equals(returnType)) { // find substitution final Object substituted = calcSubstituted(m); if (substituted != null) return substituted; diff --git a/plugins/devkit/src/dom/impl/ExtensionDomExtender.java b/plugins/devkit/src/dom/impl/ExtensionDomExtender.java index 97546dd5e704..2315cb045499 100644 --- a/plugins/devkit/src/dom/impl/ExtensionDomExtender.java +++ b/plugins/devkit/src/dom/impl/ExtensionDomExtender.java @@ -158,7 +158,7 @@ public class ExtensionDomExtender extends DomExtender { Class clazz = String.class; if (withElement != null || isClassField(fieldName)) { clazz = PsiClass.class; - } else if (field.getType() == PsiType.BOOLEAN) { + } else if (PsiType.BOOLEAN.equals(field.getType())) { clazz = Boolean.class; } final DomExtension extension = diff --git a/plugins/devkit/src/inspections/DevKitImplicitUsageProvider.java b/plugins/devkit/src/inspections/DevKitImplicitUsageProvider.java index 7aeb7a047046..70d8cf939d18 100644 --- a/plugins/devkit/src/inspections/DevKitImplicitUsageProvider.java +++ b/plugins/devkit/src/inspections/DevKitImplicitUsageProvider.java @@ -102,7 +102,7 @@ public class DevKitImplicitUsageProvider implements ImplicitUsageProvider { private static boolean isDomElementVisitorMethod(PsiMethod method, PsiClass containingClass) { - if (method.getReturnType() != PsiType.VOID || + if (!PsiType.VOID.equals(method.getReturnType()) || !method.getName().startsWith("visit") || method.getParameterList().getParametersCount() != 1 || !InheritanceUtil.isInheritor(containingClass, "com.intellij.util.xml.DomElementVisitor")) { diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java index ff48a0fde0b8..88cedf1b1097 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java @@ -1067,7 +1067,7 @@ public class GroovyAnnotator extends GroovyElementVisitor { PsiMethod superMethod = superMethodSignature.getMethod(); PsiType declaredReturnType = superMethod.getReturnType(); PsiType superReturnType = superMethodSignature.getSubstitutor().substitute(declaredReturnType); - if (superReturnType == PsiType.VOID && method instanceof GrMethod && ((GrMethod)method).getReturnTypeElementGroovy() == null) return; + if (PsiType.VOID.equals(superReturnType) && method instanceof GrMethod && ((GrMethod)method).getReturnTypeElementGroovy() == null) return; if (superMethodSignature.isRaw()) superReturnType = TypeConversionUtil.erasure(declaredReturnType); if (returnType == null || superReturnType == null || method == superMethod) continue; PsiClass superClass = superMethod.getContainingClass(); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/noReturnMethod/MissingReturnInspection.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/noReturnMethod/MissingReturnInspection.java index 248074a55b95..7b1abd439e0d 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/noReturnMethod/MissingReturnInspection.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/noReturnMethod/MissingReturnInspection.java @@ -84,10 +84,10 @@ public class MissingReturnInspection extends GroovySuppressableInspectionTool { PsiClass resolved = ((PsiClassType)inferredReturnType).resolve(); if (resolved != null && !(resolved instanceof PsiTypeParameter)) return mustReturnValue; } - return inferredReturnType != null && inferredReturnType != PsiType.VOID ? shouldReturnValue : shouldNotReturnValue; + return inferredReturnType != null && !PsiType.VOID.equals(inferredReturnType) ? shouldReturnValue : shouldNotReturnValue; } else if (subject instanceof GrMethod) { - return ((GrMethod)subject).getReturnTypeElementGroovy() != null && ((GrMethod)subject).getReturnType() != PsiType.VOID + return ((GrMethod)subject).getReturnTypeElementGroovy() != null && !PsiType.VOID.equals(((GrMethod)subject).getReturnType()) ? mustReturnValue : shouldNotReturnValue; } diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/type/GroovyTypeCheckVisitor.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/type/GroovyTypeCheckVisitor.java index 782f10c65d49..da729abb2ac9 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/type/GroovyTypeCheckVisitor.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/type/GroovyTypeCheckVisitor.java @@ -22,7 +22,6 @@ import com.intellij.openapi.util.Condition; import com.intellij.psi.*; import com.intellij.psi.impl.PsiSubstitutorImpl; import com.intellij.psi.tree.IElementType; -import com.intellij.psi.util.TypeConversionUtil; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; @@ -696,7 +695,7 @@ public class GroovyTypeCheckVisitor extends BaseInspectionVisitor { @NotNull PsiElement elementToHighlight) { if (getTupleInitializer(expression) != null) return; final PsiType returnType = PsiImplUtil.inferReturnType(expression); - if (returnType == null || returnType == PsiType.VOID) return; + if (returnType == null || PsiType.VOID.equals(returnType)) return; processAssignment(returnType, expression, elementToHighlight, "cannot.return.type", context, ApplicableTo.RETURN_VALUE); } diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/findUsages/LiteralConstructorReference.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/findUsages/LiteralConstructorReference.java index 2d1810f5bfa2..e88b5e3fe191 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/findUsages/LiteralConstructorReference.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/findUsages/LiteralConstructorReference.java @@ -77,7 +77,7 @@ public class LiteralConstructorReference extends PsiReferenceBase.Poly myExitPoints = returnType != PsiType.VOID ? ControlFlowUtils.collectReturns(block) : Collections.emptySet(); + Collection myExitPoints = !PsiType.VOID.equals(returnType) ? ControlFlowUtils.collectReturns(block) : Collections.emptySet(); boolean shouldInsertReturnNull = !(returnType instanceof PsiPrimitiveType) && MissingReturnInspection.methodMissesSomeReturns(block, MissingReturnInspection.ReturnStatus.shouldNotReturnValue); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/CodeBlockGenerator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/CodeBlockGenerator.java index 70581983a0b2..d367f3db936a 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/CodeBlockGenerator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/CodeBlockGenerator.java @@ -101,7 +101,7 @@ public class CodeBlockGenerator extends Generator { boolean shouldInsertReturnNull; myExitPoints.clear(); PsiType returnType = context.typeProvider.getReturnType(method); - if (!method.isConstructor() && returnType != PsiType.VOID) { + if (!method.isConstructor() && !PsiType.VOID.equals(returnType)) { myExitPoints.addAll(ControlFlowUtils.collectReturns(block)); shouldInsertReturnNull = block != null && !(returnType instanceof PsiPrimitiveType) && @@ -338,7 +338,7 @@ public class CodeBlockGenerator extends Generator { private boolean isRealExpression(GrExpression expression) { final PsiType type = expression.getType(); - if (type == PsiType.VOID) return false; //statement + if (PsiType.VOID.equals(type)) return false; //statement if (type == PsiType.NULL) return !org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil.isVoidMethodCall(expression); @@ -351,7 +351,8 @@ public class CodeBlockGenerator extends Generator { builder.append("return "); final PsiType expectedReturnType = PsiImplUtil.inferReturnType(expression); - final PsiType nnReturnType = expectedReturnType == null || expectedReturnType == PsiType.VOID ? TypesUtil.getJavaLangObject(expression) : expectedReturnType; + final PsiType nnReturnType = expectedReturnType == null || PsiType.VOID.equals(expectedReturnType) + ? TypesUtil.getJavaLangObject(expression) : expectedReturnType; GenerationUtil.wrapInCastIfNeeded(builder, nnReturnType, expression.getNominalType(), expression, context, new StatementWriter() { @Override public void writeStatement(StringBuilder builder, ExpressionContext context) { @@ -382,7 +383,7 @@ public class CodeBlockGenerator extends Generator { builder.append("if ("); if (condition != null) { final PsiType type = condition.getType(); - if (TypesUtil.unboxPrimitiveTypeWrapper(type) == PsiType.BOOLEAN) { + if (PsiType.BOOLEAN.equals(TypesUtil.unboxPrimitiveTypeWrapper(type))) { writeExpression(condition, builder, context); } else { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ExpressionGenerator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ExpressionGenerator.java index aceef3c34b84..5c2c3ba0c91a 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ExpressionGenerator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ExpressionGenerator.java @@ -374,7 +374,7 @@ public class ExpressionGenerator extends Generator { var = null; } final PsiType type = condition.getType(); - if (type == null || TypesUtil.unboxPrimitiveTypeWrapper(type) == PsiType.BOOLEAN) { + if (type == null || PsiType.BOOLEAN.equals(TypesUtil.unboxPrimitiveTypeWrapper(type))) { if (elvis) { builder.append(var); } @@ -721,7 +721,7 @@ public class ExpressionGenerator extends Generator { } private static boolean isBooleanType(PsiType type) { - return type == PsiType.BOOLEAN || type != null && type.equalsToText(CommonClassNames.JAVA_LANG_BOOLEAN); + return PsiType.BOOLEAN.equals(type) || type != null && type.equalsToText(CommonClassNames.JAVA_LANG_BOOLEAN); } private void writeSimpleBinaryExpression(PsiElement opToken, GrExpression left, GrExpression right) { @@ -901,7 +901,7 @@ public class ExpressionGenerator extends Generator { boolean isChar = false; for (TypeConstraint constraint : constraints) { - if (constraint instanceof SubtypeConstraint && TypesUtil.unboxPrimitiveTypeWrapper(constraint.getDefaultType()) == PsiType.CHAR) { + if (constraint instanceof SubtypeConstraint && PsiType.CHAR.equals(TypesUtil.unboxPrimitiveTypeWrapper(constraint.getDefaultType()))) { isChar = true; } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractUtil.java index e2ef05c0a2de..4c4515315eb8 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractUtil.java @@ -46,12 +46,12 @@ import org.jetbrains.plugins.groovy.lang.psi.api.util.GrStatementOwner; import org.jetbrains.plugins.groovy.lang.psi.api.util.GrVariableDeclarationOwner; import org.jetbrains.plugins.groovy.lang.psi.dataFlow.reachingDefs.VariableInfo; import org.jetbrains.plugins.groovy.lang.psi.impl.ApplicationStatementUtil; +import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyNamesUtil; import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; import org.jetbrains.plugins.groovy.lang.psi.util.GrStringUtil; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil; -import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyNamesUtil; import org.jetbrains.plugins.groovy.refactoring.extract.method.ExtractMethodInfoHelper; import org.jetbrains.plugins.groovy.refactoring.introduce.StringPartInfo; @@ -323,7 +323,7 @@ public class ExtractUtil { buffer.append(") { \n"); GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(helper.getProject()); - generateBody(helper, type == PsiType.VOID, buffer, helper.isForceReturn()); + generateBody(helper, PsiType.VOID.equals(type), buffer, helper.isForceReturn()); buffer.append("\n}"); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/GroovyExtractMethodDialog.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/GroovyExtractMethodDialog.java index da9869133eed..60a41dae6c1c 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/GroovyExtractMethodDialog.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/method/GroovyExtractMethodDialog.java @@ -144,7 +144,7 @@ public class GroovyExtractMethodDialog extends DialogWrapper { myNameLabel.setLabelFor(myNameField); final PsiType type = myHelper.getOutputType(); - if (type != PsiType.VOID) { + if (!PsiType.VOID.equals(type)) { myForceReturnCheckBox.setSelected(GroovyApplicationSettings.getInstance().FORCE_RETURN); } else { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/inline/GroovyMethodInliner.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/inline/GroovyMethodInliner.java index a38cf14cfe58..2d52b8e88e06 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/inline/GroovyMethodInliner.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/inline/GroovyMethodInliner.java @@ -257,7 +257,7 @@ public class GroovyMethodInliner implements InlineHandler.Inliner { } // Process method return statements - if (returnCount > 1 && PsiType.VOID != methodType && !isTailMethodCall) { + if (returnCount > 1 && !PsiType.VOID.equals(methodType) && !isTailMethodCall) { PsiType type = methodType != null && methodType.equalsToText(CommonClassNames.JAVA_LANG_OBJECT) ? null : methodType; GrVariableDeclaration resultDecl = factory.createVariableDeclaration(ArrayUtil.EMPTY_STRING_ARRAY, "", type, resultName); GrStatement statement = ((GrStatementOwner) owner).addStatementBefore(resultDecl, anchor); @@ -421,7 +421,7 @@ public class GroovyMethodInliner implements InlineHandler.Inliner { if (statements[0] instanceof GrExpression) return (GrExpression) statements[0]; if (statements[0] instanceof GrReturnStatement) { GrExpression value = ((GrReturnStatement) statements[0]).getReturnValue(); - if (value == null && PsiUtil.getSmartReturnType(method) != PsiType.VOID) { + if (value == null && !PsiType.VOID.equals(PsiUtil.getSmartReturnType(method))) { return GroovyPsiElementFactory.getInstance(method.getProject()).createExpressionFromText("null"); } return value; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java index bb1953bbca86..fd84b3c10ca9 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrIntroduceHandlerBase.java @@ -237,7 +237,7 @@ public abstract class GrIntroduceHandlerBase Date: Fri, 6 Nov 2015 19:27:03 +0100 Subject: [PATCH 066/124] Cleanup (warnings) --- .../util/src/com/intellij/util/io/SafeFileOutputStream.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/platform/util/src/com/intellij/util/io/SafeFileOutputStream.java b/platform/util/src/com/intellij/util/io/SafeFileOutputStream.java index 6596b54a0982..481022132e0f 100644 --- a/platform/util/src/com/intellij/util/io/SafeFileOutputStream.java +++ b/platform/util/src/com/intellij/util/io/SafeFileOutputStream.java @@ -45,11 +45,11 @@ public class SafeFileOutputStream extends OutputStream { myTargetFile = target; myPreserveAttributes = preserveAttributes; myBackupFile = new File(myTargetFile.getParentFile(), myTargetFile.getName() + EXTENSION_BAK); - //noinspection IOResourceOpenedButNotSafelyClosed myBackupStream = new FileOutputStream(myBackupFile); } @Override + @SuppressWarnings("Duplicates") public void write(byte[] b) throws IOException { try { myBackupStream.write(b); @@ -62,6 +62,7 @@ public class SafeFileOutputStream extends OutputStream { } @Override + @SuppressWarnings("Duplicates") public void write(int b) throws IOException { try { myBackupStream.write(b); @@ -74,6 +75,7 @@ public class SafeFileOutputStream extends OutputStream { } @Override + @SuppressWarnings("Duplicates") public void write(byte[] b, int off, int len) throws IOException { try { myBackupStream.write(b, off, len); @@ -137,4 +139,4 @@ public class SafeFileOutputStream extends OutputStream { throw new IOException(CommonBundle.message("safe.write.drop.temp", oldFile)); } } -} +} \ No newline at end of file From bab48d3c7da9a7ad81cfc934cadda15f1ead7669 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 6 Nov 2015 19:23:33 +0100 Subject: [PATCH 067/124] update testng dtd (IDEA-147573) --- .../resources/standardSchemas/testng-1.0.dtd | 49 +++++++++++++------ 1 file changed, 35 insertions(+), 14 deletions(-) diff --git a/plugins/testng/src/resources/standardSchemas/testng-1.0.dtd b/plugins/testng/src/resources/standardSchemas/testng-1.0.dtd index c1a478ab1c6f..8c7da51f678e 100644 --- a/plugins/testng/src/resources/standardSchemas/testng-1.0.dtd +++ b/plugins/testng/src/resources/standardSchemas/testng-1.0.dtd @@ -30,16 +30,19 @@ Cedric Beust & Alexandru Popescu - + + group-by-instances (true | false) "false" + preserve-order (true | false) "true" + allow-return-values (true | false) "false" + > @@ -75,7 +84,7 @@ Cedric Beust & Alexandru Popescu + > + preserve-order (true | false) "true" + group-by-instances (true | false) "false" + allow-return-values (true | false) "false" + > - + - + + + + + + - + @@ -180,7 +201,7 @@ Defines additional groups ("groups of groups") and also which groups to include name CDATA #REQUIRED > - + From 918e68fa709aef44379461f2f40e4d375dfefc81 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 6 Nov 2015 19:33:32 +0100 Subject: [PATCH 068/124] revert test data --- .../intellij/codeInsight/daemon/lambda/InferredTypeTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/InferredTypeTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/InferredTypeTest.java index a377fe016026..d17ee3c2731e 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/InferredTypeTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/InferredTypeTest.java @@ -80,7 +80,8 @@ public class InferredTypeTest extends LightCodeInsightFixtureTestCase { final PsiJavaFile file = (PsiJavaFile)myFixture.addFileToProject("R.java", "public interface R {@D void run();}"); final PsiClass psiClass = file.getClasses()[0]; final PsiMethod method = psiClass.getMethods()[0]; - assertFalse(PsiType.VOID.equals(method.getReturnType())); + //noinspection UsePrimitiveTypes + assertFalse(PsiType.VOID == method.getReturnType()); myFixture.configureByText("a.java", "class A {{R r = () -> {};}} "); myFixture.checkHighlighting(false, false, false); } From 6348011d80b8ec0737d5856b575c5b8afa53b173 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 6 Nov 2015 20:19:49 +0100 Subject: [PATCH 069/124] dependencies view: consistent icon for directories (IDEA-147531) --- .../packageDependencies/ui/DirectoryNode.java | 35 ++++++++++++------- .../psi/impl/file/DirectoryIconProvider.java | 22 ++++++------ 2 files changed, 34 insertions(+), 23 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/packageDependencies/ui/DirectoryNode.java b/platform/lang-impl/src/com/intellij/packageDependencies/ui/DirectoryNode.java index 0393cf8848bc..6168269d7d98 100644 --- a/platform/lang-impl/src/com/intellij/packageDependencies/ui/DirectoryNode.java +++ b/platform/lang-impl/src/com/intellij/packageDependencies/ui/DirectoryNode.java @@ -22,6 +22,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ProjectFileIndex; import com.intellij.openapi.roots.ProjectRootManager; import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.vfs.JarFileSystem; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; @@ -116,28 +117,35 @@ public class DirectoryNode extends PackageDependenciesNode { public void fillFiles(Set set, boolean recursively) { super.fillFiles(set, recursively); int count = getChildCount(); + Boolean isRoot = null; for (int i = 0; i < count; i++) { PackageDependenciesNode child = (PackageDependenciesNode)getChildAt(i); if (child instanceof FileNode || recursively) { child.fillFiles(set, true); } else if (child instanceof DirectoryNode) { - final VirtualFile directory = ((DirectoryNode)child).getDirectory(); - if (directory != null) { - final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(myProject).getFileIndex(); - final VirtualFile contentRoot = fileIndex.getContentRootForFile(directory); - final VirtualFile sourceRoot = fileIndex.getSourceRootForFile(directory); - if (directory.equals(contentRoot) || - contentRoot != null && contentRoot.equals(directory.getParent()) || - directory.equals(sourceRoot) || - sourceRoot != null && sourceRoot.equals(directory.getParent())) { - child.fillFiles(set, false); - } + if (isRoot == null) { + isRoot = isContentOrSourceRoot(); + } + if (isRoot) { + child.fillFiles(set, false); } } } } + public boolean isContentOrSourceRoot() { + if (myVDirectory != null) { + final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(myProject).getFileIndex(); + final VirtualFile contentRoot = fileIndex.getContentRootForFile(myVDirectory); + final VirtualFile sourceRoot = fileIndex.getSourceRootForFile(myVDirectory); + if (myVDirectory.equals(contentRoot) || myVDirectory.equals(sourceRoot)) { + return true; + } + } + return false; + } + public String toString() { if (myFQName != null) return myFQName; if (myCompactPackages && myCompactedDirNode != null) { @@ -217,8 +225,9 @@ public class DirectoryNode extends PackageDependenciesNode { @Override public Icon getIcon() { - if (myDirectory != null) { - return new DirectoryIconProvider().getIcon(myDirectory, 0); + if (myVDirectory != null) { + final VirtualFile jarRoot = JarFileSystem.getInstance().getRootByEntry(myVDirectory); + return myVDirectory.equals(jarRoot) ? PlatformIcons.JAR_ICON : DirectoryIconProvider.getDirectoryIcon(myVDirectory, myProject); } return PlatformIcons.PACKAGE_ICON; } diff --git a/platform/lang-impl/src/com/intellij/psi/impl/file/DirectoryIconProvider.java b/platform/lang-impl/src/com/intellij/psi/impl/file/DirectoryIconProvider.java index 03e0b4fa4c92..1fa0d02c3c5f 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/file/DirectoryIconProvider.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/file/DirectoryIconProvider.java @@ -43,20 +43,22 @@ public class DirectoryIconProvider extends IconProvider implements DumbAware { public Icon getIcon(@NotNull final PsiElement element, final int flags) { if (element instanceof PsiDirectory) { final PsiDirectory psiDirectory = (PsiDirectory)element; - final VirtualFile vFile = psiDirectory.getVirtualFile(); - Project project = psiDirectory.getProject(); - SourceFolder sourceFolder = ProjectRootsUtil.getModuleSourceRoot(vFile, project); - if (sourceFolder != null) { - return SourceRootPresentation.getSourceRootIcon(sourceFolder); - } - else { - Icon excludedIcon = getIconIfExcluded(project, vFile); - return excludedIcon != null ? excludedIcon : PlatformIcons.DIRECTORY_CLOSED_ICON; - } + return getDirectoryIcon(psiDirectory.getVirtualFile(), psiDirectory.getProject()); } return null; } + public static Icon getDirectoryIcon(VirtualFile vFile, Project project) { + SourceFolder sourceFolder = ProjectRootsUtil.getModuleSourceRoot(vFile, project); + if (sourceFolder != null) { + return SourceRootPresentation.getSourceRootIcon(sourceFolder); + } + else { + Icon excludedIcon = getIconIfExcluded(project, vFile); + return excludedIcon != null ? excludedIcon : PlatformIcons.DIRECTORY_CLOSED_ICON; + } + } + @Nullable public static Icon getIconIfExcluded(@NotNull Project project, @NotNull VirtualFile vFile) { if (!Registry.is("ide.hide.excluded.files")) { From 8405c1983286f6b7f4b72fb5b620a31071dc5e01 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 6 Nov 2015 20:31:02 +0100 Subject: [PATCH 070/124] priority of array index expression (IDEA-147503) --- .../psi/impl/source/tree/java/ReplaceExpressionUtil.java | 2 +- .../refactoring/inlineLocal/ArrayAccessPriority.java | 6 ++++++ .../refactoring/inlineLocal/ArrayAccessPriority.java.after | 5 +++++ .../com/intellij/refactoring/inline/InlineLocalTest.java | 4 ++++ 4 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 java/java-tests/testData/refactoring/inlineLocal/ArrayAccessPriority.java create mode 100644 java/java-tests/testData/refactoring/inlineLocal/ArrayAccessPriority.java.after diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/ReplaceExpressionUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/ReplaceExpressionUtil.java index 6b499e1bfdd5..f131c759a008 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/ReplaceExpressionUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/ReplaceExpressionUtil.java @@ -75,7 +75,7 @@ public class ReplaceExpressionUtil { } else if (i == JavaElementType.ARRAY_ACCESS_EXPRESSION) { int role = ((CompositeElement)oldParent).getChildRole(oldExpr); - return role != ChildRole.ARRAY_DIMENSION && priority < parentPriority; + return role != ChildRole.ARRAY_DIMENSION && role != ChildRole.INDEX && priority < parentPriority; } else if (i == JavaElementType.ARRAY_INITIALIZER_EXPRESSION) { return false; diff --git a/java/java-tests/testData/refactoring/inlineLocal/ArrayAccessPriority.java b/java/java-tests/testData/refactoring/inlineLocal/ArrayAccessPriority.java new file mode 100644 index 000000000000..adea1fa10edc --- /dev/null +++ b/java/java-tests/testData/refactoring/inlineLocal/ArrayAccessPriority.java @@ -0,0 +1,6 @@ +class C { + void f(int[] a, int i) { + int i1 = i + 1; + int temp = a[i1]; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/inlineLocal/ArrayAccessPriority.java.after b/java/java-tests/testData/refactoring/inlineLocal/ArrayAccessPriority.java.after new file mode 100644 index 000000000000..bf9e8dc573ea --- /dev/null +++ b/java/java-tests/testData/refactoring/inlineLocal/ArrayAccessPriority.java.after @@ -0,0 +1,5 @@ +class C { + void f(int[] a, int i) { + int temp = a[i + 1]; + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/refactoring/inline/InlineLocalTest.java b/java/java-tests/testSrc/com/intellij/refactoring/inline/InlineLocalTest.java index 6650bb7b6bed..11c62b549b68 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/inline/InlineLocalTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/inline/InlineLocalTest.java @@ -244,6 +244,10 @@ public class InlineLocalTest extends LightCodeInsightTestCase { doTest(true); } + public void testArrayAccessPriority() throws Exception { + doTest(true); + } + public void testLocalVarInsideLambdaBodyWriteUsage() throws Exception { doTest(true, "Cannot perform refactoring.\n" + "Variable 'hello' is accessed for writing"); From b59398ca6715bfe418732164235da0fce0f79338 Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Fri, 6 Nov 2015 22:43:12 +0300 Subject: [PATCH 071/124] Fixed the order of functions returned by getAllSuperFunctions() to match MRO (PY-16776) Previously we didn't respect the MRO and returned functions from early ancestors before later ancestors. Now we return them according to the MRO and we traverse methods by the types of ancestors instead of concrete PSI elements to invoke the extension points that change the list of ancestors. --- .../src/com/jetbrains/python/psi/PyClass.java | 5 ++- .../override/PyOverrideImplementUtil.java | 34 +++++++++---------- .../python/psi/impl/PyClassImpl.java | 26 +------------- .../search/PySuperMethodsSearchExecutor.java | 2 +- .../python/psi/types/PyTypeUtil.java | 18 ++++------ .../notImplementedOverriddenInParent.py | 12 +++++++ .../PyAbstractClassInspectionTest.java | 5 +++ 7 files changed, 43 insertions(+), 59 deletions(-) create mode 100644 python/testData/inspections/PyAbstractClassInspection/notImplementedOverriddenInParent.py diff --git a/python/psi-api/src/com/jetbrains/python/psi/PyClass.java b/python/psi-api/src/com/jetbrains/python/psi/PyClass.java index 40407d6edac2..36f19071610e 100644 --- a/python/psi-api/src/com/jetbrains/python/psi/PyClass.java +++ b/python/psi-api/src/com/jetbrains/python/psi/PyClass.java @@ -98,11 +98,10 @@ public interface PyClass extends PsiNameIdentifierOwner, PyStatement, NameDefine PyExpression[] getSuperClassExpressions(); /** - * Collects methods defined in the class and its ancestors if necessary. + * Collects methods defined in the class. *

- * This method does not access AST if underlying PSI is stub based and {@code inherited} parameter is false. + * This method does not access AST if underlying PSI is stub based. * - * @param inherited return inherited (parent) methods as well * @return class methods */ @NotNull diff --git a/python/src/com/jetbrains/python/codeInsight/override/PyOverrideImplementUtil.java b/python/src/com/jetbrains/python/codeInsight/override/PyOverrideImplementUtil.java index 042e115896c4..8b7e1d9a3599 100644 --- a/python/src/com/jetbrains/python/codeInsight/override/PyOverrideImplementUtil.java +++ b/python/src/com/jetbrains/python/codeInsight/override/PyOverrideImplementUtil.java @@ -16,6 +16,7 @@ package com.jetbrains.python.codeInsight.override; import com.google.common.collect.Lists; +import com.google.common.collect.Maps; import com.intellij.codeInsight.CodeInsightUtilCore; import com.intellij.featureStatistics.FeatureUsageTracker; import com.intellij.featureStatistics.ProductivityFeatureNames; @@ -41,8 +42,8 @@ import com.jetbrains.python.psi.*; import com.jetbrains.python.psi.impl.PyFunctionBuilder; import com.jetbrains.python.psi.impl.PyPsiUtils; import com.jetbrains.python.psi.types.PyClassLikeType; -import com.jetbrains.python.psi.types.PyTypeUtil; import com.jetbrains.python.psi.types.PyNoneType; +import com.jetbrains.python.psi.types.PyTypeUtil; import com.jetbrains.python.psi.types.TypeEvalContext; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -316,25 +317,22 @@ public class PyOverrideImplementUtil { return toClass.getName(); } + /** + * Returns all super functions available through MRO. + */ @NotNull - public static Collection getAllSuperFunctions(@NotNull PyClass pyClass, @NotNull TypeEvalContext context) { - - // This is a legacy approach. Should be removed soon since type-based members should be enough - final Map superFunctions = new HashMap(); - for (PyFunction function : pyClass.getMethods(true)) { - if (!superFunctions.containsKey(function.getName())) { - superFunctions.put(function.getName(), function); + public static List getAllSuperFunctions(@NotNull PyClass pyClass, @NotNull TypeEvalContext context) { + final Map functions = Maps.newLinkedHashMap(); + for (final PyClassLikeType type : pyClass.getAncestorTypes(context)) { + if (type != null) { + for (PyFunction function : PyTypeUtil.getMembersOfType(type, PyFunction.class, false, context)) { + final String name = function.getName(); + if (name != null && !functions.containsKey(name)) { + functions.put(name, function); + } + } } } - - - - final Set functions = new HashSet(superFunctions.values()); - final PyClassLikeType type = PyUtil.as(context.getType(pyClass), PyClassLikeType.class); - - if (type != null) { - functions.addAll(PyTypeUtil.getMembersOfType(type, PyFunction.class, context)); - } - return functions; + return Lists.newArrayList(functions.values()); } } diff --git a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java index 056d9dfa8b5c..e421b5392ecd 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java @@ -464,31 +464,7 @@ public class PyClassImpl extends PyBaseElementImpl implements PyCla @Override @NotNull public PyFunction[] getMethods(final boolean inherited) { - final PyFunction[] thisClassFunctions = - getClassChildren(PythonDialectsTokenSetProvider.INSTANCE.getFunctionDeclarationTokens(), PyFunction.ARRAY_FACTORY); - if (!inherited) { - return thisClassFunctions; - } - // Map to get rid of duplicated (overwritten methods) - final Map result = new HashMap(); - // We get classes in MRO order (hopefully), so last methods are last - for (final PyClass superClass : getAncestorClasses(null)) { - for (final PyFunction function : superClass.getMethods(false)) { - final String functionName = function.getName(); - if (functionName != null) { - result.put(functionName, function); - } - } - } - // We now need to add our own methods - for (final PyFunction function : thisClassFunctions) { - final String functionName = function.getName(); - if (functionName != null) { - result.put(functionName, function); - } - } - final Collection functionsToReturn = result.values(); - return functionsToReturn.toArray(new PyFunction[functionsToReturn.size()]); + return getClassChildren(PythonDialectsTokenSetProvider.INSTANCE.getFunctionDeclarationTokens(), PyFunction.ARRAY_FACTORY); } @Override diff --git a/python/src/com/jetbrains/python/psi/search/PySuperMethodsSearchExecutor.java b/python/src/com/jetbrains/python/psi/search/PySuperMethodsSearchExecutor.java index 3b92da74485e..50c2abb10c93 100644 --- a/python/src/com/jetbrains/python/psi/search/PySuperMethodsSearchExecutor.java +++ b/python/src/com/jetbrains/python/psi/search/PySuperMethodsSearchExecutor.java @@ -68,7 +68,7 @@ public class PySuperMethodsSearchExecutor implements QueryExecutor expected member type - * @return collection of members + * Returns members of certain type from {@link PyClassLikeType}. */ @NotNull - public static Collection getMembersOfType(@NotNull final PyClassLikeType type, - @NotNull final Class expectedMemberType, - @NotNull final TypeEvalContext context) { + public static List getMembersOfType(@NotNull final PyClassLikeType type, + @NotNull final Class expectedMemberType, + boolean inherited, + @NotNull final TypeEvalContext context) { final List result = new ArrayList(); type.visitMembers(new Processor() { @@ -60,7 +54,7 @@ public final class PyTypeUtil { } return true; } - }, true, context); + }, inherited, context); return result; } diff --git a/python/testData/inspections/PyAbstractClassInspection/notImplementedOverriddenInParent.py b/python/testData/inspections/PyAbstractClassInspection/notImplementedOverriddenInParent.py new file mode 100644 index 000000000000..b81c3b6ab7f4 --- /dev/null +++ b/python/testData/inspections/PyAbstractClassInspection/notImplementedOverriddenInParent.py @@ -0,0 +1,12 @@ +class A: + def foo(self): + raise NotImplementedError + + +class B(A): + def foo(self): + print('foo') + + +class C(B): + pass diff --git a/python/testSrc/com/jetbrains/python/inspections/PyAbstractClassInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyAbstractClassInspectionTest.java index 78c2b5f8e4bd..d5e5ad3127e8 100644 --- a/python/testSrc/com/jetbrains/python/inspections/PyAbstractClassInspectionTest.java +++ b/python/testSrc/com/jetbrains/python/inspections/PyAbstractClassInspectionTest.java @@ -52,6 +52,11 @@ public class PyAbstractClassInspectionTest extends PyInspectionTestCase { doTest(); } + // PY-16776 + public void testNotImplementedOverriddenInParent() { + doTest(); + } + @NotNull @Override protected Class getInspectionClass() { From b159c2d8e59473ae385f8fd63baf10f0277b0c95 Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Fri, 6 Nov 2015 22:46:32 +0300 Subject: [PATCH 072/124] Removed unused parameter --- .../psi-api/src/com/jetbrains/python/psi/PyClass.java | 2 +- .../codeInsight/PyMethodNavigationOffsetProvider.java | 2 +- .../completion/PySuperMethodCompletionContributor.java | 4 ++-- .../PyUserSkeletonsClassMembersProvider.java | 2 +- .../python/inspections/PyAbstractClassInspection.java | 2 +- .../inspections/PyOldStyleClassesInspection.java | 2 +- .../python/inspections/quickfix/AddFieldQuickFix.java | 2 +- .../PyUnresolvedReferencesInspection.java | 2 +- .../jetbrains/python/projectView/PyElementNode.java | 2 +- .../src/com/jetbrains/python/psi/impl/PyClassImpl.java | 8 ++++---- .../python/psi/stubs/PyClassAttributesIndex.java | 2 +- .../com/jetbrains/python/psi/types/PyTypeChecker.java | 2 +- .../classes/membersManager/MethodsManager.java | 4 ++-- .../refactoring/extractmethod/PyExtractMethodUtil.java | 2 +- .../attest/PythonAtTestConfigurationProducer.java | 2 +- .../python/testing/doctest/PythonDocTestUtil.java | 2 +- .../jetbrains/python/testing/pytest/PyTestUtil.java | 2 +- .../com/jetbrains/python/PyControlFlowBuilderTest.java | 4 ++-- .../testSrc/com/jetbrains/python/PyOverrideTest.java | 8 ++++---- python/testSrc/com/jetbrains/python/PyStubsTest.java | 10 +++++----- .../classes/PyDependenciesComparatorTest.java | 2 +- 21 files changed, 34 insertions(+), 34 deletions(-) diff --git a/python/psi-api/src/com/jetbrains/python/psi/PyClass.java b/python/psi-api/src/com/jetbrains/python/psi/PyClass.java index 36f19071610e..98c7be60a0d2 100644 --- a/python/psi-api/src/com/jetbrains/python/psi/PyClass.java +++ b/python/psi-api/src/com/jetbrains/python/psi/PyClass.java @@ -105,7 +105,7 @@ public interface PyClass extends PsiNameIdentifierOwner, PyStatement, NameDefine * @return class methods */ @NotNull - PyFunction[] getMethods(boolean inherited); + PyFunction[] getMethods(); /** * Get class properties. diff --git a/python/src/com/jetbrains/python/codeInsight/PyMethodNavigationOffsetProvider.java b/python/src/com/jetbrains/python/codeInsight/PyMethodNavigationOffsetProvider.java index 36c4faceaeff..438b79580f69 100644 --- a/python/src/com/jetbrains/python/codeInsight/PyMethodNavigationOffsetProvider.java +++ b/python/src/com/jetbrains/python/codeInsight/PyMethodNavigationOffsetProvider.java @@ -54,7 +54,7 @@ public class PyMethodNavigationOffsetProvider implements MethodNavigationOffsetP array.add(psiElement); } else if (psiElement instanceof PyClass) { - Collections.addAll(array, ((PyClass)psiElement).getMethods(false)); + Collections.addAll(array, ((PyClass)psiElement).getMethods()); } } } diff --git a/python/src/com/jetbrains/python/codeInsight/completion/PySuperMethodCompletionContributor.java b/python/src/com/jetbrains/python/codeInsight/completion/PySuperMethodCompletionContributor.java index 24af1dfacd99..f182fc83da58 100644 --- a/python/src/com/jetbrains/python/codeInsight/completion/PySuperMethodCompletionContributor.java +++ b/python/src/com/jetbrains/python/codeInsight/completion/PySuperMethodCompletionContributor.java @@ -57,13 +57,13 @@ public class PySuperMethodCompletionContributor extends CompletionContributor { return; } Set seenNames = new HashSet(); - for (PyFunction function : containingClass.getMethods(false)) { + for (PyFunction function : containingClass.getMethods()) { seenNames.add(function.getName()); } LanguageLevel languageLevel = LanguageLevel.forElement(parameters.getOriginalFile()); seenNames.addAll(PyNames.getBuiltinMethods(languageLevel).keySet()); for (PyClass ancestor : containingClass.getAncestorClasses(null)) { - for (PyFunction superMethod : ancestor.getMethods(false)) { + for (PyFunction superMethod : ancestor.getMethods()) { if (!seenNames.contains(superMethod.getName())) { String text = superMethod.getName() + superMethod.getParameterList().getText(); LookupElementBuilder element = LookupElementBuilder.create(text); diff --git a/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsClassMembersProvider.java b/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsClassMembersProvider.java index c7512d3f11b5..387aa2f81307 100644 --- a/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsClassMembersProvider.java +++ b/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsClassMembersProvider.java @@ -83,7 +83,7 @@ public class PyUserSkeletonsClassMembersProvider extends PyClassMembersProviderB public static Collection getClassMembers(@NotNull PyClass cls, boolean isDefinition) { final List result = new ArrayList(); - for (PyFunction function : cls.getMethods(false)) { + for (PyFunction function : cls.getMethods()) { final String name = function.getName(); final PyUtil.MethodFlags methodFlags = PyUtil.MethodFlags.of(function); final boolean instanceMethod = methodFlags == null || methodFlags.isInstanceMethod(); diff --git a/python/src/com/jetbrains/python/inspections/PyAbstractClassInspection.java b/python/src/com/jetbrains/python/inspections/PyAbstractClassInspection.java index 481db69e0594..8873fe5228c0 100644 --- a/python/src/com/jetbrains/python/inspections/PyAbstractClassInspection.java +++ b/python/src/com/jetbrains/python/inspections/PyAbstractClassInspection.java @@ -91,7 +91,7 @@ public class PyAbstractClassInspection extends PyInspection { return true; } } - for (PyFunction method : pyClass.getMethods(false)) { + for (PyFunction method : pyClass.getMethods()) { if (PyUtil.isDecoratedAsAbstract(method)) { return true; } diff --git a/python/src/com/jetbrains/python/inspections/PyOldStyleClassesInspection.java b/python/src/com/jetbrains/python/inspections/PyOldStyleClassesInspection.java index 532c5a5b4112..a866b36281e2 100644 --- a/python/src/com/jetbrains/python/inspections/PyOldStyleClassesInspection.java +++ b/python/src/com/jetbrains/python/inspections/PyOldStyleClassesInspection.java @@ -74,7 +74,7 @@ public class PyOldStyleClassesInspection extends PyInspection { registerProblem(attr, "Old-style class contains __slots__ definition", ProblemHighlightType.GENERIC_ERROR_OR_WARNING, null, quickFixes.toArray(new LocalQuickFix[quickFixes.size()])); } } - for (PyFunction attr : node.getMethods(false)) { + for (PyFunction attr : node.getMethods()) { if ("__getattribute__".equals(attr.getName())) { final ASTNode nameNode = attr.getNameNode(); assert nameNode != null; diff --git a/python/src/com/jetbrains/python/inspections/quickfix/AddFieldQuickFix.java b/python/src/com/jetbrains/python/inspections/quickfix/AddFieldQuickFix.java index 8029597a5405..5156205aa82f 100644 --- a/python/src/com/jetbrains/python/inspections/quickfix/AddFieldQuickFix.java +++ b/python/src/com/jetbrains/python/inspections/quickfix/AddFieldQuickFix.java @@ -163,7 +163,7 @@ public class AddFieldQuickFix implements LocalQuickFix { appendToMethod(newInit, callback); PsiElement addAnchor = null; - PyFunction[] meths = cls.getMethods(false); + PyFunction[] meths = cls.getMethods(); if (meths.length > 0) addAnchor = meths[0].getPrevSibling(); PyStatementList clsContent = cls.getStatementList(); newInit = (PyFunction) clsContent.addAfter(newInit, addAnchor); diff --git a/python/src/com/jetbrains/python/inspections/unresolvedReference/PyUnresolvedReferencesInspection.java b/python/src/com/jetbrains/python/inspections/unresolvedReference/PyUnresolvedReferencesInspection.java index d0b59e3f7fac..1bfe00a95fa7 100644 --- a/python/src/com/jetbrains/python/inspections/unresolvedReference/PyUnresolvedReferencesInspection.java +++ b/python/src/com/jetbrains/python/inspections/unresolvedReference/PyUnresolvedReferencesInspection.java @@ -888,7 +888,7 @@ public class PyUnresolvedReferencesInspection extends PyInspection { } } } - for (PyFunction method : containedClass.getMethods(false)) { + for (PyFunction method : containedClass.getMethods()) { if (expr.getText().equals(method.getName())) { actions.add(new UnresolvedReferenceAddSelfQuickFix(expr, qualifier)); } diff --git a/python/src/com/jetbrains/python/projectView/PyElementNode.java b/python/src/com/jetbrains/python/projectView/PyElementNode.java index dcf0088275dc..17e28cf102a1 100644 --- a/python/src/com/jetbrains/python/projectView/PyElementNode.java +++ b/python/src/com/jetbrains/python/projectView/PyElementNode.java @@ -50,7 +50,7 @@ public class PyElementNode extends BasePsiNode { for (PyClass aClass : pyClass.getNestedClasses()) { result.add(new PyElementNode(myProject, aClass, getSettings())); } - for (PyFunction function : pyClass.getMethods(false)) { + for (PyFunction function : pyClass.getMethods()) { result.add(new PyElementNode(myProject, function, getSettings())); } return result; diff --git a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java index e421b5392ecd..3fd8de69e7b5 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java @@ -463,7 +463,7 @@ public class PyClassImpl extends PyBaseElementImpl implements PyCla @Override @NotNull - public PyFunction[] getMethods(final boolean inherited) { + public PyFunction[] getMethods() { return getClassChildren(PythonDialectsTokenSetProvider.INSTANCE.getFunctionDeclarationTokens(), PyFunction.ARRAY_FACTORY); } @@ -587,7 +587,7 @@ public class PyClassImpl extends PyBaseElementImpl implements PyCla // look at @property decorators Map> grouped = new HashMap>(); // group suitable same-named methods, each group defines a property - for (PyFunction method : getMethods(false)) { + for (PyFunction method : getMethods()) { final String methodName = method.getName(); if (name == null || name.equals(methodName)) { List bucket = grouped.get(methodName); @@ -899,7 +899,7 @@ public class PyClassImpl extends PyBaseElementImpl implements PyCla private boolean visitMethods(Processor processor, boolean inherited, boolean skipClassObj, TypeEvalContext context) { - PyFunction[] methods = getMethods(false); + PyFunction[] methods = getMethods(); if (!ContainerUtil.process(methods, processor)) return false; if (inherited) { for (PyClass ancestor : getAncestorClasses(context)) { @@ -1013,7 +1013,7 @@ public class PyClassImpl extends PyBaseElementImpl implements PyCla collectInstanceAttributes(initMethod, result); } Set namesInInit = new HashSet(result.keySet()); - final PyFunction[] methods = getMethods(false); + final PyFunction[] methods = getMethods(); for (PyFunction method : methods) { if (!PyNames.INIT.equals(method.getName())) { collectInstanceAttributes(method, result, namesInInit); diff --git a/python/src/com/jetbrains/python/psi/stubs/PyClassAttributesIndex.java b/python/src/com/jetbrains/python/psi/stubs/PyClassAttributesIndex.java index d371ecc7b442..62036e848a6c 100644 --- a/python/src/com/jetbrains/python/psi/stubs/PyClassAttributesIndex.java +++ b/python/src/com/jetbrains/python/psi/stubs/PyClassAttributesIndex.java @@ -41,7 +41,7 @@ public class PyClassAttributesIndex extends StringStubIndexExtension { public static List getAllDeclaredAttributeNames(@NotNull PyClass pyClass) { final List members = ContainerUtil.concat(pyClass.getInstanceAttributes(), pyClass.getClassAttributes(), - Arrays.asList(pyClass.getMethods(false))); + Arrays.asList(pyClass.getMethods())); return ContainerUtil.mapNotNull(members, new Function() { @Override diff --git a/python/src/com/jetbrains/python/psi/types/PyTypeChecker.java b/python/src/com/jetbrains/python/psi/types/PyTypeChecker.java index 09aab39c0759..ae0450ecee0a 100644 --- a/python/src/com/jetbrains/python/psi/types/PyTypeChecker.java +++ b/python/src/com/jetbrains/python/psi/types/PyTypeChecker.java @@ -230,7 +230,7 @@ public class PyTypeChecker { boolean isDefinition, @NotNull TypeEvalContext context) { final Set attributes = new HashSet(); - for (PyFunction function : cls.getMethods(false)) { + for (PyFunction function : cls.getMethods()) { attributes.add(function.getName()); } for (PyTargetExpression instanceAttribute : cls.getInstanceAttributes()) { diff --git a/python/src/com/jetbrains/python/refactoring/classes/membersManager/MethodsManager.java b/python/src/com/jetbrains/python/refactoring/classes/membersManager/MethodsManager.java index 1ad4f03c53cf..4c5996cc6ddd 100644 --- a/python/src/com/jetbrains/python/refactoring/classes/membersManager/MethodsManager.java +++ b/python/src/com/jetbrains/python/refactoring/classes/membersManager/MethodsManager.java @@ -59,7 +59,7 @@ class MethodsManager extends MembersManager { @Override public boolean hasConflict(@NotNull final PyFunction member, @NotNull final PyClass aClass) { - return NamePredicate.hasElementWithSameName(member, Arrays.asList(aClass.getMethods(false))); + return NamePredicate.hasElementWithSameName(member, Arrays.asList(aClass.getMethods())); } @NotNull @@ -79,7 +79,7 @@ class MethodsManager extends MembersManager { @NotNull @Override protected List getMembersCouldBeMoved(@NotNull final PyClass pyClass) { - return FluentIterable.from(Arrays.asList(pyClass.getMethods(false))).filter(new NamelessFilter()).filter(NO_PROPERTIES).toList(); + return FluentIterable.from(Arrays.asList(pyClass.getMethods())).filter(new NamelessFilter()).filter(NO_PROPERTIES).toList(); } @Override diff --git a/python/src/com/jetbrains/python/refactoring/extractmethod/PyExtractMethodUtil.java b/python/src/com/jetbrains/python/refactoring/extractmethod/PyExtractMethodUtil.java index 9a7161c8d057..21c800a08ee4 100644 --- a/python/src/com/jetbrains/python/refactoring/extractmethod/PyExtractMethodUtil.java +++ b/python/src/com/jetbrains/python/refactoring/extractmethod/PyExtractMethodUtil.java @@ -201,7 +201,7 @@ public class PyExtractMethodUtil { scope.add(owner); final PyClass containingClass = ((PyFunction)owner).getContainingClass(); if (containingClass != null) { - for (PyFunction function : containingClass.getMethods(false)) { + for (PyFunction function : containingClass.getMethods()) { if (!function.equals(owner) && !function.equals(generatedMethod)) { scope.add(function); } diff --git a/python/src/com/jetbrains/python/testing/attest/PythonAtTestConfigurationProducer.java b/python/src/com/jetbrains/python/testing/attest/PythonAtTestConfigurationProducer.java index 40115fcdb343..ecf72053f29f 100644 --- a/python/src/com/jetbrains/python/testing/attest/PythonAtTestConfigurationProducer.java +++ b/python/src/com/jetbrains/python/testing/attest/PythonAtTestConfigurationProducer.java @@ -60,7 +60,7 @@ public class PythonAtTestConfigurationProducer extends } private static boolean hasTestFunction(@NotNull final PyClass pyClass) { - PyFunction[] methods = pyClass.getMethods(false); + PyFunction[] methods = pyClass.getMethods(); for (PyFunction function : methods) { PyDecoratorList decorators = function.getDecoratorList(); if (decorators == null) continue; diff --git a/python/src/com/jetbrains/python/testing/doctest/PythonDocTestUtil.java b/python/src/com/jetbrains/python/testing/doctest/PythonDocTestUtil.java index 351bbc01fd34..e0360ae5a6f5 100644 --- a/python/src/com/jetbrains/python/testing/doctest/PythonDocTestUtil.java +++ b/python/src/com/jetbrains/python/testing/doctest/PythonDocTestUtil.java @@ -58,7 +58,7 @@ public class PythonDocTestUtil { } public static boolean isDocTestClass(PyClass pyClass) { - for (PyFunction cls : pyClass.getMethods(false)) { + for (PyFunction cls : pyClass.getMethods()) { if (isDocTestFunction(cls)) { return true; } diff --git a/python/src/com/jetbrains/python/testing/pytest/PyTestUtil.java b/python/src/com/jetbrains/python/testing/pytest/PyTestUtil.java index 4bc36647257c..a888e1292da9 100644 --- a/python/src/com/jetbrains/python/testing/pytest/PyTestUtil.java +++ b/python/src/com/jetbrains/python/testing/pytest/PyTestUtil.java @@ -83,7 +83,7 @@ public class PyTestUtil { if (className == null) return false; final String name = className.toLowerCase(); if (name.startsWith("test")) { - for (PyFunction cls : pyClass.getMethods(false)) { + for (PyFunction cls : pyClass.getMethods()) { if (isPyTestFunction(cls)) { return true; } diff --git a/python/testSrc/com/jetbrains/python/PyControlFlowBuilderTest.java b/python/testSrc/com/jetbrains/python/PyControlFlowBuilderTest.java index c5e489c06485..203b462c5a44 100644 --- a/python/testSrc/com/jetbrains/python/PyControlFlowBuilderTest.java +++ b/python/testSrc/com/jetbrains/python/PyControlFlowBuilderTest.java @@ -205,7 +205,7 @@ public class PyControlFlowBuilderTest extends LightMarkedTestCase { configureByFile(testName + ".py"); final String fullPath = getTestDataPath() + testName + ".txt"; final PyClass pyClass = ((PyFile) myFile).getTopLevelClasses().get(0); - final ControlFlow flow = ControlFlowCache.getControlFlow(pyClass.getMethods(false)[0]); + final ControlFlow flow = ControlFlowCache.getControlFlow(pyClass.getMethods()[0]); check(fullPath, flow); } @@ -214,7 +214,7 @@ public class PyControlFlowBuilderTest extends LightMarkedTestCase { configureByFile(testName + ".py"); final String fullPath = getTestDataPath() + testName + ".txt"; final PyClass pyClass = ((PyFile) myFile).getTopLevelClasses().get(0); - final ControlFlow flow = ControlFlowCache.getControlFlow(pyClass.getMethods(false)[0]); + final ControlFlow flow = ControlFlowCache.getControlFlow(pyClass.getMethods()[0]); check(fullPath, flow); } diff --git a/python/testSrc/com/jetbrains/python/PyOverrideTest.java b/python/testSrc/com/jetbrains/python/PyOverrideTest.java index e89eb6c6bb7c..53a5d7f55d12 100644 --- a/python/testSrc/com/jetbrains/python/PyOverrideTest.java +++ b/python/testSrc/com/jetbrains/python/PyOverrideTest.java @@ -34,7 +34,7 @@ import java.util.Collections; public class PyOverrideTest extends PyTestCase { private void doTest() { myFixture.configureByFile("override/" + getTestName(true) + ".py"); - PyFunction toOverride = getTopLevelClass(0).getMethods(false) [0]; + PyFunction toOverride = getTopLevelClass(0).getMethods() [0]; PyOverrideImplementUtil.overrideMethods(myFixture.getEditor(), getTopLevelClass(1), Collections.singletonList(new PyMethodMember(toOverride)), false); myFixture.checkResultByFile("override/" + getTestName(true) + "_after.py", true); @@ -91,7 +91,7 @@ public class PyOverrideTest extends PyTestCase { public void testInnerClass() { // PY-10976 myFixture.configureByFile("override/" + getTestName(true) + ".py"); - PyFunction toOverride = getTopLevelClass(0).getMethods(false)[0]; + PyFunction toOverride = getTopLevelClass(0).getMethods()[0]; PyClass pyClass = getTopLevelClass(1).getNestedClasses()[0]; PyOverrideImplementUtil.overrideMethods(myFixture.getEditor(), pyClass, Collections.singletonList(new PyMethodMember(toOverride)), false); @@ -100,7 +100,7 @@ public class PyOverrideTest extends PyTestCase { public void testInnerFunctionClass() { myFixture.configureByFile("override/" + getTestName(true) + ".py"); - PyFunction toOverride = getTopLevelClass(0).getMethods(false)[0]; + PyFunction toOverride = getTopLevelClass(0).getMethods()[0]; final PsiElement element = myFixture.getElementAtCaret(); PyOverrideImplementUtil.overrideMethods(myFixture.getEditor(), PsiTreeUtil.getParentOfType(element, PyClass.class, false), Collections.singletonList(new PyMethodMember(toOverride)), false); @@ -120,7 +120,7 @@ public class PyOverrideTest extends PyTestCase { public void testImplement() { myFixture.configureByFile("override/" + getTestName(true) + ".py"); - PyFunction toImplement = getTopLevelClass(0).getMethods(false)[1]; + PyFunction toImplement = getTopLevelClass(0).getMethods()[1]; PyOverrideImplementUtil.overrideMethods(myFixture.getEditor(), getTopLevelClass(1), Collections.singletonList(new PyMethodMember(toImplement)), true); myFixture.checkResultByFile("override/" + getTestName(true) + "_after.py", true); diff --git a/python/testSrc/com/jetbrains/python/PyStubsTest.java b/python/testSrc/com/jetbrains/python/PyStubsTest.java index f553adf47d15..6b63660f8be5 100644 --- a/python/testSrc/com/jetbrains/python/PyStubsTest.java +++ b/python/testSrc/com/jetbrains/python/PyStubsTest.java @@ -70,7 +70,7 @@ public class PyStubsTest extends PyTestCase { assertEquals("staticField", attrs.get(0).getName()); assertTrue(attrs.get(0).getAssignedQName().matches("deco")); - final PyFunction[] methods = pyClass.getMethods(false); + final PyFunction[] methods = pyClass.getMethods(); assertEquals(2, methods.length); assertEquals("__init__", methods [0].getName()); assertEquals("fooFunction", methods [1].getName()); @@ -117,7 +117,7 @@ public class PyStubsTest extends PyTestCase { Property prop = pyClass.findProperty("value", true, null); Maybe maybe_function = prop.getGetter(); assertTrue(maybe_function.isDefined()); - assertEquals(pyClass.getMethods(false)[0], maybe_function.value()); + assertEquals(pyClass.getMethods()[0], maybe_function.value()); Property setvalueProp = pyClass.findProperty("setvalue", true, null); Maybe setter = setvalueProp.getSetter(); @@ -130,10 +130,10 @@ public class PyStubsTest extends PyTestCase { prop = pyClass.findProperty("x", true, null); maybe_function = prop.getGetter(); assertTrue(maybe_function.isDefined()); - assertEquals(pyClass.getMethods(false)[0], maybe_function.value()); + assertEquals(pyClass.getMethods()[0], maybe_function.value()); maybe_function = prop.getSetter(); assertTrue(maybe_function.isDefined()); - assertEquals(pyClass.getMethods(false)[1], maybe_function.value()); + assertEquals(pyClass.getMethods()[1], maybe_function.value()); // ...and the juice: assertNotParsed(file); @@ -332,7 +332,7 @@ public class PyStubsTest extends PyTestCase { public void testWrappedStaticMethod() { final PyFileImpl file = (PyFileImpl) getTestFile(); final PyClass pyClass = file.getTopLevelClasses().get(0); - final PyFunction[] methods = pyClass.getMethods(false); + final PyFunction[] methods = pyClass.getMethods(); assertEquals(1, methods.length); final PyFunction.Modifier modifier = methods[0].getModifier(); assertEquals(PyFunction.Modifier.STATICMETHOD, modifier); diff --git a/python/testSrc/com/jetbrains/python/refactoring/classes/PyDependenciesComparatorTest.java b/python/testSrc/com/jetbrains/python/refactoring/classes/PyDependenciesComparatorTest.java index b3be3825f970..ba952c3f2456 100644 --- a/python/testSrc/com/jetbrains/python/refactoring/classes/PyDependenciesComparatorTest.java +++ b/python/testSrc/com/jetbrains/python/refactoring/classes/PyDependenciesComparatorTest.java @@ -22,7 +22,7 @@ public class PyDependenciesComparatorTest extends PyTestCase { @SuppressWarnings("ConstantConditions") // Can't be null (class has docstring) PsiElement docStringExpression = clazz.getDocStringExpression().getParent(); - PyFunction method = clazz.getMethods(false)[0]; + PyFunction method = clazz.getMethods()[0]; PsiElement classField = clazz.getClassAttributes().get(0).getParent(); final List elementList = new ArrayList(); From b171c04f50763631611d4d6c54a2be1c24c05aef Mon Sep 17 00:00:00 2001 From: Daniil Ovchinnikov Date: Tue, 3 Nov 2015 16:53:58 +0300 Subject: [PATCH 073/124] [groovy] properly display `as`-coercion trait types in quick info. --- .../lang/documentation/GroovyDocumentationProvider.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/documentation/GroovyDocumentationProvider.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/documentation/GroovyDocumentationProvider.java index 53acacb07d74..c3476c287db5 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/documentation/GroovyDocumentationProvider.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/documentation/GroovyDocumentationProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * 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. @@ -209,7 +209,7 @@ public class GroovyDocumentationProvider implements CodeDocumentationProvider, E if (inferredType != null) { buffer.append("[inferred type] "); - PsiImplUtil.appendTypeString(buffer, inferredType, originalElement); + appendTypeString(buffer, inferredType, originalElement); } else { buffer.append("[cannot infer type]"); From 331a1d487326997cc2560f118abc7d11eb57e6af Mon Sep 17 00:00:00 2001 From: Daniil Ovchinnikov Date: Tue, 3 Nov 2015 17:06:08 +0300 Subject: [PATCH 074/124] [groovy] enable GrWithTraitTypeCalculator in Groovy plugin. --- plugins/groovy/src/META-INF/plugin.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/groovy/src/META-INF/plugin.xml b/plugins/groovy/src/META-INF/plugin.xml index 567c72430b0c..40b1b701a1ee 100644 --- a/plugins/groovy/src/META-INF/plugin.xml +++ b/plugins/groovy/src/META-INF/plugin.xml @@ -128,6 +128,8 @@ + From a3a04702bbb600e19c19e92189393cf826c7eb1e Mon Sep 17 00:00:00 2001 From: Daniil Ovchinnikov Date: Fri, 6 Nov 2015 22:49:35 +0300 Subject: [PATCH 075/124] [groovy] make GrTraitType extend PsiIntersectionType. Tests included. - Get rid of mock trait definition and its processing. - Now we can process it like PsiIntersection type. - Proper trait ordering in completion and resolve restored. --- .../com/intellij/psi/PsiIntersectionType.java | 4 +- .../groovy/lang/psi/impl/GrTraitType.java | 379 ++---------------- .../expressions/GrReferenceResolveRunner.java | 42 +- .../statements/expressions/TypesUtil.java | 7 +- .../path/GrWithTraitTypeCalculator.java | 10 +- .../types/GrSafeCastExpressionImpl.java | 4 +- .../groovy/lang/resolve/ResolveUtil.java | 6 +- .../CompleteReferenceExpression.java | 21 +- .../GroovyDocumentationProvider.java | 6 +- .../plugins/groovy/LightGroovyTestCase.groovy | 7 +- .../resolve/GroovyTraitCoercionTest.groovy | 168 ++++++++ .../lang/resolve/ResolvePropertyTest.groovy | 3 +- 12 files changed, 248 insertions(+), 409 deletions(-) create mode 100644 plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/GroovyTraitCoercionTest.groovy diff --git a/java/java-psi-api/src/com/intellij/psi/PsiIntersectionType.java b/java/java-psi-api/src/com/intellij/psi/PsiIntersectionType.java index f590c38392d6..3eec614acb26 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiIntersectionType.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiIntersectionType.java @@ -32,7 +32,7 @@ import java.util.*; public class PsiIntersectionType extends PsiType.Stub { private final PsiType[] myConjuncts; - private PsiIntersectionType(@NotNull PsiType[] conjuncts) { + protected PsiIntersectionType(@NotNull PsiType[] conjuncts) { super(PsiAnnotation.EMPTY_ARRAY); myConjuncts = conjuncts; } @@ -67,7 +67,7 @@ public class PsiIntersectionType extends PsiType.Stub { } } - private static Set flatten(PsiType[] conjuncts, Set types) { + protected static Set flatten(PsiType[] conjuncts, Set types) { for (PsiType conjunct : conjuncts) { if (conjunct instanceof PsiIntersectionType) { PsiIntersectionType type = (PsiIntersectionType)conjunct; diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrTraitType.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrTraitType.java index a8bf62957332..3faf99eaa8d8 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrTraitType.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrTraitType.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * 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. @@ -15,389 +15,96 @@ */ package org.jetbrains.plugins.groovy.lang.psi.impl; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.util.Condition; -import com.intellij.openapi.util.VolatileNotNullLazyValue; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.pom.java.LanguageLevel; -import com.intellij.psi.*; -import com.intellij.psi.search.GlobalSearchScope; -import com.intellij.psi.util.*; -import com.intellij.util.ArrayUtil; +import com.intellij.psi.PsiClassType; +import com.intellij.psi.PsiIntersectionType; +import com.intellij.psi.PsiType; +import com.intellij.psi.util.PsiTypesUtil; import com.intellij.util.Function; -import com.intellij.util.IncorrectOperationException; import com.intellij.util.containers.ContainerUtil; -import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrSafeCastExpression; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrImplementsClause; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrReferenceList; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition; -import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement; -import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeParameter; -import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeParameterList; import org.jetbrains.plugins.groovy.lang.psi.util.GrTraitUtil; -import java.util.Collections; +import java.util.LinkedHashSet; import java.util.List; -import java.util.Map; +import java.util.Set; -/** - * Created by Max Medvedev on 20/05/14 - */ -public class GrTraitType extends PsiClassType { +public class GrTraitType extends PsiIntersectionType { - private static final Logger LOG = Logger.getInstance(GrTraitType.class); + private final @NotNull PsiType myExprType; + private final @NotNull List myTraitTypes; - private final GrExpression myOriginal; + private GrTraitType(@NotNull PsiType[] types) { + super(types); + myExprType = types[0]; + myTraitTypes = ContainerUtil.newArrayList(types, 1, types.length); + } - private final PsiClassType myExprType; - private final List myTraitTypes; + @NotNull + public PsiType getExprType() { + return myExprType; + } - private final GlobalSearchScope myResolveScope; - - private final VolatileNotNullLazyValue myParameters = new VolatileNotNullLazyValue() { - @NotNull - @Override - protected PsiType[] compute() { - List result = ContainerUtil.newArrayList(); - ContainerUtil.addAll(result, myExprType.getParameters()); - for (PsiClassType type : myTraitTypes) { - ContainerUtil.addAll(result, type.getParameters()); - } - return result.toArray(new PsiType[result.size()]); - } - }; - - - public GrTraitType(@NotNull GrExpression original, - @NotNull PsiClassType exprType, - @NotNull List traitTypes, - @NotNull GlobalSearchScope resolveScope, LanguageLevel languageLevel) { - super(languageLevel); - myOriginal = original; - myResolveScope = resolveScope; - myExprType = exprType; - myTraitTypes = ContainerUtil.newArrayList(traitTypes); + @NotNull + public List getTraitTypes() { + return myTraitTypes; } @NotNull @Override public String getPresentableText() { - return myExprType.getPresentableText() + " as " + StringUtil.join(ContainerUtil.map(myTraitTypes, new Function() { + return myExprType.getPresentableText() + " as " + StringUtil.join(ContainerUtil.map(myTraitTypes, new Function() { @Override - public String fun(PsiClassType type) { + public String fun(PsiType type) { return type.getPresentableText(); } }), ", "); } - @NotNull - @Override - public String getCanonicalText() { - return myExprType.getCanonicalText(); - } - @NotNull @Override public String getInternalCanonicalText() { - return myExprType.getCanonicalText() + " as " + StringUtil.join(ContainerUtil.map(myTraitTypes, new Function() { + return myExprType.getCanonicalText() + " as " + StringUtil.join(ContainerUtil.map(myTraitTypes, new Function() { @Override - public String fun(PsiClassType type) { - return type.getCanonicalText(); + public String fun(PsiType type) { + return type.getInternalCanonicalText(); } }), ", "); } - @Override - public boolean isValid() { - return myExprType.isValid() && ContainerUtil.find(myTraitTypes, new Condition() { - @Override - public boolean value(PsiClassType type) { - return !type.isValid(); - } - }) == null; - } - - @Override - public boolean equalsToText(@NotNull @NonNls String text) { - return false; - } - - @NotNull - @Override - public LanguageLevel getLanguageLevel() { - return myLanguageLevel; - } - - @NotNull - @Override - public PsiClassType setLanguageLevel(@NotNull LanguageLevel languageLevel) { - return new GrTraitType(myOriginal, myExprType, myTraitTypes, myResolveScope, languageLevel); - } - + // todo move this method to org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.types.GrSafeCastExpressionImpl @Nullable - @Override - public PsiClass resolve() { - return getMockTypeDefinition(); - } - - @Override - public String getClassName() { - return null; - } - - @NotNull - @Override - public PsiType[] getParameters() { - return myParameters.getValue(); - } - - @NotNull - @Override - public PsiType[] getSuperTypes() { - PsiType[] result = new PsiType[myTraitTypes.size() + 1]; - result[0] = myExprType; - ArrayUtil.copy(myTraitTypes, result, 1); - return result; - } - - @NotNull - @Override - public ClassResolveResult resolveGenerics() { - return CachedValuesManager.getCachedValue(myOriginal, new CachedValueProvider() { - @Nullable - @Override - public Result compute() { - final GrTypeDefinition definition = new MockTypeBuilder().buildMockTypeDefinition(); - final PsiSubstitutor substitutor = new SubstitutorBuilder(definition).buildSubstitutor(); - - return Result.create(new TraitResolveResult(definition, substitutor), PsiModificationTracker.MODIFICATION_COUNT); - } - }); - } - - @NotNull - @Override - public PsiClassType rawType() { - return new GrTraitType(myOriginal, myExprType.rawType(), ContainerUtil.map(myTraitTypes, new Function() { - @Override - public PsiClassType fun(PsiClassType type) { - return type.rawType(); - } - }), myResolveScope, myLanguageLevel); - } - - @NotNull - @Override - public GlobalSearchScope getResolveScope() { - return myResolveScope; - } - - @Nullable - public GrTypeDefinition getMockTypeDefinition() { - return CachedValuesManager.getCachedValue(myOriginal, new CachedValueProvider() { - @Nullable - @Override - public Result compute() { - return Result.create(new MockTypeBuilder().buildMockTypeDefinition(), PsiModificationTracker.MODIFICATION_COUNT); - } - }); - } - - public PsiClassType getExprType() { - return myExprType; - } - - public List getTraitTypes() { - return Collections.unmodifiableList(myTraitTypes); - } - - public GrTraitType erasure() { - PsiClassType exprType = (PsiClassType)TypeConversionUtil.erasure(myExprType); - List traitTypes = ContainerUtil.map(myTraitTypes, new Function() { - @Override - public PsiClassType fun(PsiClassType type) { - return (PsiClassType)TypeConversionUtil.erasure(type); - } - }); - return new GrTraitType(myOriginal, exprType, traitTypes, myResolveScope, LanguageLevel.JDK_1_5); - } - - @Nullable - public static GrTraitType createTraitClassType(@NotNull GrSafeCastExpression safeCastExpression) { + public static PsiType createTraitClassType(@NotNull GrSafeCastExpression safeCastExpression) { GrExpression operand = safeCastExpression.getOperand(); PsiType exprType = operand.getType(); - if (!(exprType instanceof PsiClassType)) return null; + if (!(exprType instanceof PsiClassType) && !(exprType instanceof GrTraitType)) return null; GrTypeElement typeElement = safeCastExpression.getCastTypeElement(); if (typeElement == null) return null; PsiType type = typeElement.getType(); if (!GrTraitUtil.isTrait(PsiTypesUtil.getPsiClass(type))) return null; - return new GrTraitType(safeCastExpression, ((PsiClassType)exprType), Collections.singletonList((PsiClassType)type), safeCastExpression.getResolveScope(), - LanguageLevel.JDK_1_5); + return createTraitClassType(exprType, ContainerUtil.newSmartList(type)); } - - @NotNull - public static GrTraitType createTraitClassType(@NotNull GrExpression context, - @NotNull PsiClassType exprType, - @NotNull List traitTypes, - @NotNull GlobalSearchScope resolveScope) { - return new GrTraitType(context, exprType, traitTypes, resolveScope, LanguageLevel.JDK_1_5); + public static PsiType createTraitClassType(@NotNull PsiType type, @NotNull List traits) { + return createTraitClassType(ContainerUtil.prepend(traits, type)); } - private static class TraitResolveResult implements ClassResolveResult { - - private final GrTypeDefinition myDefinition; - private final PsiSubstitutor mySubstitutor; - - public TraitResolveResult(GrTypeDefinition definition, PsiSubstitutor substitutor) { - myDefinition = definition; - mySubstitutor = substitutor; - } - - @Override - public GrTypeDefinition getElement() { - return myDefinition; - } - - @NotNull - @Override - public PsiSubstitutor getSubstitutor() { - return mySubstitutor; - } - - @Override - public boolean isPackagePrefixPackageReference() { - return false; - } - - @Override - public boolean isAccessible() { - return true; - } - - @Override - public boolean isStaticsScopeCorrect() { - return true; - } - - @Override - public PsiElement getCurrentFileResolveScope() { - return null; - } - - @Override - public boolean isValidResult() { - return true; - } - } - - private class MockTypeBuilder { - GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(myOriginal.getProject()); - - @Nullable - public GrTypeDefinition buildMockTypeDefinition() { - try { - - StringBuilder buffer = new StringBuilder("class _____________Temp___________ "); - prepareGenerics(buffer); - buffer.append(" extends Super implements Trait {}"); - GrTypeDefinition definition = factory.createTypeDefinition(buffer.toString()); - replaceReferenceWith(definition.getExtendsClause(), myExprType); - addReferencesWith(definition.getImplementsClause(), myTraitTypes, myExprType.getParameterCount()); - return definition; + public static PsiType createTraitClassType(@NotNull List types) { + final Set flattened = flatten(types.toArray(createArray(types.size())), new LinkedHashSet() { + @Override + public boolean add(PsiType type) { + remove(type); + return super.add(type); } - catch (IncorrectOperationException e) { - return null; - } - } - - private void prepareGenerics(StringBuilder buffer) { - int count = myExprType.getParameterCount(); - for (PsiClassType trait : myTraitTypes) { - count += trait.getParameterCount(); - } - if (count == 0) return; - - buffer.append('<'); - for (int i = 0; i < count; i++) { - buffer.append("T").append(i).append(","); - } - buffer.replace(buffer.length() - 1, buffer.length(), ">"); - } - - private void addReferencesWith(@Nullable GrImplementsClause clause, @NotNull List traitTypes, int parameterOffset) { - LOG.assertTrue(clause != null); - clause.getReferenceElementsGroovy()[0].delete(); - for (PsiClassType type : traitTypes) { - processType(clause, type, parameterOffset); - parameterOffset += type.getParameterCount(); - } - } - - private void replaceReferenceWith(@Nullable GrReferenceList clause, @NotNull PsiClassType type) { - LOG.assertTrue(clause != null); - clause.getReferenceElementsGroovy()[0].delete(); - processType(clause, type, 0); - } - - private void processType(@NotNull GrReferenceList clause, @NotNull PsiClassType type, int parameterOffset) { - PsiClass resolved = type.resolve(); - if (resolved != null) { - String qname = resolved.getQualifiedName(); - StringBuilder buffer = new StringBuilder(); - buffer.append(qname); - int parameterCount = type.getParameterCount(); - if (parameterCount > 0) { - buffer.append('<'); - for (int i = 0; i < parameterCount; i++) { - buffer.append("T").append(parameterOffset + i).append(','); - } - buffer.replace(buffer.length() - 1, buffer.length(), ">"); - } - - GrCodeReferenceElement ref = factory.createCodeReferenceElementFromText(buffer.toString()); - clause.add(ref); - } - } - } - - private class SubstitutorBuilder { - - private final GrTypeParameter[] myParameters; - private int myOffset = 0; - - public SubstitutorBuilder(@NotNull GrTypeDefinition definition) { - GrTypeParameterList typeParameterList = definition.getTypeParameterList(); - myParameters = typeParameterList != null ? typeParameterList.getTypeParameters() : GrTypeParameter.EMPTY_ARRAY; - } - - @NotNull - public PsiSubstitutor buildSubstitutor() { - if (myParameters.length == 0) return PsiSubstitutor.EMPTY; - - Map map = ContainerUtil.newLinkedHashMap(); - putMappingAndReturnOffset(map, myExprType); - for (PsiClassType type : myTraitTypes) { - putMappingAndReturnOffset(map, type); - } - - return JavaPsiFacade.getElementFactory(myOriginal.getProject()).createSubstitutor(map); - } - - private void putMappingAndReturnOffset(@NotNull Map map, @NotNull PsiClassType type) { - PsiType[] args = type.getParameters(); - for (int i = 0; i < args.length; i++) { - map.put(myParameters[myOffset + i], args[i]); - } - myOffset += args.length; - } + }); + final PsiType[] conjuncts = flattened.toArray(createArray(flattened.size())); + if (conjuncts.length == 1) return conjuncts[0]; + return new GrTraitType(conjuncts); } } diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrReferenceResolveRunner.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrReferenceResolveRunner.java index fa201a4713e7..fdd9b1129fc4 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrReferenceResolveRunner.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrReferenceResolveRunner.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * 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. @@ -34,9 +34,6 @@ import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil; import org.jetbrains.plugins.groovy.lang.resolve.processors.ClassHint; import org.jetbrains.plugins.groovy.lang.resolve.processors.ResolverProcessor; -import java.util.List; -import java.util.ListIterator; - /** * @author Medvedev Max */ @@ -129,11 +126,6 @@ public class GrReferenceResolveRunner { } } } - else if (qualifierType instanceof PsiIntersectionType) { - for (PsiType conjunct : ((PsiIntersectionType)qualifierType).getConjuncts()) { - if (!processQualifierType(conjunct, state)) return false; - } - } else { if (!processQualifierType(qualifierType, state)) return false; if (qualifier instanceof GrReferenceExpression && !PsiUtil.isSuperReference(qualifier) && !PsiUtil.isInstanceThisRef(qualifier)) { @@ -174,20 +166,16 @@ public class GrReferenceResolveRunner { ? ((PsiDisjunctionType)originalQualifierType).getLeastUpperBound() : originalQualifierType; - if (qualifierType instanceof PsiIntersectionType) { + if (qualifierType instanceof GrTraitType) { + return processTraitType((GrTraitType)qualifierType, state); + } + else if (qualifierType instanceof PsiIntersectionType) { for (PsiType conjunct : ((PsiIntersectionType)qualifierType).getConjuncts()) { if (!processQualifierType(conjunct, state)) return false; } return true; } - if (qualifierType instanceof GrTraitType) { - if (!processTraitType((GrTraitType)qualifierType, state)) { - return false; - } - return true; - } - if (qualifierType instanceof PsiClassType) { PsiClassType.ClassResolveResult qualifierResult = ((PsiClassType)qualifierType).resolveGenerics(); PsiClass qualifierClass = qualifierResult.getElement(); @@ -217,24 +205,10 @@ public class GrReferenceResolveRunner { } private boolean processTraitType(@NotNull GrTraitType traitType, @NotNull ResolveState state) { - GrTypeDefinition mockDefinition = traitType.getMockTypeDefinition(); - if (mockDefinition != null) { - if (!mockDefinition.processDeclarations(processor, state, null, place)) { - return false; - } + final PsiType[] conjuncts = traitType.getConjuncts(); + for (int i = conjuncts.length - 1; i >= 0; i--) { + if (!processQualifierType(conjuncts[i], state)) return false; } - else { - PsiClassType exprType = traitType.getExprType(); - - if (!processQualifierType(exprType, state)) return false; - - List traitTypes = traitType.getTraitTypes(); - for (ListIterator iterator = traitTypes.listIterator(); iterator.hasPrevious(); ) { - PsiClassType type = iterator.previous(); - if (!processQualifierType(type, state)) return false; - } - } - return true; } } diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/TypesUtil.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/TypesUtil.java index eb48749a95cf..7eb1ac7654b2 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/TypesUtil.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/TypesUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * 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. @@ -310,9 +310,8 @@ public class TypesUtil { } if (rType instanceof GrTraitType) { - if (isAssignableWithoutConversions(lType, ((GrTraitType)rType).getExprType(), context)) return true; - for (PsiClassType trait : ((GrTraitType)rType).getTraitTypes()) { - if (isAssignableWithoutConversions(lType, trait, context)) return true; + for (PsiType type : ((GrTraitType)rType).getConjuncts()) { + if (isAssignableWithoutConversions(lType, type, context)) return true; } return false; } diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/path/GrWithTraitTypeCalculator.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/path/GrWithTraitTypeCalculator.java index e53d5e394646..2c0459f20c58 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/path/GrWithTraitTypeCalculator.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/path/GrWithTraitTypeCalculator.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * 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. @@ -51,22 +51,22 @@ public class GrWithTraitTypeCalculator extends GrCallExpressionTypeCalculator { if (originalObject == null) return null; PsiType invokedType = originalObject.getType(); - if (!(invokedType instanceof PsiClassType)) return null; + if (!(invokedType instanceof PsiClassType) && !(invokedType instanceof GrTraitType)) return null; PsiClass containingClass = resolvedMethod.getContainingClass(); if (containingClass == null || !GroovyCommonClassNames.DEFAULT_GROOVY_METHODS.equals(containingClass.getQualifiedName())) return null; - List traits = ContainerUtil.newArrayList(); + List traits = ContainerUtil.newArrayList(); GrExpression[] args = callExpression.getArgumentList().getExpressionArguments(); for (GrExpression arg : args) { PsiType type = arg.getType(); PsiType classItem = PsiUtil.substituteTypeParameter(type, CommonClassNames.JAVA_LANG_CLASS, 0, false); PsiClass psiClass = PsiTypesUtil.getPsiClass(classItem); if (GrTraitUtil.isTrait(psiClass)) { - traits.add((PsiClassType)classItem); + traits.add(classItem); } } - return GrTraitType.createTraitClassType(callExpression, (PsiClassType)invokedType, traits, callExpression.getResolveScope()); + return GrTraitType.createTraitClassType(invokedType, traits); } } diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/types/GrSafeCastExpressionImpl.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/types/GrSafeCastExpressionImpl.java index 78aa01b21860..f1e69345f5bf 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/types/GrSafeCastExpressionImpl.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/types/GrSafeCastExpressionImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * 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. @@ -67,7 +67,7 @@ public class GrSafeCastExpressionImpl extends GrExpressionImpl implements GrSafe return JavaPsiFacade.getElementFactory(cast.getProject()).createType(resolved, substitutor); } - GrTraitType traitClassType = GrTraitType.createTraitClassType(cast); + PsiType traitClassType = GrTraitType.createTraitClassType(cast); if (traitClassType != null) { return traitClassType; } diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ResolveUtil.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ResolveUtil.java index f38b17bc9b83..68f7f8440945 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ResolveUtil.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/resolve/ResolveUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * 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. @@ -59,7 +59,6 @@ import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.imports.GrImportStatem import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement; import org.jetbrains.plugins.groovy.lang.psi.api.util.GrStatementOwner; import org.jetbrains.plugins.groovy.lang.psi.impl.GrClosureType; -import org.jetbrains.plugins.groovy.lang.psi.impl.GrTraitType; import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyResolveResultImpl; import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; @@ -369,9 +368,6 @@ public class ResolveUtil { final PsiClass superClass = cls.getSuperClass(); key = cls.getName() + (superClass == null ? CommonClassNames.JAVA_LANG_OBJECT : superClass.getName()); } - else if (base instanceof GrTraitType) { - key = ((GrTraitType)base).erasure().getCanonicalText(); - } else if (base instanceof PsiClassType) { key = TypesUtil.getQualifiedName(base); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/CompleteReferenceExpression.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/CompleteReferenceExpression.java index 1b99010ef18b..3878f65b556a 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/CompleteReferenceExpression.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/CompleteReferenceExpression.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * 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. @@ -300,24 +300,17 @@ public class CompleteReferenceExpression { } getVariantsFromQualifierType(TypesUtil.getJavaLangObject(qualifier), project); } + else if (qualifierType instanceof GrTraitType) { + PsiType[] conjuncts = ((GrTraitType)qualifierType).getConjuncts(); + for (int i = conjuncts.length - 1; i >= 0; i--) { + getVariantsFromQualifierType(conjuncts[i], project); + } + } else if (qualifierType instanceof PsiIntersectionType) { for (PsiType conjunct : ((PsiIntersectionType)qualifierType).getConjuncts()) { getVariantsFromQualifierType(conjunct, project); } } - else if (qualifierType instanceof GrTraitType) { - GrTypeDefinition definition = ((GrTraitType)qualifierType).getMockTypeDefinition(); - if (definition != null) { - PsiClassType classType = JavaPsiFacade.getElementFactory(project).createType(definition); - getVariantsFromQualifierType(classType, project); - } - else { - getVariantsFromQualifierType(((GrTraitType)qualifierType).getExprType(), project); - for (PsiClassType traitType : ((GrTraitType)qualifierType).getTraitTypes()) { - getVariantsFromQualifierType(traitType, project); - } - } - } else { getVariantsFromQualifierType(qualifierType, project); if (qualifier instanceof GrReferenceExpression && !PsiUtil.isSuperReference(qualifier) && !PsiUtil.isInstanceThisRef(qualifier)) { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/documentation/GroovyDocumentationProvider.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/documentation/GroovyDocumentationProvider.java index c3476c287db5..1e0e21335cbb 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/documentation/GroovyDocumentationProvider.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/documentation/GroovyDocumentationProvider.java @@ -263,11 +263,9 @@ public class GroovyDocumentationProvider implements CodeDocumentationProvider, E } private static void generateTraitType(@NotNull StringBuilder buffer, @NotNull GrTraitType type, PsiElement context) { - PsiClassType exprType = type.getExprType(); - List traitTypes = type.getTraitTypes(); - appendTypeString(buffer, exprType, context); + appendTypeString(buffer, type.getExprType(), context); buffer.append(" as "); - for (PsiClassType traitType : traitTypes) { + for (PsiType traitType : type.getTraitTypes()) { appendTypeString(buffer, traitType, context); buffer.append(", "); } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/LightGroovyTestCase.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/LightGroovyTestCase.groovy index e26d327a2e06..2a5f12742fb8 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/LightGroovyTestCase.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/LightGroovyTestCase.groovy @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * 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. @@ -19,6 +19,7 @@ package org.jetbrains.plugins.groovy import com.intellij.psi.PsiIntersectionType import com.intellij.psi.PsiType import com.intellij.testFramework.LightProjectDescriptor +import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase import org.jetbrains.annotations.NonNls import org.jetbrains.annotations.NotNull @@ -29,6 +30,10 @@ import org.jetbrains.annotations.Nullable */ public abstract class LightGroovyTestCase extends LightCodeInsightFixtureTestCase { + JavaCodeInsightTestFixture getFixture() { + myFixture + } + @Override @NotNull protected LightProjectDescriptor getProjectDescriptor() { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/GroovyTraitCoercionTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/GroovyTraitCoercionTest.groovy new file mode 100644 index 000000000000..ba0fc238162c --- /dev/null +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/GroovyTraitCoercionTest.groovy @@ -0,0 +1,168 @@ +/* + * 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.plugins.groovy.lang.resolve + +import com.intellij.codeInsight.completion.CompletionType +import com.intellij.psi.PsiElement +import com.intellij.psi.util.PsiTreeUtil +import com.intellij.testFramework.LightProjectDescriptor +import org.jetbrains.plugins.groovy.GroovyFileType +import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod + +class GroovyTraitCoercionTest extends GroovyResolveTestCase { + + String basePath = null + LightProjectDescriptor projectDescriptor = GroovyLightProjectDescriptor.GROOVY_2_3_9 + + @Override + void setUp() { + super.setUp() + 'add necessary classes'() + } + + public void 'add necessary classes'() { + fixture.addFileToProject 'classes.groovy', '''\ +trait T1 { + String foo() {} + def bar() {} +} + +trait T2 { + Integer foo() {} +} + +interface I { + def someMethod() +} + +class Foo implements I { + Foo foo() {} + def someMethod() {} + def fooMethod() {} +} +''' + } + + void 'test types: `as` and chained `as`'() { + testExpressionTypes([ + 'new Foo() as T1' : 'Foo as T1', + 'new Foo() as T2' : 'Foo as T2', + '(new Foo() as T1) as T2': 'Foo as T1, T2', + '(new Foo() as T2) as T1': 'Foo as T2, T1', + ]) + } + + void 'test types: `withTraits()` and chained `withTraits()`'() { + testExpressionTypes([ + 'new Foo().withTraits(T1)' : 'Foo as T1', + 'new Foo().withTraits(T2)' : 'Foo as T2', + 'new Foo().withTraits(T1).withTraits(T2)': 'Foo as T1, T2', + 'new Foo().withTraits(T2).withTraits(T1)': 'Foo as T2, T1', + ]) + } + + void 'test types: remove duplicates'() { + testExpressionTypes([ + '(new Foo() as T1) as T1' : 'Foo as T1', + '(new Foo() as T1).withTraits(T1)' : 'Foo as T1', + 'new Foo().withTraits(T2) as T2' : 'Foo as T2', + 'new Foo().withTraits(T2).withTraits(T2)': 'Foo as T2', + ]) + } + + void 'test types: mixed `as` and `withTraits()`'() { + testExpressionTypes([ + '(new Foo() as T1).withTraits(T2)': 'Foo as T1, T2', + '(new Foo() as T2).withTraits(T1)': 'Foo as T2, T1', + 'new Foo().withTraits(T1) as T2' : 'Foo as T1, T2', + 'new Foo().withTraits(T2) as T1' : 'Foo as T2, T1', + ]) + } + + void 'test types: with two traits'() { + testExpressionTypes( + 'new Foo().withTraits(T1, T2)': 'Foo as T1, T2' + ) + } + + void 'test types: traits duplicates and order'() { + testExpressionTypes( + '(new Foo() as T1).withTraits(T2, T1)': 'Foo as T2, T1' + ) + } + + void 'test `as` operator'() { + testResolveContainingClass([ + '(new Foo() as T1).foo()' : 'T1', + '(new Foo() as T1).bar()' : 'T1', + '(new Foo() as T1).someMethod()' : 'Foo', + '(new Foo() as T1).fooMethod()' : 'Foo', + '((new Foo() as T1) as T2).foo()': 'T2', + '((new Foo() as T1) as T2).bar()': 'T1', + ]) + } + + void 'test `withTraits()`'() { + testResolveContainingClass([ + 'new Foo().withTraits(T1).foo()' : 'T1', + 'new Foo().withTraits(T1).bar()' : 'T1', + 'new Foo().withTraits(T1).withTraits(T2).foo()': 'T2', + 'new Foo().withTraits(T2).withTraits(T1).foo()': 'T1', + ]) + } + + void 'test duplicates and order'() { + testResolveContainingClass([ + '(new Foo() as T1).withTraits(T2, T1).foo()': 'T1' + ]) + } + + void 'test completion proirity'() { + fixture.configureByText GroovyFileType.GROOVY_FILE_TYPE, '''\ +(new Foo().withTraits(T1, T2).f) +''' + def method = fixture.findClass('T2').findMethodsByName('foo', false)[0] + def lookupElements = fixture.complete(CompletionType.BASIC) + assert lookupElements.find { it.psiElement == method } + } + + def T configureByExpression(String text, Class expressionType = GrExpression) { + assert text + fixture.configureByText GroovyFileType.GROOVY_FILE_TYPE, text + PsiTreeUtil.findFirstParent(fixture.file.findElementAt(0), { PsiElement element -> + element in expressionType && element.text == text + }).asType(expressionType) + } + + def testExpressionType(String expressionString, String typeString) { + configureByExpression(expressionString).with { GrExpression expression -> + assert expression.type: expression.getText() + assert expression.type.internalCanonicalText == typeString: "$expression.text: $expression.type.internalCanonicalText == $typeString" + } + } + + def testExpressionTypes(Map data) { + data.each this.&testExpressionType + } + + def testResolveContainingClass(Map data) { + data.each { k, v -> + assert resolveByText(k, GrMethod).containingClass == fixture.findClass(v) + } + } +} diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolvePropertyTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolvePropertyTest.groovy index 4ab258e57d86..6ad716aead4a 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolvePropertyTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolvePropertyTest.groovy @@ -30,7 +30,6 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEn import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrGdkMethod import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrBindingVariable -import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrTraitMethod import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil import org.jetbrains.plugins.groovy.util.TestUtils @@ -1476,7 +1475,7 @@ class B { def v = new B() as A print v.foo -''', GrTraitMethod) +''', GrAccessorMethod) } void testTraitPropertyFromAsOperator2() { From 7e73699edcaf234de1c713cbbd21450bbf607b73 Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Fri, 6 Nov 2015 17:47:06 +0300 Subject: [PATCH 076/124] add bulk mode operations to editor stress tests --- .../openapi/editor/impl/EditorStressTest.java | 24 ++++++++++++++++--- .../softwrap/mapping/SoftWrapStressTest.java | 4 ++++ 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/EditorStressTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/EditorStressTest.java index 5d26078803c1..a51e8153217c 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/EditorStressTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/EditorStressTest.java @@ -17,6 +17,7 @@ package com.intellij.openapi.editor.impl; import com.intellij.openapi.editor.*; import com.intellij.openapi.editor.ex.DocumentEx; +import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.editor.ex.SoftWrapModelEx; import com.intellij.util.DocumentUtil; @@ -36,7 +37,8 @@ public class EditorStressTest extends AbstractEditorTest { new AddFoldRegion(), new RemoveFoldRegion(), new CollapseFoldRegion(), - new ExpandFoldRegion()); + new ExpandFoldRegion(), + new ChangeBulkModeState()); private final Random myRandom = new Random() {{ //noinspection ConstantConditions @@ -70,7 +72,8 @@ public class EditorStressTest extends AbstractEditorTest { } private static void checkSoftWrapPositions(Editor editor) { - Document document = editor.getDocument(); + DocumentEx document = ((EditorEx)editor).getDocument(); + if (document.isInBulkUpdate()) return; FoldingModel foldingModel = editor.getFoldingModel(); List softWraps = ((SoftWrapModelEx)editor.getSoftWrapModel()).getRegisteredSoftWraps(); int lastSoftWrapOffset = -1; @@ -134,7 +137,8 @@ public class EditorStressTest extends AbstractEditorTest { private static class AddFoldRegion implements Action { @Override public void perform(final Editor editor, Random random) { - Document document = editor.getDocument(); + DocumentEx document = ((EditorEx)editor).getDocument(); + if (document.isInBulkUpdate()) return; int textLength = document.getTextLength(); if (textLength <= 0) return; final int startOffset = random.nextInt(textLength + 1); @@ -150,6 +154,8 @@ public class EditorStressTest extends AbstractEditorTest { private static class RemoveFoldRegion implements Action { @Override public void perform(final Editor editor, Random random) { + DocumentEx document = ((EditorEx)editor).getDocument(); + if (document.isInBulkUpdate()) return; final FoldingModel foldingModel = editor.getFoldingModel(); FoldRegion[] foldRegions = foldingModel.getAllFoldRegions(); if (foldRegions.length == 0) return; @@ -161,6 +167,8 @@ public class EditorStressTest extends AbstractEditorTest { private static class CollapseFoldRegion implements Action { @Override public void perform(final Editor editor, Random random) { + DocumentEx document = ((EditorEx)editor).getDocument(); + if (document.isInBulkUpdate()) return; final FoldingModel foldingModel = editor.getFoldingModel(); FoldRegion[] foldRegions = foldingModel.getAllFoldRegions(); if (foldRegions.length == 0) return; @@ -172,6 +180,8 @@ public class EditorStressTest extends AbstractEditorTest { private static class ExpandFoldRegion implements Action { @Override public void perform(final Editor editor, Random random) { + DocumentEx document = ((EditorEx)editor).getDocument(); + if (document.isInBulkUpdate()) return; final FoldingModel foldingModel = editor.getFoldingModel(); FoldRegion[] foldRegions = foldingModel.getAllFoldRegions(); if (foldRegions.length == 0) return; @@ -179,4 +189,12 @@ public class EditorStressTest extends AbstractEditorTest { foldingModel.runBatchFoldingOperation(() -> region.setExpanded(true)); } } + + private static class ChangeBulkModeState implements Action { + @Override + public void perform(Editor editor, Random random) { + DocumentEx document = ((EditorEx)editor).getDocument(); + document.setInBulkUpdate(!document.isInBulkUpdate()); + } + } } \ No newline at end of file diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapStressTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapStressTest.java index d72fcdfc69bb..692a32b3a609 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapStressTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapStressTest.java @@ -16,6 +16,8 @@ package com.intellij.openapi.editor.impl.softwrap.mapping; import com.intellij.openapi.editor.*; +import com.intellij.openapi.editor.ex.DocumentEx; +import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.editor.impl.EditorStressTest; import com.intellij.openapi.editor.impl.SoftWrapModelImpl; import com.intellij.openapi.util.registry.Registry; @@ -42,6 +44,8 @@ public class SoftWrapStressTest extends EditorStressTest { @Override protected void checkConsistency(Editor editor) { + DocumentEx document = ((EditorEx)editor).getDocument(); + if (document.isInBulkUpdate()) return; Set softWrapOffsets = checkSoftWraps(editor); List cache = ((SoftWrapModelImpl)editor.getSoftWrapModel()).getDataMapper().getCache(); CacheEntry prevEntry = null; From 153e03ae7d53baff3b61dd32b84d9e06c6150441 Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Fri, 6 Nov 2015 22:46:28 +0300 Subject: [PATCH 077/124] don't perform coordinate conversions in EditorSizeManager when soft wrap model is in inconsistent state fixes EA-75267 - AIOOBE: TIntArrayList.insert --- .../editor/impl/EditorDocumentPriorities.java | 2 +- .../openapi/editor/impl/EditorImpl.java | 4 ++ .../editor/impl/view/EditorSizeManager.java | 60 +++++++++++++++---- 3 files changed, 53 insertions(+), 13 deletions(-) diff --git a/platform/core-impl/src/com/intellij/openapi/editor/impl/EditorDocumentPriorities.java b/platform/core-impl/src/com/intellij/openapi/editor/impl/EditorDocumentPriorities.java index 157231cbbb36..677da409294c 100644 --- a/platform/core-impl/src/com/intellij/openapi/editor/impl/EditorDocumentPriorities.java +++ b/platform/core-impl/src/com/intellij/openapi/editor/impl/EditorDocumentPriorities.java @@ -35,9 +35,9 @@ public class EditorDocumentPriorities { public static final int FOLD_MODEL = 60; public static final int LOGICAL_POSITION_CACHE = 65; public static final int EDITOR_TEXT_LAYOUT_CACHE = 70; - public static final int EDITOR_TEXT_WIDTH_CACHE = 75; public static final int LEXER_EDITOR = 80; public static final int SOFT_WRAP_MODEL = 100; + public static final int EDITOR_TEXT_WIDTH_CACHE = 110; public static final int CARET_MODEL = 120; public static final int SELECTION_MODEL = 140; public static final int EDITOR_DOCUMENT_ADAPTER = 160; diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java index 7b5f21a3ddf8..556dd39d4481 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java @@ -1832,6 +1832,10 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi } private void bulkUpdateStarted() { + if (myUseNewRendering) { + myView.getPreferredSize(); // make sure size is calculated (in case it will be required while bulk mode is active) + } + saveCaretRelativePosition(); myCaretModel.onBulkDocumentUpdateStarted(); diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/EditorSizeManager.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/EditorSizeManager.java index b9ce1d8684f9..e41b3efc46a3 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/EditorSizeManager.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/view/EditorSizeManager.java @@ -58,6 +58,11 @@ class EditorSizeManager implements PrioritizedDocumentListener, Disposable, Fold private int myMaxLineWithExtensionWidth; private int myWidestLineWithExtension; + private int myDocumentChangeStartOffset; + private int myDocumentChangeEndOffset; + private int myFoldingChangeStartOffset = Integer.MAX_VALUE; + private int myFoldingChangeEndOffset = Integer.MIN_VALUE; + private final List myDeferredRanges = new ArrayList(); private final SoftWrapAwareDocumentParsingListenerAdapter mySoftWrapChangeListener = new SoftWrapAwareDocumentParsingListenerAdapter() { @@ -88,31 +93,34 @@ class EditorSizeManager implements PrioritizedDocumentListener, Disposable, Fold @Override public void beforeDocumentChange(DocumentEvent event) { + if (myDocument.isInBulkUpdate()) return; + myDocumentChangeStartOffset = event.getOffset(); + myDocumentChangeEndOffset = event.getOffset() + event.getNewLength(); } @Override public void documentChanged(DocumentEvent event) { - invalidateRange(event.getOffset(), event.getOffset() + event.getNewLength()); + if (myDocument.isInBulkUpdate()) return; + doInvalidateRange(myDocumentChangeStartOffset, myDocumentChangeEndOffset); } - private int foldingChangeStartOffset = Integer.MAX_VALUE; - private int foldingChangeEndOffset = Integer.MIN_VALUE; - @Override public void onFoldRegionStateChange(@NotNull FoldRegion region) { + if (myDocument.isInBulkUpdate()) return; if (region.isValid()) { - foldingChangeStartOffset = Math.min(foldingChangeStartOffset, region.getStartOffset()); - foldingChangeEndOffset = Math.max(foldingChangeEndOffset, region.getEndOffset()); + myFoldingChangeStartOffset = Math.min(myFoldingChangeStartOffset, region.getStartOffset()); + myFoldingChangeEndOffset = Math.max(myFoldingChangeEndOffset, region.getEndOffset()); } } @Override public void onFoldProcessingEnd() { - if (foldingChangeStartOffset <= foldingChangeEndOffset) { - invalidateRange(foldingChangeStartOffset, foldingChangeEndOffset); + if (myDocument.isInBulkUpdate()) return; + if (myFoldingChangeStartOffset <= myFoldingChangeEndOffset) { + doInvalidateRange(myFoldingChangeStartOffset, myFoldingChangeEndOffset); } - foldingChangeStartOffset = Integer.MAX_VALUE; - foldingChangeEndOffset = Integer.MIN_VALUE; + myFoldingChangeStartOffset = Integer.MAX_VALUE; + myFoldingChangeEndOffset = Integer.MIN_VALUE; for (TextRange range : myDeferredRanges) { onTextLayoutPerformed(range.getStartOffset(), range.getEndOffset()); @@ -121,7 +129,21 @@ class EditorSizeManager implements PrioritizedDocumentListener, Disposable, Fold } private void onSoftWrapRecalculationEnd(IncrementalCacheUpdateEvent event) { - invalidateRange(event.getStartOffset(), event.getActualEndOffset()); + if (myDocument.isInBulkUpdate()) return; + boolean invalidate = true; + if (myEditor.getFoldingModel().isInBatchFoldingOperation()) { + myFoldingChangeStartOffset = Math.min(myFoldingChangeStartOffset, event.getStartOffset()); + myFoldingChangeEndOffset = Math.max(myFoldingChangeEndOffset, event.getActualEndOffset()); + invalidate = false; + } + if (myDocument.isInEventsHandling()) { + myDocumentChangeStartOffset = Math.min(myDocumentChangeStartOffset, event.getStartOffset()); + myDocumentChangeEndOffset = Math.max(myDocumentChangeEndOffset, event.getActualEndOffset()); + invalidate = false; + } + if (invalidate) { + doInvalidateRange(event.getStartOffset(), event.getActualEndOffset()); + } } Dimension getPreferredSize() { @@ -149,6 +171,7 @@ class EditorSizeManager implements PrioritizedDocumentListener, Disposable, Fold private int getPreferredWidth() { if (myWidthInPixels < 0) { + assert !myDocument.isInBulkUpdate(); myWidthInPixels = calculatePreferredWidth(); } validateMaxLineWithExtension(); @@ -193,10 +216,22 @@ class EditorSizeManager implements PrioritizedDocumentListener, Disposable, Fold } void reset() { - invalidateRange(0, myDocument.getTextLength()); + assert !myDocument.isInBulkUpdate(); + doInvalidateRange(0, myDocument.getTextLength()); } void invalidateRange(int startOffset, int endOffset) { + if (myDocument.isInBulkUpdate()) return; + if (myDocument.isInEventsHandling()) { + myDocumentChangeStartOffset = Math.min(myDocumentChangeStartOffset, startOffset); + myDocumentChangeEndOffset = Math.max(myDocumentChangeEndOffset, endOffset); + } + else { + doInvalidateRange(startOffset, endOffset); + } + } + + private void doInvalidateRange(int startOffset, int endOffset) { myWidthInPixels = -1; int startVisualLine = myView.offsetToVisualLine(startOffset, false); int endVisualLine = myView.offsetToVisualLine(endOffset, true); @@ -223,6 +258,7 @@ class EditorSizeManager implements PrioritizedDocumentListener, Disposable, Fold } void textLayoutPerformed(int startOffset, int endOffset) { + if (myDocument.isInBulkUpdate()) return; if (myEditor.getFoldingModel().isInBatchFoldingOperation()) { myDeferredRanges.add(new TextRange(startOffset, endOffset)); } From 4449b8e0d246e5b9713de809ba4e5af8d788c4d2 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Fri, 6 Nov 2015 15:01:04 +0100 Subject: [PATCH 078/124] SSR: remove unused method --- .../intellij/structuralsearch/impl/matcher/MatcherImpl.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/MatcherImpl.java b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/MatcherImpl.java index b0ea748c8477..48eb7c471ae7 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/MatcherImpl.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/MatcherImpl.java @@ -219,10 +219,6 @@ public class MatcherImpl { } } - Project getProject() { - return project; - } - /** * Finds the matches of given pattern starting from given tree element. * @throws MalformedPatternException From 7312c982757ccfb6238c073a058145b3ca58e116 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Fri, 6 Nov 2015 15:10:48 +0100 Subject: [PATCH 079/124] SSR: test that the type of variables in script are as expected --- .../JavaStructuralSearchProfile.java | 8 ++--- .../impl/matcher/JavaMatchingVisitor.java | 13 ++------ .../matcher/predicates/ScriptSupport.java | 2 +- .../StructuralSearchTest.java | 30 +++++++++++++++++++ 4 files changed, 38 insertions(+), 15 deletions(-) diff --git a/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaStructuralSearchProfile.java b/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaStructuralSearchProfile.java index d79eb59219c5..d50c08ba3fed 100644 --- a/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaStructuralSearchProfile.java +++ b/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaStructuralSearchProfile.java @@ -721,10 +721,10 @@ public class JavaStructuralSearchProfile extends StructuralSearchProfile { } } - private static void appendParameter(final StringBuilder buf, final MatchResult _matchResult) { - for(Iterator j = _matchResult.getAllSons().iterator();j.hasNext();) { - buf.append(j.next().getMatchImage()).append(' ').append(j.next().getMatchImage()); - } + private static void appendParameter(final StringBuilder buf, final MatchResult matchResult) { + final List sons = matchResult.getAllSons(); + assert sons.size() == 1; + buf.append(sons.get(0).getMatchImage()).append(' ').append(matchResult.getMatchImage()); } private static void removeExtraSemicolonForSingleVarInstanceInMultipleMatch(final ParameterInfo info, MatchResult r, StringBuilder buf) { diff --git a/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/JavaMatchingVisitor.java b/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/JavaMatchingVisitor.java index 26f77d163a51..d545e0f25f7a 100644 --- a/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/JavaMatchingVisitor.java +++ b/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/JavaMatchingVisitor.java @@ -941,13 +941,12 @@ public class JavaMatchingVisitor extends JavaElementVisitor { myMatchingVisitor.getMatchContext().pushResult(); final PsiIdentifier nameIdentifier = var.getNameIdentifier(); - boolean isTypedVar = myMatchingVisitor.getMatchContext().getPattern().isTypedVar(nameIdentifier); + final boolean isTypedVar = myMatchingVisitor.getMatchContext().getPattern().isTypedVar(nameIdentifier); final PsiVariable var2 = (PsiVariable)myMatchingVisitor.getElement(); try { myMatchingVisitor.setResult((myMatchingVisitor.matchText(var.getNameIdentifier(), var2.getNameIdentifier()) || isTypedVar) && - ((var.getParent() instanceof PsiClass && ((PsiClass)var.getParent()).isInterface()) || - myMatchingVisitor.match(var.getModifierList(), var2.getModifierList()))); + myMatchingVisitor.match(var.getModifierList(), var2.getModifierList())); if (myMatchingVisitor.getResult()) { final PsiTypeElement typeElement1 = var.getTypeElement(); if (typeElement1 != null) { @@ -972,10 +971,6 @@ public class JavaMatchingVisitor extends JavaElementVisitor { ((PsiCatchSection)var2.getParent()).getCatchBlock() )); } - - if (myMatchingVisitor.getResult() && isTypedVar) { - myMatchingVisitor.setResult(myMatchingVisitor.handleTypedElement(nameIdentifier, var2.getNameIdentifier())); - } } finally { saveOrDropResult(nameIdentifier, isTypedVar, var2.getNameIdentifier()); @@ -1692,9 +1687,7 @@ public class JavaMatchingVisitor extends JavaElementVisitor { myMatchingVisitor.matchSonsOptionally(method.getBody(), method2.getBody())); } finally { - final PsiIdentifier methodNameNode2 = method2.getNameIdentifier(); - - saveOrDropResult(methodNameNode, isTypedVar, methodNameNode2); + saveOrDropResult(methodNameNode, isTypedVar, method2.getNameIdentifier()); } } } diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/predicates/ScriptSupport.java b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/predicates/ScriptSupport.java index 60190275a902..cc6f97a295ed 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/predicates/ScriptSupport.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/predicates/ScriptSupport.java @@ -46,7 +46,7 @@ public class ScriptSupport { private static Map buildVariableMap(@NotNull MatchResult result, @NotNull Map out) { final String name = result.getName(); - if (name != null && !result.isMultipleMatch() && !result.isScopeMatch()) { + if (name != null && !result.isMultipleMatch()) { final Object value = out.get(name); final PsiElement match = StructuralSearchUtil.getPresentableElement(result.getMatch()); if (value == null) { diff --git a/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java b/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java index 2aa293f3bba6..afba06233973 100644 --- a/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java +++ b/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java @@ -1174,6 +1174,36 @@ public class StructuralSearchTest extends StructuralSearchTestCase { " Type.type.canonicalText\n" + // reference to '_Type ")\n\")]" + "static final '_Type 'variable = '_init;")); + + final String source2 = "class A {" + + " String s = new String();" + + " int m() {" + + " int i = 2+1;" + + " return i;" + + " }" + + "}"; + assertEquals("type of variables in script are as expected", 1, + findMatchesCount(source2, + "[script(\"" + + "import com.intellij.psi.*\n" + + "a instanceof PsiClass &&" + + "b instanceof PsiTypeElement &&" + + "c instanceof PsiField &&" + + "d instanceof PsiNewExpression &&" + + "e instanceof PsiTypeElement &&" + + "f instanceof PsiMethod &&" + + "g instanceof PsiTypeElement &&" + + "h instanceof PsiLocalVariable &&" + + "i instanceof PsiPolyadicExpression &&" + + "j instanceof PsiReferenceExpression" + + "\n\")]" + + "class '_a {" + + " '_b '_c = '_d;" + + " '_e '_f() {" + + " '_g '_h = '_i" + + " return '_j;" + + " }" + + "}")); } public void testCheckScriptValidation() { From c2ef9b756d797c292edd3c46c7af707486a3240b Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Fri, 6 Nov 2015 17:08:52 +0100 Subject: [PATCH 080/124] SSR: cleanup MatchResultImpl & related --- .../JavaStructuralSearchProfile.java | 2 +- .../structuralsearch/MatchResult.java | 5 ++-- .../StructuralSearchProfile.java | 2 +- .../impl/matcher/GlobalMatchingVisitor.java | 14 ++++------- .../impl/matcher/MatchResultImpl.java | 24 ++++++++++++------- .../matcher/handlers/SubstitutionHandler.java | 4 +--- 6 files changed, 25 insertions(+), 26 deletions(-) diff --git a/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaStructuralSearchProfile.java b/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaStructuralSearchProfile.java index d50c08ba3fed..cbbe61dc9e68 100644 --- a/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaStructuralSearchProfile.java +++ b/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaStructuralSearchProfile.java @@ -531,7 +531,7 @@ public class JavaStructuralSearchProfile extends StructuralSearchProfile { handleMethodParameter(buf, info, matchMap); replacementString = buf.toString(); } - else if (match.getAllSons().size() > 0 && !match.isScopeMatch()) { + else if (match.hasSons() && !match.isScopeMatch()) { // compound matches StringBuilder buf = new StringBuilder(); MatchResult r = null; diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/MatchResult.java b/platform/structuralsearch/source/com/intellij/structuralsearch/MatchResult.java index c5196e67178d..75ee67a63bfe 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/MatchResult.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/MatchResult.java @@ -10,8 +10,8 @@ import java.util.List; * Class describing the match result */ public abstract class MatchResult { - @NonNls public static final String LINE_MATCH = "line"; - @NonNls public static final String MULTI_LINE_MATCH = "context"; + @NonNls public static final String LINE_MATCH = "__line__"; + @NonNls public static final String MULTI_LINE_MATCH = "__multi_line__"; public abstract String getMatchImage(); @@ -26,4 +26,5 @@ public abstract class MatchResult { public abstract boolean hasSons(); public abstract boolean isScopeMatch(); public abstract boolean isMultipleMatch(); + public abstract boolean isTarget(); } diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/StructuralSearchProfile.java b/platform/structuralsearch/source/com/intellij/structuralsearch/StructuralSearchProfile.java index ea25cdefb89a..41a1c264832f 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/StructuralSearchProfile.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/StructuralSearchProfile.java @@ -221,7 +221,7 @@ public abstract class StructuralSearchProfile { if (info.getName().equals(match.getName())) { String replacementString = match.getMatchImage(); boolean forceAddingNewLine = false; - if (match.getAllSons().size() > 0 && !match.isScopeMatch()) { + if (match.hasSons() && !match.isScopeMatch()) { // compound matches StringBuilder buf = new StringBuilder(); diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/GlobalMatchingVisitor.java b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/GlobalMatchingVisitor.java index 50e64b6457b9..8d5309ad46b5 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/GlobalMatchingVisitor.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/GlobalMatchingVisitor.java @@ -246,17 +246,15 @@ public class GlobalMatchingVisitor extends AbstractMatchingVisitor { matchContext.getSink().newMatch(result); } - private boolean doDispatch(final MatchResultImpl result, MatchResultImpl context) { + private boolean doDispatch(final MatchResult result, MatchResultImpl context) { boolean ret = false; - for (MatchResult _r : result.getAllSons()) { - final MatchResultImpl r = (MatchResultImpl)_r; - + for (MatchResult r : result.getAllSons()) { if ((r.isScopeMatch() && !r.isTarget()) || r.isMultipleMatch()) { ret |= doDispatch(r, context); } else if (r.isTarget()) { - r.setContext(context); + ((MatchResultImpl)r).setContext(context); matchContext.getSink().newMatch(r); ret = true; } @@ -273,19 +271,15 @@ public class GlobalMatchingVisitor extends AbstractMatchingVisitor { result.setMatchImage(match.getText()); } else { - MatchResultImpl sonresult; for (final PsiElement matchStatement : matchedNodes) { - result.getMatches().add( - sonresult = new MatchResultImpl( + result.getMatches().add(new MatchResultImpl( MatchResult.LINE_MATCH, matchStatement.getText(), new SmartPsiPointer(matchStatement), true ) ); - - sonresult.setParent(result); } result.setMatchRef( diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/MatchResultImpl.java b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/MatchResultImpl.java index 6278a6023382..58748a35b970 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/MatchResultImpl.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/MatchResultImpl.java @@ -3,7 +3,6 @@ package com.intellij.structuralsearch.impl.matcher; import com.intellij.psi.PsiElement; import com.intellij.structuralsearch.MatchResult; import com.intellij.structuralsearch.plugin.util.SmartPsiPointer; -import org.jetbrains.annotations.NonNls; import java.util.ArrayList; import java.util.Iterator; @@ -23,7 +22,6 @@ public final class MatchResultImpl extends MatchResult { private boolean myScopeMatch; private boolean myMultipleMatch; - @NonNls private static final String NULL = "null"; private MatchResultImpl myContext; MatchResultImpl() { @@ -42,21 +40,21 @@ public final class MatchResultImpl extends MatchResult { this.end = end; } + @Override public String getMatchImage() { - if (matchImage==null) { - matchImage = NULL; - } return matchImage; } - public void setParent(MatchResult parent) { - } - + @Override public SmartPsiPointer getMatchRef() { return matchRef; } + @Override public PsiElement getMatch() { + if (matchRef == null) { + return null; + } return matchRef.getElement(); } @@ -64,6 +62,7 @@ public final class MatchResultImpl extends MatchResult { matchRef = matchStart; } + @Override public String getName() { return name; } @@ -77,18 +76,22 @@ public final class MatchResultImpl extends MatchResult { return matches; } + @Override public List getAllSons() { return getMatches(); } + @Override public boolean hasSons() { - return matches!=null; + return matches!=null && matches.size() > 0; } + @Override public boolean isScopeMatch() { return myScopeMatch; } + @Override public boolean isMultipleMatch() { return myMultipleMatch; } @@ -159,6 +162,7 @@ public final class MatchResultImpl extends MatchResult { this.matchImage = matchImage; } + @Override public boolean isTarget() { return target; } @@ -171,6 +175,7 @@ public final class MatchResultImpl extends MatchResult { return matchImage==null; } + @Override public int getStart() { return start; } @@ -179,6 +184,7 @@ public final class MatchResultImpl extends MatchResult { this.start = start; } + @Override public int getEnd() { return end; } diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/handlers/SubstitutionHandler.java b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/handlers/SubstitutionHandler.java index 2fb20927d329..4be40683bf02 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/handlers/SubstitutionHandler.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/handlers/SubstitutionHandler.java @@ -167,7 +167,7 @@ public class SubstitutionHandler extends MatchingHandler { if (!substitution.isMultipleMatch()) { // adding intermediate node to contain all multiple matches - MatchResultImpl sonresult = new MatchResultImpl( + final MatchResultImpl sonresult = new MatchResultImpl( substitution.getName(), substitution.getMatchImage(), substitution.getMatchRef(), @@ -176,7 +176,6 @@ public class SubstitutionHandler extends MatchingHandler { target ); - sonresult.setParent(substitution); substitution.setMatchRef( new SmartPsiPointer(match == null ? null : match) ); @@ -193,7 +192,6 @@ public class SubstitutionHandler extends MatchingHandler { substitution.addSon( sonresult); } - result.setParent(substitution); substitution.addSon( result ); } } From ec56e22ca0cc56af33f9d50a9ca512e219a17025 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Fri, 6 Nov 2015 17:41:11 +0100 Subject: [PATCH 081/124] SSR: small simplification --- .../structuralsearch/JavaStructuralSearchProfile.java | 4 ++-- .../structuralsearch/DocumentBasedReplaceHandler.java | 2 +- .../impl/matcher/handlers/SubstitutionHandler.java | 4 ++-- .../plugin/replace/impl/ReplacementContext.java | 2 +- .../structuralsearch/plugin/replace/impl/Replacer.java | 4 ++-- .../intellij/structuralsearch/plugin/ui/SearchCommand.java | 4 ++-- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaStructuralSearchProfile.java b/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaStructuralSearchProfile.java index cbbe61dc9e68..2e63ea33adec 100644 --- a/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaStructuralSearchProfile.java +++ b/java/structuralsearch-java/src/com/intellij/structuralsearch/JavaStructuralSearchProfile.java @@ -551,7 +551,7 @@ public class JavaStructuralSearchProfile extends StructuralSearchProfile { } } else if (info.isStatementContext()) { - final PsiElement previousElement = previous.getMatchRef().getElement(); + final PsiElement previousElement = previous.getMatch(); if (!(previousElement instanceof PsiComment) && ( buf.charAt(buf.length() - 1) != '}' || @@ -729,7 +729,7 @@ public class JavaStructuralSearchProfile extends StructuralSearchProfile { private static void removeExtraSemicolonForSingleVarInstanceInMultipleMatch(final ParameterInfo info, MatchResult r, StringBuilder buf) { if (info.isStatementContext()) { - final PsiElement element = r.getMatchRef().getElement(); + final PsiElement element = r.getMatch(); // remove extra ; if (buf.charAt(buf.length()-1)==';' && diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/DocumentBasedReplaceHandler.java b/platform/structuralsearch/source/com/intellij/structuralsearch/DocumentBasedReplaceHandler.java index 1f319b8f15e5..ec0847d6c4f9 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/DocumentBasedReplaceHandler.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/DocumentBasedReplaceHandler.java @@ -45,7 +45,7 @@ public class DocumentBasedReplaceHandler extends StructuralReplaceHandler { PsiElement element = result.getMatch(); PsiFile file = element instanceof PsiFile ? (PsiFile)element : element.getContainingFile(); Document document = PsiDocumentManager.getInstance(myProject).getDocument(file); - TextRange textRange = result.getMatchRef().getElement().getTextRange(); + TextRange textRange = result.getMatch().getTextRange(); assert textRange != null; RangeMarker rangeMarker = document.createRangeMarker(textRange); rangeMarker.setGreedyToLeft(true); diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/handlers/SubstitutionHandler.java b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/handlers/SubstitutionHandler.java index 4be40683bf02..1936818628df 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/handlers/SubstitutionHandler.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/handlers/SubstitutionHandler.java @@ -96,7 +96,7 @@ public class SubstitutionHandler extends MatchingHandler { if (match!=null) { if (start==0 && end==-1 && result.getStart()==0 && result.getEnd()==-1) { - matchresult = matchContext.getMatcher().match(match,result.getMatchRef().getElement()); + matchresult = matchContext.getMatcher().match(match,result.getMatch()); } else { matchresult = StructuralSearchUtil.getProfileByPsiElement(match).getText(match, start, end).equals( result.getMatchImage() @@ -245,7 +245,7 @@ public class SubstitutionHandler extends MatchingHandler { if (minOccurs >= 1 && ( substitution == null || - StructuralSearchUtil.getProfileByFileType(context.getOptions().getFileType()).getElementContextByPsi(substitution.getMatchRef().getElement()) != elementContext + StructuralSearchUtil.getProfileByFileType(context.getOptions().getFileType()).getElementContextByPsi(substitution.getMatch()) != elementContext ) ) { return false; diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/replace/impl/ReplacementContext.java b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/replace/impl/ReplacementContext.java index 07566796cf06..0bb427036f55 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/replace/impl/ReplacementContext.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/replace/impl/ReplacementContext.java @@ -42,7 +42,7 @@ public class ReplacementContext { if (variableMap != null) { for (String s : variableMap.keySet()) { final MatchResult matchResult = replacementInfo.getVariableMap().get(s); - PsiElement match = matchResult.getMatchRef() != null ? matchResult.getMatch() : null; + PsiElement match = matchResult.getMatch(); match = StructuralSearchUtil.getParentIfIdentifier(match); if (match instanceof PsiNamedElement) { diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/replace/impl/Replacer.java b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/replace/impl/Replacer.java index 6ca23da13e7b..c0db4e7a24f7 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/replace/impl/Replacer.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/replace/impl/Replacer.java @@ -390,7 +390,7 @@ public class Replacer { final MatchResult r = i.next(); if (MatchResult.LINE_MATCH.equals(r.getName())) { - PsiElement element = r.getMatchRef().getElement(); + PsiElement element = r.getMatch(); if (element instanceof PsiDocCommentBase) { // doc comment is not collapsed when created in block if (i.hasNext()) { @@ -409,7 +409,7 @@ public class Replacer { } } } else { - l.add( manager.createSmartPsiElementPointer(result.getMatchRef().getElement())); + l.add(manager.createSmartPsiElementPointer(result.getMatch())); } ReplacementInfoImpl replacementInfo = new ReplacementInfoImpl(); diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/SearchCommand.java b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/SearchCommand.java index ac3c39e4b9a2..71118f1e4030 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/SearchCommand.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/ui/SearchCommand.java @@ -144,10 +144,10 @@ public class SearchCommand { if (MatchResult.MULTI_LINE_MATCH.equals(result.getName())) { int start = -1; int end = -1; - PsiElement parent = result.getMatchRef().getElement().getParent(); + PsiElement parent = result.getMatch().getParent(); for (final MatchResult matchResult : ((MatchResultImpl)result).getMatches()) { - PsiElement el = matchResult.getMatchRef().getElement(); + PsiElement el = matchResult.getMatch(); final int elementStart = el.getTextRange().getStartOffset(); if (start == -1 || start > elementStart) { From d7f9b94114b1035a74c2735d2833737d41f49656 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Fri, 6 Nov 2015 20:52:01 +0100 Subject: [PATCH 082/124] SSR: script log first pass --- .../matcher/compiler/PatternCompiler.java | 8 +-- .../impl/matcher/predicates/ScriptLog.java | 60 +++++++++++++++++++ .../matcher/predicates/ScriptPredicate.java | 6 +- .../matcher/predicates/ScriptSupport.java | 11 +++- .../replace/impl/ReplacementBuilder.java | 4 +- 5 files changed, 79 insertions(+), 10 deletions(-) create mode 100644 platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/predicates/ScriptLog.java diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/PatternCompiler.java b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/PatternCompiler.java index 78744bad6390..afe40f03792c 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/PatternCompiler.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/PatternCompiler.java @@ -437,7 +437,7 @@ public class PatternCompiler { addPredicate(handler, matchPredicate); } - addScriptConstraint(name, constraint, handler); + addScriptConstraint(project, name, constraint, handler); if (!StringUtil.isEmptyOrSpaces(constraint.getContainsConstraint())) { predicate = new ContainsPredicate(name, constraint.getContainsConstraint()); @@ -474,7 +474,7 @@ public class PatternCompiler { addPredicate(handler,predicate); } - addScriptConstraint(Configuration.CONTEXT_VAR_NAME, constraint, handler); + addScriptConstraint(project, Configuration.CONTEXT_VAR_NAME, constraint, handler); } buf.append(text.substring(prevOffset,text.length())); @@ -505,12 +505,12 @@ public class PatternCompiler { return elements; } - private static void addScriptConstraint(String name, MatchVariableConstraint constraint, SubstitutionHandler handler) { + private static void addScriptConstraint(Project project, String name, MatchVariableConstraint constraint, SubstitutionHandler handler) { if (constraint.getScriptCodeConstraint()!= null && constraint.getScriptCodeConstraint().length() > 2) { final String script = StringUtil.stripQuotesAroundValue(constraint.getScriptCodeConstraint()); final String s = ScriptSupport.checkValidScript(script); if (s != null) throw new MalformedPatternException("Script constraint for " + constraint.getName() + " has problem "+s); - MatchPredicate predicate = new ScriptPredicate(name, script); + MatchPredicate predicate = new ScriptPredicate(project, name, script); addPredicate(handler,predicate); } } diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/predicates/ScriptLog.java b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/predicates/ScriptLog.java new file mode 100644 index 000000000000..340b5bb45dc4 --- /dev/null +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/predicates/ScriptLog.java @@ -0,0 +1,60 @@ +/* + * 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 com.intellij.structuralsearch.impl.matcher.predicates; + +import com.intellij.notification.NotificationGroup; +import com.intellij.notification.NotificationType; +import com.intellij.openapi.project.Project; +import com.intellij.structuralsearch.SSRBundle; + +/** + * @author Bas Leijdekkers + */ +public class ScriptLog { + + private final NotificationGroup myEventLog; + private final Project myProject; + + public ScriptLog(Project project) { + myProject = project; + myEventLog = NotificationGroup.logOnlyGroup(SSRBundle.message("structural.search.title")); + } + + public void info(Object message) { + log(message, NotificationType.INFORMATION); + } + + public void warn(Object message) { + log(message, NotificationType.WARNING); + } + + public void error(Object message) { + log(message, NotificationType.ERROR); + } + + private void log(Object message, NotificationType type) { + final StackTraceElement[] stackTrace = new Throwable().getStackTrace(); + String location = ""; + for (StackTraceElement e : stackTrace) { + final String methodName = e.getMethodName(); + if ("run".equals(methodName)) { + location = "(" + e.getFileName() + ":" + e.getLineNumber() + ") "; + break; + } + } + myEventLog.createNotification(location + String.valueOf(message), type).notify(myProject); + } +} diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/predicates/ScriptPredicate.java b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/predicates/ScriptPredicate.java index 9310eb9e70a0..c4c09167b99a 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/predicates/ScriptPredicate.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/predicates/ScriptPredicate.java @@ -1,5 +1,6 @@ package com.intellij.structuralsearch.impl.matcher.predicates; +import com.intellij.openapi.project.Project; import com.intellij.psi.PsiElement; import com.intellij.structuralsearch.impl.matcher.MatchContext; @@ -9,11 +10,12 @@ import com.intellij.structuralsearch.impl.matcher.MatchContext; public class ScriptPredicate extends AbstractStringBasedPredicate { private final ScriptSupport scriptSupport; - public ScriptPredicate(String name, String within) { + public ScriptPredicate(Project project, String name, String within) { super(name, within); - scriptSupport = new ScriptSupport(within, name); + scriptSupport = new ScriptSupport(project, within, name); } + @Override public boolean match(PsiElement node, PsiElement match, int start, int end, MatchContext context) { if (match == null) return false; diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/predicates/ScriptSupport.java b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/predicates/ScriptSupport.java index cc6f97a295ed..f161dabd08d5 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/predicates/ScriptSupport.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/predicates/ScriptSupport.java @@ -1,11 +1,13 @@ package com.intellij.structuralsearch.impl.matcher.predicates; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.Project; import com.intellij.psi.PsiElement; import com.intellij.structuralsearch.MatchResult; import com.intellij.structuralsearch.SSRBundle; import com.intellij.structuralsearch.StructuralSearchException; import com.intellij.structuralsearch.StructuralSearchUtil; +import com.intellij.structuralsearch.plugin.ui.Configuration; import groovy.lang.Binding; import groovy.lang.GroovyRuntimeException; import groovy.lang.GroovyShell; @@ -32,12 +34,14 @@ import java.util.Map; */ public class ScriptSupport { private final Script script; + private final ScriptLog myScriptLog; - public ScriptSupport(String text, String name) { + public ScriptSupport(Project project, String text, String name) { + myScriptLog = new ScriptLog(project); File scriptFile = new File(text); GroovyShell shell = new GroovyShell(); try { - script = scriptFile.exists() ? shell.parse(scriptFile):shell.parse(text, name); + script = scriptFile.exists() ? shell.parse(scriptFile) : shell.parse(text, name); } catch (Exception ex) { Logger.getInstance(getClass().getName()).error(ex); throw new RuntimeException(ex); @@ -78,6 +82,7 @@ public class ScriptSupport { public String evaluate(MatchResult result, PsiElement context) { try { final HashMap variableMap = new HashMap(); + variableMap.put("__log__", myScriptLog); if (result != null) { buildVariableMap(result, variableMap); if (context == null) { @@ -87,7 +92,7 @@ public class ScriptSupport { final Binding binding = new Binding(variableMap); context = StructuralSearchUtil.getPresentableElement(context); - binding.setVariable("__context__", context); + binding.setVariable(Configuration.CONTEXT_VAR_NAME, context); script.setBinding(binding); final Object o = script.run(); diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/replace/impl/ReplacementBuilder.java b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/replace/impl/ReplacementBuilder.java index 2ec2c6ed3175..61c21f26180e 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/replace/impl/ReplacementBuilder.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/plugin/replace/impl/ReplacementBuilder.java @@ -34,8 +34,10 @@ public final class ReplacementBuilder { private final List parameterizations = new ArrayList(); private final Map replacementVarsMap; private final ReplaceOptions options; + private final Project myProject; ReplacementBuilder(final Project project,final ReplaceOptions options) { + myProject = project; replacementVarsMap = new HashMap(); this.options = options; String _replacement = options.getReplacement(); @@ -177,7 +179,7 @@ public final class ReplacementBuilder { if (scriptSupport == null) { String constraint = options.getVariableDefinition(info.getName()).getScriptCodeConstraint(); - scriptSupport = new ScriptSupport(StringUtil.stripQuotesAroundValue(constraint), info.getName()); + scriptSupport = new ScriptSupport(myProject, StringUtil.stripQuotesAroundValue(constraint), info.getName()); replacementVarsMap.put(info.getName(), scriptSupport); } return scriptSupport.evaluate(match, null); From 4625d366548813f4d7b0c000609929d8b5d44b9d Mon Sep 17 00:00:00 2001 From: "Vassiliy.Kudryashov" Date: Fri, 6 Nov 2015 22:41:25 +0300 Subject: [PATCH 083/124] IDEA-147099 ICSE at com.intellij.openapi.wm.impl.ToolWindowManagerImpl$RemoveWindowedDecoratorCmd. --- .../com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java index 41885d1cd823..6b62e19a9106 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java @@ -975,7 +975,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements deactivateToolWindowImpl(id, true, commandList); - if (hideSide && !info.isFloating()) { + if (hideSide && !info.isFloating() && !info.isWindowed()) { final List ids = myLayout.getVisibleIdsOn(info.getAnchor(), this); for (String each : ids) { myActiveStack.remove(each, true); @@ -2231,6 +2231,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements myId2WindowedDecorator.remove(info.getId()); JRootPane rootPane = ((RootPaneContainer)myWindowedDecorator.getFrame()).getRootPane(); + if (!rootPane.isShowing()) return; Rectangle bounds = rootPane.getBounds(); Point location = rootPane.getLocationOnScreen(); bounds.setBounds(location.x - DIVIDER_WIDTH, location.y - DIVIDER_WIDTH, bounds.width + 2 * DIVIDER_WIDTH, bounds.height + 2 * DIVIDER_WIDTH); From adcac39ed4a9d653250ced15a08964c5c6e5ee49 Mon Sep 17 00:00:00 2001 From: "Ilya.Kazakevich" Date: Sat, 31 Oct 2015 04:29:00 +0300 Subject: [PATCH 084/124] PY-17356: Attributes cached for function since as_manager / from_queryset is called multiple times --- .../python/psi/impl/PyFunctionImpl.java | 28 +++++++++++++++---- 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java index a88555bff68e..7f7b91c58f46 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java @@ -18,6 +18,7 @@ package com.jetbrains.python.psi.impl; import com.intellij.lang.ASTNode; import com.intellij.navigation.ItemPresentation; import com.intellij.openapi.extensions.Extensions; +import com.intellij.openapi.util.Key; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.text.StringUtil; @@ -29,10 +30,7 @@ import com.intellij.psi.search.LocalSearchScope; import com.intellij.psi.search.SearchScope; import com.intellij.psi.stubs.IStubElementType; import com.intellij.psi.stubs.StubElement; -import com.intellij.psi.util.CachedValueProvider; -import com.intellij.psi.util.CachedValuesManager; -import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.psi.util.QualifiedName; +import com.intellij.psi.util.*; import com.intellij.util.IncorrectOperationException; import com.intellij.util.PlatformIcons; import com.jetbrains.python.PyElementTypes; @@ -67,6 +65,9 @@ import static com.jetbrains.python.psi.impl.PyCallExpressionHelper.interpretAsMo */ public class PyFunctionImpl extends PyBaseElementImpl implements PyFunction { + private static final Key>> + ATTRIBUTES_KEY = Key.create("attributes"); + public PyFunctionImpl(ASTNode astNode) { super(astNode); } @@ -732,8 +733,23 @@ public class PyFunctionImpl extends PyBaseElementImpl implements @NotNull @Override public List findAttributes() { + return CachedValuesManager.getManager(getProject()).getCachedValue(this, ATTRIBUTES_KEY, new CachedValueProvider>() { + @Nullable + @Override + public Result> compute() { + final List result = findAttributesStatic(PyFunctionImpl.this); + return Result.create(result, PsiModificationTracker.MODIFICATION_COUNT); + } + }, false); + } + + /** + * @param self should be this + */ + @NotNull + private static List findAttributesStatic(@NotNull final PsiElement self) { final List result = new ArrayList(); - for (final PyAssignmentStatement statement : new PsiQuery(this).siblings(PyAssignmentStatement.class).getElements()) { + for (final PyAssignmentStatement statement : new PsiQuery(self).siblings(PyAssignmentStatement.class).getElements()) { for (final PyQualifiedExpression targetExpression : new PsiQuery(statement.getTargets()).filter(PyQualifiedExpression.class) .getElements()) { final PyExpression qualifier = targetExpression.getQualifier(); @@ -744,7 +760,7 @@ public class PyFunctionImpl extends PyBaseElementImpl implements if (qualifierReference == null) { continue; } - if (qualifierReference.isReferenceTo(this)) { + if (qualifierReference.isReferenceTo(self)) { result.add(statement); } } From 36fb42e303b114c7409a659d4a1dc18168d86fa3 Mon Sep 17 00:00:00 2001 From: "Ilya.Kazakevich" Date: Sat, 31 Oct 2015 05:23:16 +0300 Subject: [PATCH 085/124] PY-17356: PyTypeParser is slow, so we cache its result in PyCustomMember --- .../python/codeInsight/PyCustomMember.java | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/python/psi-api/src/com/jetbrains/python/codeInsight/PyCustomMember.java b/python/psi-api/src/com/jetbrains/python/codeInsight/PyCustomMember.java index 77218c6457fc..543d635050d5 100644 --- a/python/psi-api/src/com/jetbrains/python/codeInsight/PyCustomMember.java +++ b/python/psi-api/src/com/jetbrains/python/codeInsight/PyCustomMember.java @@ -17,8 +17,11 @@ package com.jetbrains.python.codeInsight; import com.intellij.extapi.psi.ASTWrapperPsiElement; import com.intellij.icons.AllIcons; +import com.intellij.openapi.util.Key; +import com.intellij.openapi.util.UserDataHolderBase; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiReference; +import com.intellij.psi.util.*; import com.intellij.util.Function; import com.jetbrains.python.psi.PyClass; import com.jetbrains.python.psi.PyFunction; @@ -34,7 +37,9 @@ import javax.swing.*; /** * @author Dennis.Ushakov */ -public class PyCustomMember { +public class PyCustomMember extends UserDataHolderBase { + private static final Key> + RESOLVE = Key.create("resolve"); private final String myName; private final boolean myResolveToInstance; private final Function myTypeCallback; @@ -165,14 +170,26 @@ public class PyCustomMember { } @Nullable - public PsiElement resolve(@NotNull PsiElement context) { + public PsiElement resolve(@NotNull final PsiElement context) { + if (myTarget != null) { return myTarget; } PyClass targetClass = null; if (myTypeName != null) { - targetClass = PyPsiFacade.getInstance(context.getProject()).createClassByQName(myTypeName, context); + + final ParameterizedCachedValueProvider provider = new ParameterizedCachedValueProvider() { + @Nullable + @Override + public CachedValueProvider.Result compute( + final PsiElement param) { + final PyClass result = PyPsiFacade.getInstance(param.getProject()).createClassByQName(myTypeName, param); + return CachedValueProvider.Result.create(result, PsiModificationTracker.MODIFICATION_COUNT); + } + }; + targetClass = CachedValuesManager.getManager(context.getProject()).getParameterizedCachedValue(this, RESOLVE, + provider, false, context); } final PsiElement resolveTarget = findResolveTarget(context); if (resolveTarget instanceof PyFunction && !myAlwaysResolveToCustomElement) { @@ -212,6 +229,7 @@ public class PyCustomMember { /** * Checks if some reference points to this element + * * @param reference reference to check * @return true if reference points to it */ From c7a14df2ab1ee837c851869e204f295b13e4870d Mon Sep 17 00:00:00 2001 From: "Ilya.Kazakevich" Date: Wed, 4 Nov 2015 02:48:29 +0300 Subject: [PATCH 086/124] PY-17356: shortcuts added to make inspections faster --- .../nameResolver/NameResolverTools.java | 80 ++++++++++++++++++- 1 file changed, 77 insertions(+), 3 deletions(-) diff --git a/python/psi-api/src/com/jetbrains/python/nameResolver/NameResolverTools.java b/python/psi-api/src/com/jetbrains/python/nameResolver/NameResolverTools.java index b9cbbaec5061..5118d2cd9edc 100644 --- a/python/psi-api/src/com/jetbrains/python/nameResolver/NameResolverTools.java +++ b/python/psi-api/src/com/jetbrains/python/nameResolver/NameResolverTools.java @@ -18,19 +18,22 @@ package com.jetbrains.python.nameResolver; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Pair; import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; import com.intellij.psi.PsiReference; import com.intellij.psi.util.PsiCacheKey; import com.intellij.psi.util.PsiModificationTracker; import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.util.QualifiedName; import com.intellij.util.Function; import com.jetbrains.python.psi.*; import com.jetbrains.python.psi.resolve.PyResolveContext; +import com.jetbrains.python.psi.types.PyFunctionType; +import com.jetbrains.python.psi.types.PyType; +import com.jetbrains.python.psi.types.TypeEvalContext; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; +import java.util.*; /** * @author Ilya.Kazakevich @@ -103,6 +106,77 @@ public final class NameResolverTools { return null; } + /** + * Same as {@link #isName(PyElement, FQNamesProvider...)} for call expr, but first checks name. + * Aliases not supported, but much lighter that way + * + * @param call expr + * @param function names to check + * @param context + * @return true if callee is correct + */ + public static boolean isCalleeShortCut(@NotNull final PyCallExpression call, + @NotNull final FQNamesProvider function, + @Nullable final TypeEvalContext context) { + if (context == null) { + return call.isCallee(function); + } + final PyExpression callee = call.getCallee(); + if (callee == null) { + return false; + } + + final PyType calleeType = context.getType(callee); + if (!(calleeType instanceof PyFunctionType)) { + return false; + } + final PyCallable callable = ((PyFunctionType)calleeType).getCallable(); + final String callableName = callable.getName(); + if (callableName == null) { + return false; + } + + final Set possibleNames = new HashSet(); + for (final String lastComponent : getLastComponents(function)) { + possibleNames.add(lastComponent); + } + return possibleNames.contains(callableName) && call.isCallee(function); + } + + @NotNull + private static List getLastComponents(@NotNull final FQNamesProvider provider) { + final List result = new ArrayList(); + for (final String name : provider.getNames()) { + final String component = QualifiedName.fromDottedString(name).getLastComponent(); + if (component != null) { + result.add(component); + } + } + return result; + } + + /** + * Checks if some string contains last component one of name + * @param text test to check + * @param names + */ + public static boolean isContainsName(@NotNull final String text, @NotNull final FQNamesProvider names) { + for (final String lastComponent : getLastComponents(names)) { + if (text.contains(lastComponent)) { + return true; + } + } + return false; + } + /** + * Checks if some file contains last component one of name + * @param file file to check + * @param names + */ + public static boolean isContainsName(@NotNull final PsiFile file, @NotNull final FQNamesProvider names) { + return isContainsName(file.getText(), names); + } + /** * Looks for call of some function */ From 36ff3702d7a693ba14e2b7b2aa9ad41ef896c9a3 Mon Sep 17 00:00:00 2001 From: "Ilya.Kazakevich" Date: Sat, 7 Nov 2015 01:28:20 +0300 Subject: [PATCH 087/124] Fixed according to reviews --- .../python/codeInsight/PyCustomMember.java | 24 +++---------------- .../nameResolver/NameResolverTools.java | 8 +++---- .../python/psi/PyCallExpression.java | 15 ++++++++---- .../python/psi/impl/PyFunctionImpl.java | 5 ++++ 4 files changed, 21 insertions(+), 31 deletions(-) diff --git a/python/psi-api/src/com/jetbrains/python/codeInsight/PyCustomMember.java b/python/psi-api/src/com/jetbrains/python/codeInsight/PyCustomMember.java index 543d635050d5..77218c6457fc 100644 --- a/python/psi-api/src/com/jetbrains/python/codeInsight/PyCustomMember.java +++ b/python/psi-api/src/com/jetbrains/python/codeInsight/PyCustomMember.java @@ -17,11 +17,8 @@ package com.jetbrains.python.codeInsight; import com.intellij.extapi.psi.ASTWrapperPsiElement; import com.intellij.icons.AllIcons; -import com.intellij.openapi.util.Key; -import com.intellij.openapi.util.UserDataHolderBase; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiReference; -import com.intellij.psi.util.*; import com.intellij.util.Function; import com.jetbrains.python.psi.PyClass; import com.jetbrains.python.psi.PyFunction; @@ -37,9 +34,7 @@ import javax.swing.*; /** * @author Dennis.Ushakov */ -public class PyCustomMember extends UserDataHolderBase { - private static final Key> - RESOLVE = Key.create("resolve"); +public class PyCustomMember { private final String myName; private final boolean myResolveToInstance; private final Function myTypeCallback; @@ -170,26 +165,14 @@ public class PyCustomMember extends UserDataHolderBase { } @Nullable - public PsiElement resolve(@NotNull final PsiElement context) { - + public PsiElement resolve(@NotNull PsiElement context) { if (myTarget != null) { return myTarget; } PyClass targetClass = null; if (myTypeName != null) { - - final ParameterizedCachedValueProvider provider = new ParameterizedCachedValueProvider() { - @Nullable - @Override - public CachedValueProvider.Result compute( - final PsiElement param) { - final PyClass result = PyPsiFacade.getInstance(param.getProject()).createClassByQName(myTypeName, param); - return CachedValueProvider.Result.create(result, PsiModificationTracker.MODIFICATION_COUNT); - } - }; - targetClass = CachedValuesManager.getManager(context.getProject()).getParameterizedCachedValue(this, RESOLVE, - provider, false, context); + targetClass = PyPsiFacade.getInstance(context.getProject()).createClassByQName(myTypeName, context); } final PsiElement resolveTarget = findResolveTarget(context); if (resolveTarget instanceof PyFunction && !myAlwaysResolveToCustomElement) { @@ -229,7 +212,6 @@ public class PyCustomMember extends UserDataHolderBase { /** * Checks if some reference points to this element - * * @param reference reference to check * @return true if reference points to it */ diff --git a/python/psi-api/src/com/jetbrains/python/nameResolver/NameResolverTools.java b/python/psi-api/src/com/jetbrains/python/nameResolver/NameResolverTools.java index 5118d2cd9edc..86d52efc483a 100644 --- a/python/psi-api/src/com/jetbrains/python/nameResolver/NameResolverTools.java +++ b/python/psi-api/src/com/jetbrains/python/nameResolver/NameResolverTools.java @@ -67,7 +67,8 @@ public final class NameResolverTools { } /** - * Checks if FQ element name is one of provided names + * Checks if FQ element name is one of provided names. May be heavy. + * It is always better to use less accurate but lighter {@link #isCalleeShortCut(PyCallExpression, FQNamesProvider, TypeEvalContext)} * * @param element element to check * @param namesProviders some enum that has one or more names @@ -117,10 +118,7 @@ public final class NameResolverTools { */ public static boolean isCalleeShortCut(@NotNull final PyCallExpression call, @NotNull final FQNamesProvider function, - @Nullable final TypeEvalContext context) { - if (context == null) { - return call.isCallee(function); - } + @NotNull final TypeEvalContext context) { final PyExpression callee = call.getCallee(); if (callee == null) { return false; diff --git a/python/psi-api/src/com/jetbrains/python/psi/PyCallExpression.java b/python/psi-api/src/com/jetbrains/python/psi/PyCallExpression.java index da96e7e29b61..4c5b6a1bd0f7 100644 --- a/python/psi-api/src/com/jetbrains/python/psi/PyCallExpression.java +++ b/python/psi-api/src/com/jetbrains/python/psi/PyCallExpression.java @@ -19,6 +19,7 @@ import com.intellij.psi.PsiElement; import com.jetbrains.python.FunctionParameter; import com.jetbrains.python.nameResolver.FQNamesProvider; import com.jetbrains.python.psi.resolve.PyResolveContext; +import com.jetbrains.python.psi.types.TypeEvalContext; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -74,7 +75,7 @@ public interface PyCallExpression extends PyCallSiteExpression { * Returns the argument if one is present in the list. * * @param parameter parameter - * @param argClass argument expected type + * @param argClass argument expected type * @return the argument or null */ @Nullable @@ -85,6 +86,7 @@ public interface PyCallExpression extends PyCallSiteExpression { /** * TODO: Copy/Paste with {@link PyArgumentList#addArgument(PyExpression)} + * * @param expression */ void addArgument(PyExpression expression); @@ -110,7 +112,6 @@ public interface PyCallExpression extends PyCallSiteExpression { PyCallable resolveCalleeFunction(PyResolveContext resolveContext); /** - * * @param resolveContext the reference resolve context * @param implicitOffset known from the context implicit offset */ @@ -133,9 +134,13 @@ public interface PyCallExpression extends PyCallSiteExpression { /** * Checks if the qualified name of the callee matches any of the specified names provided by provider. - * @see com.jetbrains.python.nameResolver + * May be heavy. + * Use {@link com.jetbrains.python.nameResolver.NameResolverTools#isCalleeShortCut(PyCallExpression, FQNamesProvider, TypeEvalContext)} + * if you can. + * * @param name providers that provides one or more names to check * @return true if matches, false otherwise + * @see com.jetbrains.python.nameResolver */ boolean isCallee(@NotNull FQNamesProvider... name); @@ -243,8 +248,8 @@ public interface PyCallExpression extends PyCallSiteExpression { /** * @return number of implicitly passed positional parameters; 0 means no parameters are passed implicitly. - * Note that a *args is never marked as passed implicitly. - * E.g. for a function like foo(a, b, *args) always holds getImplicitOffset() < 2. + * Note that a *args is never marked as passed implicitly. + * E.g. for a function like foo(a, b, *args) always holds getImplicitOffset() < 2. */ public int getImplicitOffset() { return myImplicitOffset; diff --git a/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java index 7f7b91c58f46..781391c9a2bf 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java @@ -733,6 +733,11 @@ public class PyFunctionImpl extends PyBaseElementImpl implements @NotNull @Override public List findAttributes() { + /** + * TODO: This method if insanely heavy since it unstubs foreign files. + * Need to save stubs and use them somehow. + * + */ return CachedValuesManager.getManager(getProject()).getCachedValue(this, ATTRIBUTES_KEY, new CachedValueProvider>() { @Nullable @Override From e7e1f81c663dd4d74cebecf6548b857abb9d50ea Mon Sep 17 00:00:00 2001 From: Sergey Simonchik Date: Sat, 7 Nov 2015 12:44:00 +0300 Subject: [PATCH 088/124] test for VfsUtil.findRelativeFile(uri, base) --- .../com/intellij/openapi/vfs/VfsUtilTest.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/vfs/VfsUtilTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/vfs/VfsUtilTest.java index c90c85bd5b3d..0a39b739c208 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/vfs/VfsUtilTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/vfs/VfsUtilTest.java @@ -113,6 +113,25 @@ public class VfsUtilTest extends PlatformTestCase { assertEquals("test text", content); } + public void testFindRelativeFile() throws Exception { + final VirtualFile root = VirtualFileManager.getInstance().findFileByUrl("temp:///"); + assertNotNull(root); + VirtualFile file = VfsUtilCore.findRelativeFile(root.getUrl(), null); + assertEquals(root, file); + + File ioTestDataDir = new File(PathManagerEx.getTestDataPath()); + VirtualFile testDataDir = LocalFileSystem.getInstance().findFileByIoFile(ioTestDataDir); + assertNotNull(testDataDir); + assertEquals(testDataDir, VfsUtilCore.findRelativeFile(VfsUtilCore.convertFromUrl(ioTestDataDir.toURI().toURL()), null)); + assertEquals(testDataDir, VfsUtilCore.findRelativeFile(ioTestDataDir.getAbsolutePath(), null)); + + File ioVfsDir = new File(ioTestDataDir, "vfs"); + VirtualFile vfsDir = LocalFileSystem.getInstance().findFileByIoFile(ioVfsDir); + assertNotNull(vfsDir); + assertEquals(vfsDir, VfsUtilCore.findRelativeFile(ioVfsDir.getAbsolutePath(), null)); + assertEquals(vfsDir, VfsUtilCore.findRelativeFile("vfs", testDataDir)); + } + public void testRelativePath() throws Exception { final File root = new File(PathManagerEx.getTestDataPath()); final File testRoot = new File(new File(root, "vfs"), "relativePath"); From 07af579d00c82519ccb448d0b03c5af844a879a6 Mon Sep 17 00:00:00 2001 From: Tobias Bieniek Date: Sat, 7 Nov 2015 17:44:59 +0100 Subject: [PATCH 089/124] CodeDocumenationAwareCommenter: Fix copy/paste issues --- .../com/intellij/lang/CodeDocumentationAwareCommenter.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/core-api/src/com/intellij/lang/CodeDocumentationAwareCommenter.java b/platform/core-api/src/com/intellij/lang/CodeDocumentationAwareCommenter.java index fe07a4a257ef..b90a9a9e9196 100644 --- a/platform/core-api/src/com/intellij/lang/CodeDocumentationAwareCommenter.java +++ b/platform/core-api/src/com/intellij/lang/CodeDocumentationAwareCommenter.java @@ -39,7 +39,7 @@ public interface CodeDocumentationAwareCommenter extends Commenter { * Returns the type of the block comment in the language, * or null if the language does not support block comments. * It is assumed that block comment prefix is not null when block comment type is not null. - * @return the line block comment type. + * @return the block comment type. */ @Nullable IElementType getBlockCommentTokenType(); @@ -48,7 +48,7 @@ public interface CodeDocumentationAwareCommenter extends Commenter { * Returns the type of the documentation comment token in the language, * or null if the language does not support documentation comments. * It is assumed that documentation comment prefix is not null when documentation comment type is not null. - * @return the line block comment type. + * @return the documentation comment type. */ @Nullable IElementType getDocumentationCommentTokenType(); From 55afd7a01616a7ff3aea345ea89f79144670c915 Mon Sep 17 00:00:00 2001 From: Sergey Ignatov Date: Sat, 7 Nov 2015 20:01:18 +0300 Subject: [PATCH 090/124] cleanup for dataflow renderer --- .../src/com/intellij/slicer/SliceUsageCellRenderer.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/java/java-impl/src/com/intellij/slicer/SliceUsageCellRenderer.java b/java/java-impl/src/com/intellij/slicer/SliceUsageCellRenderer.java index 0dc68c326dac..a0cc2fa7fea5 100644 --- a/java/java-impl/src/com/intellij/slicer/SliceUsageCellRenderer.java +++ b/java/java-impl/src/com/intellij/slicer/SliceUsageCellRenderer.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 JetBrains s.r.o. + * 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. @@ -21,6 +21,7 @@ import com.intellij.psi.*; import com.intellij.psi.util.PsiFormatUtil; import com.intellij.psi.util.PsiFormatUtilBase; import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.ui.JBColor; import com.intellij.ui.SimpleTextAttributes; import com.intellij.usages.TextChunk; import com.intellij.util.FontUtil; @@ -56,7 +57,7 @@ public class SliceUsageCellRenderer extends SliceUsageCellRendererBase { TextChunk textChunk = text[i]; SimpleTextAttributes attributes = textChunk.getSimpleAttributesIgnoreBackground(); if (isForcedLeaf) { - attributes = attributes.derive(attributes.getStyle(), Color.LIGHT_GRAY, attributes.getBgColor(), attributes.getWaveColor()); + attributes = attributes.derive(attributes.getStyle(), JBColor.LIGHT_GRAY, attributes.getBgColor(), attributes.getWaveColor()); } boolean inUsage = (attributes.getFontStyle() & Font.BOLD) != 0; if (isInsideContainer && inUsage) { @@ -66,7 +67,7 @@ public class SliceUsageCellRenderer extends SliceUsageCellRendererBase { //setPaintFocusBorder(true); } append(textChunk.getText(), attributes); - if(i == 0){ + if (i == 0) { append(FontUtil.spaceAndThinSpace()); } } From 6816336a80668924ca159dbcb8f34e0d77ec6599 Mon Sep 17 00:00:00 2001 From: "Vassiliy.Kudryashov" Date: Sat, 7 Nov 2015 23:44:42 +0300 Subject: [PATCH 091/124] IDEA-147099 ICSE at com.intellij.openapi.wm.impl.ToolWindowManagerImpl$RemoveWindowedDecoratorCmd. --- .../openapi/wm/impl/ToolWindowManagerImpl.java | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java index 6b62e19a9106..7cb55c917692 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java @@ -2091,7 +2091,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements private final FloatingDecorator myFloatingDecorator; /** - * Creates floating decorator for specified floating decorator. + * Creates floating decorator for specified internal decorator. */ private AddFloatingDecoratorCmd(final InternalDecorator decorator, final WindowInfoImpl info) { super(myWindowManager.getCommandProcessor()); @@ -2163,7 +2163,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements private final WindowedDecorator myWindowedDecorator; /** - * Creates floating decorator for specified floating decorator. + * Creates windowed decorator for specified internal decorator. */ private AddWindowedDecoratorCmd(final InternalDecorator decorator, final WindowInfoImpl info) { super(myWindowManager.getCommandProcessor()); @@ -2230,11 +2230,10 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements myWindowedDecorator = getWindowedDecorator(info.getId()); myId2WindowedDecorator.remove(info.getId()); - JRootPane rootPane = ((RootPaneContainer)myWindowedDecorator.getFrame()).getRootPane(); - if (!rootPane.isShowing()) return; - Rectangle bounds = rootPane.getBounds(); - Point location = rootPane.getLocationOnScreen(); - bounds.setBounds(location.x - DIVIDER_WIDTH, location.y - DIVIDER_WIDTH, bounds.width + 2 * DIVIDER_WIDTH, bounds.height + 2 * DIVIDER_WIDTH); + Window frame = myWindowedDecorator.getFrame(); + if (!frame.isShowing()) return; + Rectangle bounds = frame.getBounds(); + bounds.setLocation(frame.getLocationOnScreen()); info.setFloatingBounds(bounds); } From b4bdc916c592a9886f4ec1f9a80bb5a9a9920bd8 Mon Sep 17 00:00:00 2001 From: "Vassiliy.Kudryashov" Date: Sat, 7 Nov 2015 23:45:34 +0300 Subject: [PATCH 092/124] IDEA-147099 ICSE at com.intellij.openapi.wm.impl.ToolWindowManagerImpl$RemoveWindowedDecoratorCmd. --- .../com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java index 7cb55c917692..5f4cc4b91363 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java @@ -85,8 +85,6 @@ import java.beans.PropertyChangeListener; import java.util.*; import java.util.List; -import static com.intellij.openapi.wm.impl.FloatingDecorator.DIVIDER_WIDTH; - /** * @author Anton Katilin * @author Vladimir Kondratyev @@ -2170,9 +2168,6 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements myWindowedDecorator = new WindowedDecorator(myProject, info.copy(), decorator); Window window = myWindowedDecorator.getFrame(); final Rectangle bounds = info.getFloatingBounds(); - if (bounds != null) { - bounds.setBounds(bounds.x + DIVIDER_WIDTH, bounds.y + DIVIDER_WIDTH, bounds.width - 2 * DIVIDER_WIDTH, bounds.height - 2 * DIVIDER_WIDTH); - } if (bounds != null && bounds.width > 0 && bounds.height > 0 && From 8b57c2d95e39d7c08e42bb5b074969f076a321d8 Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Sun, 8 Nov 2015 22:11:11 +0300 Subject: [PATCH 093/124] [vcs-log] make BekLinearGraph testable --- .../graph/impl/facade/BekBaseController.java | 19 +++++++++------- .../log/graph/impl/facade/bek/BekChecker.java | 22 +++++++++++++++---- 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/facade/BekBaseController.java b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/facade/BekBaseController.java index 573d1f7dffc9..0e941ce5a183 100644 --- a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/facade/BekBaseController.java +++ b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/facade/BekBaseController.java @@ -25,6 +25,7 @@ import com.intellij.vcs.log.graph.api.elements.GraphNodeType; import com.intellij.vcs.log.graph.api.permanent.PermanentGraphInfo; import com.intellij.vcs.log.graph.impl.facade.bek.BekChecker; import com.intellij.vcs.log.graph.impl.facade.bek.BekIntMap; +import com.intellij.vcs.log.graph.impl.permanent.PermanentLinearGraphImpl; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -39,9 +40,9 @@ public class BekBaseController extends CascadeController { public BekBaseController(@NotNull PermanentGraphInfo permanentGraphInfo, @NotNull BekIntMap bekIntMap) { super(null, permanentGraphInfo); myBekIntMap = bekIntMap; - myBekGraph = new BekLinearGraph(); + myBekGraph = new BekLinearGraph(myBekIntMap, myPermanentGraphInfo.getPermanentLinearGraph()); - assert BekChecker.checkLinearGraph(myBekGraph); // todo drop later + BekChecker.checkLinearGraph(myBekGraph); } @NotNull @@ -85,16 +86,18 @@ public class BekBaseController extends CascadeController { return myBekGraph; } - private class BekLinearGraph implements LinearGraph { - @NotNull private final LinearGraph myPermanentGraph; + public static class BekLinearGraph implements LinearGraph { + @NotNull private final LinearGraph myLinearGraph; + @NotNull private final BekIntMap myBekIntMap; - private BekLinearGraph() { - myPermanentGraph = myPermanentGraphInfo.getPermanentLinearGraph(); + public BekLinearGraph(@NotNull BekIntMap bekIntMap, @NotNull LinearGraph linearGraph) { + myLinearGraph = linearGraph; + myBekIntMap = bekIntMap; } @Override public int nodesCount() { - return myPermanentGraph.nodesCount(); + return myLinearGraph.nodesCount(); } @Nullable @@ -107,7 +110,7 @@ public class BekBaseController extends CascadeController { @NotNull @Override public List getAdjacentEdges(int nodeIndex, @NotNull EdgeFilter filter) { - return map(myPermanentGraph.getAdjacentEdges(myBekIntMap.getUsualIndex(nodeIndex), filter), new Function() { + return map(myLinearGraph.getAdjacentEdges(myBekIntMap.getUsualIndex(nodeIndex), filter), new Function() { @Override public GraphEdge fun(GraphEdge edge) { return new GraphEdge(getNodeIndex(edge.getUpNodeIndex()), getNodeIndex(edge.getDownNodeIndex()), edge.getTargetId(), diff --git a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/facade/bek/BekChecker.java b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/facade/bek/BekChecker.java index b1dcc6a9bdd9..6e6cd7e0316a 100644 --- a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/facade/bek/BekChecker.java +++ b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/facade/bek/BekChecker.java @@ -16,8 +16,10 @@ package com.intellij.vcs.log.graph.impl.facade.bek; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.Pair; import com.intellij.vcs.log.graph.api.LinearGraph; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import static com.intellij.vcs.log.graph.utils.LinearGraphUtils.getDownNodes; import static com.intellij.vcs.log.graph.utils.LinearGraphUtils.getUpNodes; @@ -25,17 +27,29 @@ import static com.intellij.vcs.log.graph.utils.LinearGraphUtils.getUpNodes; public class BekChecker { private final static Logger LOG = Logger.getInstance("#com.intellij.vcs.log.graph.impl.facade.bek.BekChecker"); - public static boolean checkLinearGraph(@NotNull LinearGraph linearGraph) { + public static void checkLinearGraph(@NotNull LinearGraph linearGraph) { + Pair reversedEdge = findReversedEdge(linearGraph); + if (reversedEdge != null) { + LOG.error("Illegal edge: up node " + reversedEdge.first + ", downNode " + reversedEdge.second); + } + } + + @Nullable + public static Pair findReversedEdge(@NotNull LinearGraph linearGraph) { for (int i = 0; i < linearGraph.nodesCount(); i++) { for (int downNode : getDownNodes(linearGraph, i)) { - if (downNode <= i) LOG.error("Illegal node: " + i + ", with downNode: " + downNode); + if (downNode <= i) { + return Pair.create(i, downNode); + } } for (int upNode : getUpNodes(linearGraph, i)) { - if (upNode >= i) LOG.error("Illegal node: " + i + ", with upNode: " + upNode); + if (upNode >= i) { + return Pair.create(upNode, i); + } } } - return true; + return null; } } From 6145eb84b2aaf183e3fe042f265ae1cac7a97f60 Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Sun, 8 Nov 2015 22:13:43 +0300 Subject: [PATCH 094/124] [vcs-log] test for EA-68497 and IDEA-147201 --- .../vcs/log/graph/linearBek/BekTest.kt | 40 +++++++++++++++++++ .../vcs/log/graph/linearBek/TestUtils.kt | 31 +++++++++++--- 2 files changed, 65 insertions(+), 6 deletions(-) create mode 100644 platform/vcs-log/graph/test/com/intellij/vcs/log/graph/linearBek/BekTest.kt diff --git a/platform/vcs-log/graph/test/com/intellij/vcs/log/graph/linearBek/BekTest.kt b/platform/vcs-log/graph/test/com/intellij/vcs/log/graph/linearBek/BekTest.kt new file mode 100644 index 000000000000..230f65247859 --- /dev/null +++ b/platform/vcs-log/graph/test/com/intellij/vcs/log/graph/linearBek/BekTest.kt @@ -0,0 +1,40 @@ +/* + * 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 com.intellij.vcs.log.graph.linearBek + +import com.intellij.vcs.log.graph.TestGraphBuilder +import org.junit.Test + +class BekTest { + fun runTest(beforeBekBuilder: TestGraphBuilder.() -> Unit, afterBekBuilder: TestGraphBuilder.() -> Unit) { + assertEquals(afterBekBuilder, runBek(beforeBekBuilder)) + } + + @Test fun ea68497() = runTest({ + 0(1, 3) + 1(4, 2) + 2(4, 3) + 3() + 4() + }, { + 0(1, 3) + 1(4, 2) + 2(4, 3) + 3() + 4() + }) +} + diff --git a/platform/vcs-log/graph/test/com/intellij/vcs/log/graph/linearBek/TestUtils.kt b/platform/vcs-log/graph/test/com/intellij/vcs/log/graph/linearBek/TestUtils.kt index d9941724beb0..2ae82a4024f1 100644 --- a/platform/vcs-log/graph/test/com/intellij/vcs/log/graph/linearBek/TestUtils.kt +++ b/platform/vcs-log/graph/test/com/intellij/vcs/log/graph/linearBek/TestUtils.kt @@ -15,14 +15,18 @@ */ package com.intellij.vcs.log.graph.linearBek -import com.intellij.vcs.log.graph.utils.TimestampGetter import com.intellij.vcs.log.graph.TestGraphBuilder -import com.intellij.vcs.log.graph.impl.permanent.GraphLayoutBuilder import com.intellij.vcs.log.graph.api.LinearGraph -import com.intellij.vcs.log.graph.graph -import org.junit.Assert.assertEquals import com.intellij.vcs.log.graph.asTestGraphString +import com.intellij.vcs.log.graph.graph +import com.intellij.vcs.log.graph.impl.facade.BekBaseController +import com.intellij.vcs.log.graph.impl.facade.bek.BekChecker +import com.intellij.vcs.log.graph.impl.facade.bek.BekSorter +import com.intellij.vcs.log.graph.impl.permanent.GraphLayoutBuilder import com.intellij.vcs.log.graph.impl.permanent.GraphLayoutImpl +import com.intellij.vcs.log.graph.utils.TimestampGetter +import org.junit.Assert.assertEquals +import kotlin.test.assertNull public class DummyTimestampGetter(val nodesCount: Int) : TimestampGetter { override fun size(): Int { @@ -35,7 +39,22 @@ public class DummyTimestampGetter(val nodesCount: Int) : TimestampGetter { } public fun buildLayout(graphBuilder: TestGraphBuilder.() -> Unit): GraphLayoutImpl { - return GraphLayoutBuilder.build(graph(graphBuilder), {nodeIndex1, nodeIndex2 -> nodeIndex1 - nodeIndex2 }) + return GraphLayoutBuilder.build(graph(graphBuilder), { nodeIndex1, nodeIndex2 -> nodeIndex1 - nodeIndex2 }) +} + +fun runBek(graphBuilder: TestGraphBuilder.() -> Unit): BekBaseController.BekLinearGraph { + val beforeBek = graph(graphBuilder) + val beforeLayout = buildLayout(graphBuilder) + + val bekMap = BekSorter.createBekMap(beforeBek, beforeLayout, DummyTimestampGetter(beforeBek.nodesCount())) + val afterBek = BekBaseController.BekLinearGraph(bekMap, beforeBek) + + val edge = BekChecker.findReversedEdge(afterBek) + if (edge != null) { + assertNull(Pair(bekMap.getUsualIndex(edge.first), bekMap.getUsualIndex(edge.second)), "Found reversed edge"); + } + + return afterBek } public fun runLinearBek(graphBuilder: TestGraphBuilder.() -> Unit): LinearBekGraph { @@ -49,4 +68,4 @@ public fun runLinearBek(graphBuilder: TestGraphBuilder.() -> Unit): LinearBekGra public fun assertEquals(expected: TestGraphBuilder.() -> Unit, actual: LinearGraph): Unit { assertEquals(graph(expected).asTestGraphString(), actual.asTestGraphString()) -} \ No newline at end of file +} From ca03edaf783c5e910d1f042080faca4dd453f6be Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Sun, 8 Nov 2015 22:14:20 +0300 Subject: [PATCH 095/124] [vcs-log] fix EA-68497 and IDEA-147201 --- .../vcs/log/graph/impl/facade/bek/BekBranchCreator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/facade/bek/BekBranchCreator.java b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/facade/bek/BekBranchCreator.java index f8092d6b503f..df2d13e14c0c 100644 --- a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/facade/bek/BekBranchCreator.java +++ b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/impl/facade/bek/BekBranchCreator.java @@ -79,7 +79,7 @@ class BekBranchCreator { // almost ok node, except (may be) up nodes boolean hasUndoneUpNodes = false; for (int upNode : getUpNodes(myPermanentGraph, downNode)) { - if (!myDoneNodes.get(upNode) && myGraphLayout.getLayoutIndex(upNode) <= currentLayout) { + if (!myDoneNodes.get(upNode) && myGraphLayout.getLayoutIndex(upNode) <= myGraphLayout.getLayoutIndex(downNode)) { hasUndoneUpNodes = true; break; } From b77b5c996d166389ff8de10ca5422748817ea6bf Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Sun, 8 Nov 2015 22:15:28 +0300 Subject: [PATCH 096/124] [vcs-log] add "operator" keyword where needed in kotlin code --- .../graph/test/com/intellij/vcs/log/graph/TestGraphBuilder.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/vcs-log/graph/test/com/intellij/vcs/log/graph/TestGraphBuilder.kt b/platform/vcs-log/graph/test/com/intellij/vcs/log/graph/TestGraphBuilder.kt index b55f3c721e57..1e35ca5d9ff0 100644 --- a/platform/vcs-log/graph/test/com/intellij/vcs/log/graph/TestGraphBuilder.kt +++ b/platform/vcs-log/graph/test/com/intellij/vcs/log/graph/TestGraphBuilder.kt @@ -59,8 +59,8 @@ public class TestGraphBuilder : BaseTestGraphBuilder { public fun done(): LinearGraph = TestLinearGraph(nodes) - public fun Int.invoke(): Unit = newNode(asSimpleNode()) - public fun Int.invoke(vararg edge: Int): Unit = newNode(asSimpleNode(), edge.asSimpleEdges()) + public operator fun Int.invoke(): Unit = newNode(asSimpleNode()) + public operator fun Int.invoke(vararg edge: Int): Unit = newNode(asSimpleNode(), edge.asSimpleEdges()) public fun Int.invoke(vararg edge: SimpleEdge): Unit = newNode(asSimpleNode(), edge.toList()) public fun SimpleNode.invoke(): Unit = newNode(this) public fun SimpleNode.invoke(vararg edge: Int): Unit = newNode(this, edge.asSimpleEdges()) From d206b4d19d83e106ec634d29f0fa6b89f67756fa Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Sun, 8 Nov 2015 22:17:17 +0300 Subject: [PATCH 097/124] [vcs-log] followup for EA-68497 and IDEA-147201: even if a graph is broken do not add strange dashed edges to it --- .../log/graph/collapsing/DottedFilterEdgesGenerator.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/collapsing/DottedFilterEdgesGenerator.java b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/collapsing/DottedFilterEdgesGenerator.java index cc5f42f6af70..6f31ad03fe02 100644 --- a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/collapsing/DottedFilterEdgesGenerator.java +++ b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/collapsing/DottedFilterEdgesGenerator.java @@ -67,9 +67,16 @@ public class DottedFilterEdgesGenerator { // update specified range private void update() { downWalk(); + cleanup(); upWalk(); } + private void cleanup() { + for (int currentNodeIndex = myUpIndex; currentNodeIndex <= myDownIndex; currentNodeIndex++) { + myNumbers.setNumber(currentNodeIndex, Integer.MAX_VALUE); + } + } + private boolean hasDottedEdges(int nodeIndex, boolean isUp) { for (GraphEdge edge : myModification.getEdgesToAdd().getAdjacentEdges(nodeIndex, EdgeFilter.NORMAL_ALL)) { if (edge.getType() == DOTTED) { From f456457c60f74aa9c3a1deda4c276496174e7d03 Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Sun, 8 Nov 2015 22:39:53 +0300 Subject: [PATCH 098/124] [vcs-log] add some simple bek tests --- .../vcs/log/graph/linearBek/BekTest.kt | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/platform/vcs-log/graph/test/com/intellij/vcs/log/graph/linearBek/BekTest.kt b/platform/vcs-log/graph/test/com/intellij/vcs/log/graph/linearBek/BekTest.kt index 230f65247859..55568458dcf3 100644 --- a/platform/vcs-log/graph/test/com/intellij/vcs/log/graph/linearBek/BekTest.kt +++ b/platform/vcs-log/graph/test/com/intellij/vcs/log/graph/linearBek/BekTest.kt @@ -36,5 +36,49 @@ class BekTest { 3() 4() }) + + @Test fun simpleMerge() = runTest({ + 0(1, 2) + 1(3) + 2(4) + 3(5) + 4(5) + 5() + }, { + 0(1, 2) + 2(4) + 4(5) + 1(3) + 3(5) + 5() + }) + + @Test fun twoHeads() = runTest({ + 0(2) + 1(2) + 2() + }, { + 1(2) + 0(2) + 2() + }) + + @Test fun simpleMergeWithTwoHeads() = runTest({ + 0(2, 3) + 1(4) + 2(4) + 3(5) + 4(6) + 5(6) + 6() + }, { + 1(4) + 0(2, 3) + 3(5) + 5(6) + 2(4) + 4(6) + 6() + }) } From 98e29159fb5bb68ed95453791202edcac2e10d97 Mon Sep 17 00:00:00 2001 From: Sergey Simonchik Date: Mon, 9 Nov 2015 01:41:24 +0300 Subject: [PATCH 099/124] macros: support passing compound relative path to $FileDirPathFromParent(...)$ macro (fixes WEB-18982) --- .../ide/macro/FileDirPathFromParentMacro.java | 79 +++++++++++++++++-- 1 file changed, 72 insertions(+), 7 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/macro/FileDirPathFromParentMacro.java b/platform/lang-impl/src/com/intellij/ide/macro/FileDirPathFromParentMacro.java index eb68ae221082..faee0d18ab2f 100644 --- a/platform/lang-impl/src/com/intellij/ide/macro/FileDirPathFromParentMacro.java +++ b/platform/lang-impl/src/com/intellij/ide/macro/FileDirPathFromParentMacro.java @@ -18,9 +18,16 @@ package com.intellij.ide.macro; import com.intellij.ide.IdeBundle; import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NotNull; public class FileDirPathFromParentMacro extends Macro { + + private static final String PATH_DELIMITER = "/"; + @Override public String getName() { return "FileDirPathFromParent"; @@ -41,13 +48,71 @@ public class FileDirPathFromParentMacro extends Macro { if(args.length == 0) { return super.expand(dataContext, args); } - String param = args[0]; - VirtualFile vFile = getVirtualDirOrParent(dataContext); - StringBuilder result = new StringBuilder(); - while (vFile != null && !param.equalsIgnoreCase(vFile.getName())) { - result.insert(0, vFile.getName() + "/"); - vFile = vFile.getParent(); + VirtualFile dir = getVirtualDirOrParent(dataContext); + if (dir == null) { + return ""; } - return result.toString(); + String dirPath = dir.getPath(); + String surroundedSubDir = surroundWithSlashes(FileUtil.toSystemIndependentName(args[0])); + String surroundedDirPath = surroundWithSlashes(dirPath); + if (surroundedSubDir.length() == 1) { + return surroundedDirPath.substring(1); + } + int ind = lastIndexOf(surroundedDirPath, + surroundedSubDir, + surroundedDirPath.length(), + !SystemInfo.isFileSystemCaseSensitive); + if (ind >= 0) { + return surroundedDirPath.substring(ind + surroundedSubDir.length()); + } + return dirPath; + } + + private static int lastIndexOf(@NotNull CharSequence buffer, @NotNull String pattern, int maxIndex, boolean ignoreCase) { + int patternLength = pattern.length(); + int end = buffer.length() - patternLength; + if (maxIndex > end) { + maxIndex = end; + } + for (int i = maxIndex; i >= 0; i--) { + boolean found = true; + for (int j = 0; j < patternLength; j++) { + if (ignoreCase) { + if (StringUtil.charsEqualIgnoreCase(pattern.charAt(j), buffer.charAt(i + j))) { + found = false; + break; + } + } + else { + if (pattern.charAt(j) != buffer.charAt(i + j)) { + found = false; + break; + } + } + } + if (found) { + return i; + } + } + return -1; + } + + @NotNull + private static String surroundWithSlashes(@NotNull String path) { + if (path.isEmpty()) { + return PATH_DELIMITER; + } + boolean prepend = !path.startsWith(PATH_DELIMITER); + boolean append = !path.endsWith(PATH_DELIMITER); + if (prepend && append) { + return PATH_DELIMITER + path + PATH_DELIMITER; + } + if (prepend) { + path = PATH_DELIMITER + path; + } + if (append) { + path += PATH_DELIMITER; + } + return path; } } From fe8fb9c16756268a0bdf670e76c0b600d7d303ae Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Fri, 30 Oct 2015 15:58:55 +0300 Subject: [PATCH 100/124] fixed PY-17113 Right click menu is very slow to open up in PyCharm EAP PY-143.24 --- .../python/packaging/PyCondaPackageManagerImpl.java | 4 ++-- .../jetbrains/python/packaging/PyPackageManagerImpl.java | 9 +++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/python/src/com/jetbrains/python/packaging/PyCondaPackageManagerImpl.java b/python/src/com/jetbrains/python/packaging/PyCondaPackageManagerImpl.java index d46dce3f0b5a..95f6ef828fee 100644 --- a/python/src/com/jetbrains/python/packaging/PyCondaPackageManagerImpl.java +++ b/python/src/com/jetbrains/python/packaging/PyCondaPackageManagerImpl.java @@ -130,9 +130,9 @@ public class PyCondaPackageManagerImpl extends PyPackageManagerImpl { getCondaOutput("remove", arguments); } - @Nullable + @NotNull @Override - public List getPackages(boolean cachedOnly) throws ExecutionException { + protected List getPackages() throws ExecutionException { final ProcessOutput output = getCondaOutput("list", Lists.newArrayList("-e")); return parseCondaToolOutput(output.getStdout()); } diff --git a/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java b/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java index d7ef61698cf2..dc4506aa15fb 100644 --- a/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java +++ b/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java @@ -276,8 +276,7 @@ public class PyPackageManagerImpl extends PyPackageManager { } } try { - final String output = getHelperResult(PACKAGING_TOOL, Arrays.asList("list"), false, false, null); - final List packages = parsePackagingToolOutput(output); + final List packages = getPackages(); synchronized (myCacheLock) { myPackagesCache = packages; return new ArrayList(myPackagesCache); @@ -291,6 +290,12 @@ public class PyPackageManagerImpl extends PyPackageManager { } } + @NotNull + protected List getPackages() throws ExecutionException { + final String output = getHelperResult(PACKAGING_TOOL, Arrays.asList("list"), false, false, null); + return parsePackagingToolOutput(output); + } + @Nullable public Set getDependents(@NotNull PyPackage pkg) throws ExecutionException { final List packages = getPackages(false); From bb9e1acf69f56854f679e5b4f6dff6365dcdeb78 Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Tue, 3 Nov 2015 16:51:12 +0300 Subject: [PATCH 101/124] updated plugin system for pycharm educational --- .../resources/META-INF/plugin.xml | 4 ++- .../resources/META-INF/plugin.xml | 2 ++ python/edu/resources/META-INF/plugin.xml | 33 +++++++++++++++++++ .../resources/META-INF/plugin.xml | 3 +- .../resources/META-INF/plugin.xml | 1 + .../educational/resources/META-INF/plugin.xml | 33 +++++++++++++++++++ 6 files changed, 74 insertions(+), 2 deletions(-) create mode 100644 python/edu/resources/META-INF/plugin.xml create mode 100644 python/educational/resources/META-INF/plugin.xml diff --git a/python/edu/course-creator-python/resources/META-INF/plugin.xml b/python/edu/course-creator-python/resources/META-INF/plugin.xml index 1aae572b65b5..96bd6f624ede 100644 --- a/python/edu/course-creator-python/resources/META-INF/plugin.xml +++ b/python/edu/course-creator-python/resources/META-INF/plugin.xml @@ -2,7 +2,7 @@ com.jetbrains.edu.coursecreator.python Course Creator for PyCharm Edu 2.0 - + . ]]> @@ -22,6 +22,8 @@ com.intellij.modules.platform com.intellij.modules.python com.jetbrains.edu.coursecreator + com.jetbrains.edu.core + com.jetbrains.python.edu.core diff --git a/python/edu/interactive-learning-python/resources/META-INF/plugin.xml b/python/edu/interactive-learning-python/resources/META-INF/plugin.xml index e5f7e473282d..1adcccf71a9c 100644 --- a/python/edu/interactive-learning-python/resources/META-INF/plugin.xml +++ b/python/edu/interactive-learning-python/resources/META-INF/plugin.xml @@ -18,6 +18,8 @@ com.intellij.modules.lang com.intellij.modules.python com.jetbrains.edu.interactivelearning + com.jetbrains.edu.core + com.jetbrains.python.edu.core diff --git a/python/edu/resources/META-INF/plugin.xml b/python/edu/resources/META-INF/plugin.xml new file mode 100644 index 000000000000..995178645571 --- /dev/null +++ b/python/edu/resources/META-INF/plugin.xml @@ -0,0 +1,33 @@ + + com.jetbrains.python.edu.core + Python-specific part for Stepic connector + 2.0 + + + JetBrains + + + + + + + com.intellij.modules.lang + + + + + + + + + + + + + + \ No newline at end of file diff --git a/python/educational/course-creator/resources/META-INF/plugin.xml b/python/educational/course-creator/resources/META-INF/plugin.xml index 672d7c6f3ed7..d553a3ae30b6 100644 --- a/python/educational/course-creator/resources/META-INF/plugin.xml +++ b/python/educational/course-creator/resources/META-INF/plugin.xml @@ -2,7 +2,7 @@ com.jetbrains.edu.coursecreator Course Creator Plugin 2.0 - + @@ -19,6 +19,7 @@ com.intellij.modules.lang --> com.intellij.modules.platform + com.jetbrains.edu.core diff --git a/python/educational/interactive-learning/resources/META-INF/plugin.xml b/python/educational/interactive-learning/resources/META-INF/plugin.xml index 4610eb466f89..35d4322c1a32 100644 --- a/python/educational/interactive-learning/resources/META-INF/plugin.xml +++ b/python/educational/interactive-learning/resources/META-INF/plugin.xml @@ -20,6 +20,7 @@ on how to target different products --> com.intellij.modules.lang + com.jetbrains.edu.core diff --git a/python/educational/resources/META-INF/plugin.xml b/python/educational/resources/META-INF/plugin.xml new file mode 100644 index 000000000000..3a5a7bb1b1dc --- /dev/null +++ b/python/educational/resources/META-INF/plugin.xml @@ -0,0 +1,33 @@ + + com.jetbrains.edu.core + Stepic connector + 2.0 + + + JetBrains + + + + + + + com.intellij.modules.lang + + + + + + + + + + + + + + \ No newline at end of file From ace83aa6df98c0124d7c49d5987bef4f3df0b63c Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 9 Nov 2015 11:26:45 +0100 Subject: [PATCH 102/124] internal API for easier completion statistic collection --- .../completion/CompletionLookupArranger.java | 68 ++++++++++++------- .../completion/StatisticsComparable.java | 51 ++++++++++++++ .../completion/StatisticsWeigher.java | 41 +++++------ .../impl/LiftShorterItemsClassifier.java | 33 ++++----- .../lookup/CachingComparingClassifier.java | 16 +++-- .../codeInsight/lookup/Classifier.java | 36 +++++++--- .../lookup/ComparingClassifier.java | 36 ++++------ .../codeInsight/lookup/LookupArranger.java | 10 ++- .../codeInsight/lookup/impl/LookupImpl.java | 9 ++- .../internal/DumpLookupElementWeights.java | 29 ++++---- .../impl/CodeInsightTestFixtureImpl.java | 4 +- 11 files changed, 213 insertions(+), 120 deletions(-) create mode 100644 platform/lang-impl/src/com/intellij/codeInsight/completion/StatisticsComparable.java diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionLookupArranger.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionLookupArranger.java index ea449e8ba1be..cff59c10fddf 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionLookupArranger.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionLookupArranger.java @@ -32,10 +32,7 @@ import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.RangeMarker; import com.intellij.openapi.editor.event.DocumentAdapter; import com.intellij.openapi.editor.event.DocumentEvent; -import com.intellij.openapi.util.Condition; -import com.intellij.openapi.util.Disposer; -import com.intellij.openapi.util.Key; -import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.*; import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; import com.intellij.patterns.StandardPatterns; @@ -93,7 +90,7 @@ public class CompletionLookupArranger extends LookupArranger { myLocation = new CompletionLocation(parameters); } - private MultiMap groupItemsBySorter(List source) { + private MultiMap groupItemsBySorter(Iterable source) { MultiMap inputBySorter = MultiMap.createLinked(); for (LookupElement element : source) { inputBySorter.putValue(obtainSorter(element), element); @@ -106,28 +103,30 @@ public class CompletionLookupArranger extends LookupArranger { return myProcess.getSorter(element); } + @NotNull @Override - public Map getRelevanceStrings() { - final LinkedHashMap map = new LinkedHashMap(); - for (LookupElement item : myItems) { - map.put(item, new StringBuilder()); - } - final MultiMap inputBySorter = groupItemsBySorter(new ArrayList(map.keySet())); - - if (inputBySorter.size() > 1) { - for (LookupElement element : map.keySet()) { - map.get(element).append(obtainSorter(element)).append(": "); - } - } - + public Map>> getRelevanceObjects(@NotNull Iterable items, + boolean hideSingleValued) { + final LinkedHashMap>> map = ContainerUtil.newLinkedHashMap(); + final MultiMap inputBySorter = groupItemsBySorter(items); + int sorterNumber = 0; for (CompletionSorterImpl sorter : inputBySorter.keySet()) { - final LinkedHashMap subMap = new LinkedHashMap(); - for (LookupElement element : inputBySorter.get(sorter)) { - subMap.put(element, map.get(element)); + sorterNumber++; + Collection thisSorterItems = inputBySorter.get(sorter); + for (LookupElement element : thisSorterItems) { + map.put(element, ContainerUtil.newArrayList(new Pair("frozen", myFrozenItems.contains(element)), + new Pair("sorter", sorterNumber))); } + ProcessingContext context = createContext(false); Classifier classifier = myClassifiers.get(sorter); - if (classifier != null) { - classifier.describeItems(subMap, createContext(false)); + while (classifier != null) { + List> pairs = classifier.getSortingWeights(thisSorterItems, context); + if (!hideSingleValued || !haveSameWeights(pairs)) { + for (Pair pair : pairs) { + map.get(pair.first).add(Pair.create(classifier.getPresentableName(), pair.second)); + } + } + classifier = classifier.getNext(); } } @@ -135,6 +134,18 @@ public class CompletionLookupArranger extends LookupArranger { } + private static boolean haveSameWeights(List> pairs) { + if (pairs.isEmpty()) return true; + + for (int i = 1; i < pairs.size(); i++) { + if (!Comparing.equal(pairs.get(i).second, pairs.get(0).second)) { + return false; + } + } + + return true; + } + @Override public void addElement(Lookup lookup, LookupElement element, LookupElementPresentation presentation) { StatisticsWeigher.clearBaseStatisticsInfo(element); @@ -570,12 +581,19 @@ public class CompletionLookupArranger extends LookupArranger { private final LookupImpl myLookup; private AlphaClassifier(LookupImpl lookup) { - super(null); + super(null, "alpha"); myLookup = lookup; } + @NotNull @Override - public Iterable classify(Iterable source, ProcessingContext context) { + public List> getSortingWeights(@NotNull Iterable items, @NotNull ProcessingContext context) { + return Collections.emptyList(); + } + + @NotNull + @Override + public Iterable classify(@NotNull Iterable source, @NotNull ProcessingContext context) { return sortByPresentation(source, myLookup); } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/StatisticsComparable.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/StatisticsComparable.java new file mode 100644 index 000000000000..ba72751ee357 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/StatisticsComparable.java @@ -0,0 +1,51 @@ +/* + * 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 com.intellij.codeInsight.completion; + +import com.intellij.psi.statistics.StatisticsInfo; +import org.jetbrains.annotations.NotNull; + +/** + * @author peter + */ +public class StatisticsComparable implements Comparable { + private final int myScalar; + private final StatisticsInfo myStatisticsInfo; + + public StatisticsComparable(int scalar, @NotNull StatisticsInfo statisticsInfo) { + myScalar = scalar; + myStatisticsInfo = statisticsInfo; + } + + public int getScalar() { + return myScalar; + } + + @NotNull + public StatisticsInfo getStatisticsInfo() { + return myStatisticsInfo; + } + + @Override + public String toString() { + return String.valueOf(myScalar); + } + + @Override + public int compareTo(StatisticsComparable o) { + return myScalar < o.myScalar ? -1 : myScalar == o.myScalar ? 0 : 1; + } +} diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/StatisticsWeigher.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/StatisticsWeigher.java index 176827ce4070..f6ee7eeb9cb9 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/StatisticsWeigher.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/StatisticsWeigher.java @@ -22,8 +22,10 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Key; +import com.intellij.openapi.util.Pair; import com.intellij.psi.statistics.StatisticsInfo; import com.intellij.psi.statistics.StatisticsManager; +import com.intellij.util.Function; import com.intellij.util.ProcessingContext; import com.intellij.util.SmartList; import com.intellij.util.containers.ContainerUtil; @@ -49,19 +51,19 @@ public class StatisticsWeigher extends CompletionWeigher { public static class LookupStatisticsWeigher extends Classifier { private final CompletionLocation myLocation; - private final Map myWeights = new IdentityHashMap(); - @SuppressWarnings("unchecked") private final Set myNoStats = new THashSet(TObjectHashingStrategy.IDENTITY); + private final Map myWeights = ContainerUtil.newIdentityHashMap(); + private final Set myNoStats = ContainerUtil.newIdentityTroveSet(); private int myPrefixChanges; public LookupStatisticsWeigher(CompletionLocation location, Classifier next) { - super(next); + super(next, "stats"); myLocation = location; } @Override - public void addElement(LookupElement element, ProcessingContext context) { + public void addElement(@NotNull LookupElement element, @NotNull ProcessingContext context) { StatisticsInfo baseInfo = getBaseStatisticsInfo(element, myLocation); - myWeights.put(element, weigh(element, baseInfo, context.get(CompletionLookupArranger.WEIGHING_CONTEXT))); + myWeights.put(element, new StatisticsComparable(weigh(element, baseInfo, context.get(CompletionLookupArranger.WEIGHING_CONTEXT)), baseInfo)); if (baseInfo == StatisticsInfo.EMPTY) { myNoStats.add(element); } @@ -76,8 +78,9 @@ public class StatisticsWeigher extends CompletionWeigher { } } + @NotNull @Override - public Iterable classify(Iterable source, final ProcessingContext context) { + public Iterable classify(@NotNull Iterable source, @NotNull final ProcessingContext context) { checkPrefixChanged(context); final Collection> byWeight = buildMapByWeight(source, context).descendingMap().values(); @@ -122,7 +125,7 @@ public class StatisticsWeigher extends CompletionWeigher { private TreeMap> buildMapByWeight(Iterable source, ProcessingContext context) { TreeMap> map = new TreeMap>(); for (LookupElement element : source) { - final int weight = getWeight(element, context.get(CompletionLookupArranger.WEIGHING_CONTEXT)); + final int weight = getWeight(element, context.get(CompletionLookupArranger.WEIGHING_CONTEXT)).getScalar(); List list = map.get(weight); if (list == null) { map.put(weight, list = new SmartList()); @@ -132,10 +135,11 @@ public class StatisticsWeigher extends CompletionWeigher { return map; } - private int getWeight(LookupElement t, WeighingContext context) { - Integer w = myWeights.get(t); + private StatisticsComparable getWeight(LookupElement t, WeighingContext context) { + StatisticsComparable w = myWeights.get(t); if (w == null) { - myWeights.put(t, w = weigh(t, getBaseStatisticsInfo(t, myLocation), context)); + StatisticsInfo info = getBaseStatisticsInfo(t, myLocation); + myWeights.put(t, w = new StatisticsComparable(weigh(t, info, context), info)); } return w; } @@ -151,21 +155,20 @@ public class StatisticsWeigher extends CompletionWeigher { return minRecency == Integer.MAX_VALUE ? useCount : 100 - minRecency; } + @NotNull @Override - public void describeItems(LinkedHashMap map, ProcessingContext context) { + public List> getSortingWeights(@NotNull Iterable items, @NotNull final ProcessingContext context) { checkPrefixChanged(context); - for (LookupElement element : map.keySet()) { - StringBuilder builder = map.get(element); - if (builder.length() > 0) { - builder.append(", "); + return ContainerUtil.map(items, new Function>() { + @Override + public Pair fun(LookupElement lookupElement) { + return new Pair(lookupElement, getWeight(lookupElement, context.get(CompletionLookupArranger.WEIGHING_CONTEXT))); } - builder.append("stats=").append(getWeight(element, context.get(CompletionLookupArranger.WEIGHING_CONTEXT))); - } - super.describeItems(map, context); + }); } @Override - public void removeElement(LookupElement element, ProcessingContext context) { + public void removeElement(@NotNull LookupElement element, @NotNull ProcessingContext context) { myWeights.remove(element); myNoStats.remove(element); super.removeElement(element, context); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/LiftShorterItemsClassifier.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/LiftShorterItemsClassifier.java index 9e7a9cb2e9a9..efc4401f2d9b 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/LiftShorterItemsClassifier.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/LiftShorterItemsClassifier.java @@ -19,6 +19,8 @@ import com.intellij.codeInsight.completion.CompletionUtil; import com.intellij.codeInsight.lookup.Classifier; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.openapi.util.Condition; +import com.intellij.openapi.util.Pair; +import com.intellij.util.Function; import com.intellij.util.ProcessingContext; import com.intellij.util.containers.*; import gnu.trove.THashSet; @@ -39,20 +41,18 @@ public class LiftShorterItemsClassifier extends Classifier { private final MultiMap myElements = createMultiMap(false); private final MultiMap myToLift = createMultiMap(true); private final MultiMap myReversedToLift = createMultiMap(true); - private final String myName; private final LiftingCondition myCondition; private final boolean myLiftBefore; private int myCount = 0; public LiftShorterItemsClassifier(String name, Classifier next, LiftingCondition condition, boolean liftBefore) { - super(next); - myName = name; + super(next, name); myCondition = condition; myLiftBefore = liftBefore; } @Override - public void addElement(LookupElement added, ProcessingContext context) { + public void addElement(@NotNull LookupElement added, @NotNull ProcessingContext context) { myCount++; for (String string : CompletionUtil.iterateLookupStrings(added)) { @@ -96,8 +96,9 @@ public class LiftShorterItemsClassifier extends Classifier { } } + @NotNull @Override - public Iterable classify(Iterable source, ProcessingContext context) { + public Iterable classify(@NotNull Iterable source, @NotNull ProcessingContext context) { return liftShorterElements(source, null, context); } @@ -113,25 +114,21 @@ public class LiftShorterItemsClassifier extends Classifier { return new LiftingIterable(srcSet, context, source, lifted); } + @NotNull @Override - public void describeItems(LinkedHashMap map, ProcessingContext context) { + public List> getSortingWeights(@NotNull Iterable items, @NotNull ProcessingContext context) { final THashSet lifted = newIdentityTroveSet(); - liftShorterElements(new ArrayList(map.keySet()), lifted, context); - if (!lifted.isEmpty()) { - for (LookupElement element : map.keySet()) { - final StringBuilder builder = map.get(element); - if (builder.length() > 0) { - builder.append(", "); - } - - builder.append(myName).append("=").append(lifted.contains(element)); + liftShorterElements(ContainerUtil.newArrayList(items), lifted, context); + return ContainerUtil.map(items, new Function>() { + @Override + public Pair fun(LookupElement element) { + return new Pair(element, lifted.contains(element)); } - } - super.describeItems(map, context); + }); } @Override - public void removeElement(LookupElement element, ProcessingContext context) { + public void removeElement(@NotNull LookupElement element, @NotNull ProcessingContext context) { for (String s : CompletionUtil.iterateLookupStrings(element)) { myElements.remove(s, element); if (myElements.get(s).isEmpty()) { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/CachingComparingClassifier.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/CachingComparingClassifier.java index dba7c55964f3..5597f1483440 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/CachingComparingClassifier.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/CachingComparingClassifier.java @@ -17,13 +17,15 @@ package com.intellij.codeInsight.lookup; import com.intellij.codeInsight.completion.CompletionLookupArranger; import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.Ref; import com.intellij.psi.ForceableComparable; import com.intellij.util.ProcessingContext; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.IdentityHashMap; -import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; /** @@ -52,13 +54,14 @@ public class CachingComparingClassifier extends ComparingClassifier classify(Iterable source, ProcessingContext context) { + public Iterable classify(@NotNull Iterable source, @NotNull ProcessingContext context) { if (!myWeigher.isPrefixDependent() && myPrimitive) { return myNext.classify(source, context); } @@ -75,14 +78,15 @@ public class CachingComparingClassifier extends ComparingClassifier map, ProcessingContext context) { + public List> getSortingWeights(@NotNull Iterable items, @NotNull ProcessingContext context) { checkPrefixChanged(context); - super.describeItems(map, context); + return super.getSortingWeights(items, context); } @Override - public void addElement(LookupElement t, ProcessingContext context) { + public void addElement(@NotNull LookupElement t, @NotNull ProcessingContext context) { Comparable weight = myWeigher.weigh(t, context.get(CompletionLookupArranger.WEIGHING_CONTEXT)); if (weight instanceof ForceableComparable) { ((ForceableComparable)weight).force(); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/Classifier.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/Classifier.java index 42ced4a0c60f..5f33e16bf184 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/Classifier.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/Classifier.java @@ -15,37 +15,55 @@ */ package com.intellij.codeInsight.lookup; +import com.intellij.openapi.util.Pair; import com.intellij.util.ProcessingContext; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; -import java.util.LinkedHashMap; +import java.util.List; /** * @author peter */ public abstract class Classifier { protected final Classifier myNext; + private final String myName; - protected Classifier(Classifier next) { + protected Classifier(@Nullable Classifier next, String name) { myNext = next; + myName = name; } - public void addElement(T t, ProcessingContext context) { + public void addElement(@NotNull T t, @NotNull ProcessingContext context) { if (myNext != null) { myNext.addElement(t, context); } } - public abstract Iterable classify(Iterable source, ProcessingContext context); + @NotNull + public abstract Iterable classify(@NotNull Iterable source, @NotNull ProcessingContext context); - public void describeItems(LinkedHashMap map, ProcessingContext context) { - if (myNext != null) { - myNext.describeItems(map, context); - } + /** + * @return a mapping from the given items to objects (e.g. Comparable instances) used to sort the items in {@link #classify(Iterable, ProcessingContext)}. + * May return an empty list if there are no suitable objects available. + * Used for diagnostics and statistic collection. + */ + @NotNull + public abstract List> getSortingWeights(@NotNull Iterable items, @NotNull ProcessingContext context); + + @Nullable + public final Classifier getNext() { + return myNext; } - public void removeElement(T element, ProcessingContext context) { + public void removeElement(@NotNull T element, @NotNull ProcessingContext context) { if (myNext != null) { myNext.removeElement(element, context); } } + + @NotNull + public final String getPresentableName() { + return myName; + } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/ComparingClassifier.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/ComparingClassifier.java index d399fac02f3a..96faa2fd8c31 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/ComparingClassifier.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/ComparingClassifier.java @@ -15,11 +15,13 @@ */ package com.intellij.codeInsight.lookup; -import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.util.Pair; +import com.intellij.util.Function; import com.intellij.util.ProcessingContext; import com.intellij.util.SmartList; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.FlatteningIterator; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.*; @@ -28,24 +30,19 @@ import java.util.*; * @author peter */ public abstract class ComparingClassifier extends Classifier { - protected final String myName; private final boolean myNegated; - public ComparingClassifier(Classifier next, String name) { - this(next, name, false); - } - protected ComparingClassifier(Classifier next, String name, boolean negated) { - super(next); - myName = name; + super(next, name); myNegated = negated; } @Nullable public abstract Comparable getWeight(T t, ProcessingContext context); + @NotNull @Override - public Iterable classify(final Iterable source, final ProcessingContext context) { + public Iterable classify(@NotNull final Iterable source, @NotNull final ProcessingContext context) { List nulls = null; TreeMap> map = new TreeMap>(); for (T t : source) { @@ -79,21 +76,14 @@ public abstract class ComparingClassifier extends Classifier { }; } + @NotNull @Override - public void describeItems(LinkedHashMap map, ProcessingContext context) { - Map weights = new IdentityHashMap(); - for (T t : map.keySet()) { - weights.put(t, String.valueOf(getWeight(t, context))); - } - if (new HashSet(weights.values()).size() > 1 || ApplicationManager.getApplication().isUnitTestMode()) { - for (T t : map.keySet()) { - final StringBuilder builder = map.get(t); - if (builder.length() > 0) { - builder.append(", "); - } - builder.append(myName).append("=").append(weights.get(t)); + public List> getSortingWeights(@NotNull Iterable items, @NotNull final ProcessingContext context) { + return ContainerUtil.map(items, new Function>() { + @Override + public Pair fun(T t) { + return new Pair(t, getWeight(t, context)); } - } - super.describeItems(map, context); + }); } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/LookupArranger.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/LookupArranger.java index b58ac2ce3a65..aea154223bac 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/LookupArranger.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/LookupArranger.java @@ -122,7 +122,15 @@ public abstract class LookupArranger { return myMatchingItems; } - public Map getRelevanceStrings() { + /** + * @param items the items to give relevance weight for + * @param hideSingleValued whether criteria that gave same values for all items should be skipped + * @return for each item, an (ordered) map of criteria used for lookup relevance sorting + * along with the objects representing the weights in these criteria + */ + @NotNull + public Map>> getRelevanceObjects(@NotNull Iterable items, + boolean hideSingleValued) { return Collections.emptyMap(); } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java index bc16f354e5eb..ea0f8a4853e5 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java @@ -67,10 +67,8 @@ import javax.swing.event.ListSelectionListener; import java.awt.*; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; -import java.util.Collection; -import java.util.HashMap; +import java.util.*; import java.util.List; -import java.util.Map; public class LookupImpl extends LightweightHint implements LookupEx, Disposable, WeighingContext { private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.lookup.impl.LookupImpl"); @@ -1153,9 +1151,10 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable, return true; } - public Map getRelevanceStrings() { + @NotNull + public Map>> getRelevanceObjects(@NotNull Iterable items, boolean hideSingleValued) { synchronized (myList) { - return myPresentableArranger.getRelevanceStrings(); + return myPresentableArranger.getRelevanceObjects(items, hideSingleValued); } } diff --git a/platform/lang-impl/src/com/intellij/internal/DumpLookupElementWeights.java b/platform/lang-impl/src/com/intellij/internal/DumpLookupElementWeights.java index 40dce539f4ff..49e355c0a586 100644 --- a/platform/lang-impl/src/com/intellij/internal/DumpLookupElementWeights.java +++ b/platform/lang-impl/src/com/intellij/internal/DumpLookupElementWeights.java @@ -27,10 +27,12 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.ide.CopyPasteManager; import com.intellij.openapi.project.DumbAware; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; import java.awt.datatransfer.StringSelection; -import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -59,7 +61,7 @@ public class DumpLookupElementWeights extends AnAction implements DumbAware { if (selected != null) { sb += "\nprefix: " + lookup.itemPattern(selected); } - sb += "\nweights:\n" + StringUtil.join(getLookupElementWeights(lookup), "\n"); + sb += "\nweights:\n" + StringUtil.join(getLookupElementWeights(lookup, true), "\n"); System.out.println(sb); LOG.info(sb); try { @@ -67,15 +69,18 @@ public class DumpLookupElementWeights extends AnAction implements DumbAware { } catch (Exception ignore){} } - public static List getLookupElementWeights(LookupImpl lookup) { - final Map strings = lookup.getRelevanceStrings(); - List sb = new ArrayList(); - for (LookupElement item : lookup.getItems()) { - StringBuilder builder = strings.get(item); - String weight = builder == null ? "null" : builder.toString(); - final String s = item.getLookupString() + "\t" + weight; - sb.add(s); - } - return sb; + public static List getLookupElementWeights(LookupImpl lookup, boolean hideSingleValued) { + final Map>> weights = lookup.getRelevanceObjects(lookup.getItems(), hideSingleValued); + return ContainerUtil.map(weights.entrySet(), new Function>>, String>() { + @Override + public String fun(Map.Entry>> entry) { + return entry.getKey().getLookupString() + "\t" + StringUtil.join(entry.getValue(), new Function, String>() { + @Override + public String fun(Pair pair) { + return pair.first + "=" + pair.second; + } + }, ", "); + } + }); } } \ No newline at end of file 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 dd52c9fc66e4..f32e275c7337 100644 --- a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java +++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java @@ -1893,10 +1893,10 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig Assert.assertNotNull(strings); final List actual = strings.subList(0, Math.min(expected.length, strings.size())); if (!actual.equals(Arrays.asList(expected))) { - UsefulTestCase.assertOrderedEquals(DumpLookupElementWeights.getLookupElementWeights(lookup), expected); + UsefulTestCase.assertOrderedEquals(DumpLookupElementWeights.getLookupElementWeights(lookup, false), expected); } if (selected != list.getSelectedIndex()) { - System.out.println(DumpLookupElementWeights.getLookupElementWeights(lookup)); + System.out.println(DumpLookupElementWeights.getLookupElementWeights(lookup, false)); } Assert.assertEquals(selected, list.getSelectedIndex()); } From 23396fec90e893f2f8434c7e6c97b9de97bfbf4a Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Mon, 9 Nov 2015 11:49:00 +0100 Subject: [PATCH 103/124] message readability improved according to hhariri's feedback --- .../impl/CheckRequiredPluginsActivity.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/externalDependencies/impl/CheckRequiredPluginsActivity.java b/platform/platform-impl/src/com/intellij/externalDependencies/impl/CheckRequiredPluginsActivity.java index a85400460c81..782ec7a2ebef 100644 --- a/platform/platform-impl/src/com/intellij/externalDependencies/impl/CheckRequiredPluginsActivity.java +++ b/platform/platform-impl/src/com/intellij/externalDependencies/impl/CheckRequiredPluginsActivity.java @@ -71,11 +71,11 @@ public class CheckRequiredPluginsActivity implements StartupActivity, DumbAware } String minVersion = dependency.getMinVersion(); if (minVersion != null && VersionComparatorUtil.compare(plugin.getVersion(), minVersion) < 0) { - errorMessages.add("Project '" + project.getName() + "' requires '" + plugin.getName() + "' plugin of version at least '" + minVersion + "', but '" + plugin.getVersion() + "' is installed."); + errorMessages.add("Project '" + project.getName() + "' requires plugin '" + plugin.getName() + "' version '" + minVersion + "' or higher, but '" + plugin.getVersion() + "' is installed."); } String maxVersion = dependency.getMaxVersion(); if (maxVersion != null && VersionComparatorUtil.compare(plugin.getVersion(), maxVersion) > 0) { - errorMessages.add("Project '" + project.getName() + "' requires '" + plugin.getName() + "' plugin of version at most '" + maxVersion + "', but '" + plugin.getVersion() + "' is installed."); + errorMessages.add("Project '" + project.getName() + "' requires plugin '" + plugin.getName() + "' version '" + minVersion + "' or lower, but '" + plugin.getVersion() + "' is installed."); } } From 681079f5437df1b7c925e974ce0afd1a9408526e Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Mon, 2 Nov 2015 14:15:01 +0300 Subject: [PATCH 104/124] PY-17295 Add missing cast to StatementListContainer (IDEA-CR-6388) --- python/src/com/jetbrains/python/psi/PyUtil.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/src/com/jetbrains/python/psi/PyUtil.java b/python/src/com/jetbrains/python/psi/PyUtil.java index fc3b8ff5e686..bf32c66b7b60 100644 --- a/python/src/com/jetbrains/python/psi/PyUtil.java +++ b/python/src/com/jetbrains/python/psi/PyUtil.java @@ -1475,7 +1475,7 @@ public class PyUtil { final PsiDocumentManager manager = PsiDocumentManager.getInstance(statementList.getProject()); final Document document = manager.getDocument(statementList.getContainingFile()); if (document != null) { - final PsiElement container = statementList.getParent(); + final PyStatementListContainer container = (PyStatementListContainer)statementList.getParent(); manager.doPostponedOperationsAndUnblockDocument(document); final String indentation = "\n" + PyIndentUtil.getElementIndent(statementList); // If statement list was empty initially, we need to add some anchor statement ("pass"), so that preceding new line was not @@ -1483,7 +1483,7 @@ public class PyUtil { final String text = statementList.getStatements().length == 0 ? indentation + PyNames.PASS : indentation; document.insertString(statementList.getTextRange().getStartOffset(), text); manager.commitDocument(document); - statementList = ((PyStatementListContainer)container).getStatementList(); + statementList = container.getStatementList(); } } final PsiElement firstChild = statementList.getFirstChild(); From 07cfbebd4aa4c0f2afc5f26567f65897ce855109 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Mon, 2 Nov 2015 14:17:15 +0300 Subject: [PATCH 105/124] PyStatementListContainer extends PyElement, so it can be used in methods like PsiTreeUtil#getParentOfType --- .../src/com/jetbrains/python/psi/PyStatementListContainer.java | 2 +- .../psi-api/src/com/jetbrains/python/psi/PyStatementPart.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/python/psi-api/src/com/jetbrains/python/psi/PyStatementListContainer.java b/python/psi-api/src/com/jetbrains/python/psi/PyStatementListContainer.java index c56b799f429c..b69e2c70f41e 100644 --- a/python/psi-api/src/com/jetbrains/python/psi/PyStatementListContainer.java +++ b/python/psi-api/src/com/jetbrains/python/psi/PyStatementListContainer.java @@ -20,7 +20,7 @@ import org.jetbrains.annotations.NotNull; /** * @author Ilya.Kazakevich */ -public interface PyStatementListContainer { +public interface PyStatementListContainer extends PyElement { @NotNull PyStatementList getStatementList(); } diff --git a/python/psi-api/src/com/jetbrains/python/psi/PyStatementPart.java b/python/psi-api/src/com/jetbrains/python/psi/PyStatementPart.java index 0ebc50865504..b639f206277b 100644 --- a/python/psi-api/src/com/jetbrains/python/psi/PyStatementPart.java +++ b/python/psi-api/src/com/jetbrains/python/psi/PyStatementPart.java @@ -20,6 +20,6 @@ package com.jetbrains.python.psi; * User: dcheryasov * Date: Mar 16, 2009 4:34:59 AM */ -public interface PyStatementPart extends PyElement, PyStatementListContainer { +public interface PyStatementPart extends PyStatementListContainer { PyStatementPart[] EMPTY_ARRAY = new PyStatementPart[0]; } From 1c76041108635cce275150cea30aeb9ca1b0a7b8 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Mon, 2 Nov 2015 14:39:18 +0300 Subject: [PATCH 106/124] PY-13304 Cleanup in PyBlock * Nullified * Got rid of remaining snake_case * Add missing @Override annotations * Remove redundant "final" modifiers --- .../jetbrains/python/formatter/PyBlock.java | 86 +++++++++---------- 1 file changed, 41 insertions(+), 45 deletions(-) diff --git a/python/src/com/jetbrains/python/formatter/PyBlock.java b/python/src/com/jetbrains/python/formatter/PyBlock.java index dc45bed51317..55d6eaad1261 100644 --- a/python/src/com/jetbrains/python/formatter/PyBlock.java +++ b/python/src/com/jetbrains/python/formatter/PyBlock.java @@ -77,7 +77,6 @@ public class PyBlock implements ASTBlock { PyElementTypes.CALL_EXPRESSION, PyElementTypes.FROM_IMPORT_STATEMENT); - private static final boolean DUMP_FORMATTING_BLOCKS = false; public static final Key IMPORT_GROUP_BEGIN = Key.create("com.jetbrains.python.formatter.importGroupBegin"); private final PyBlock myParent; @@ -93,12 +92,12 @@ public class PyBlock implements ASTBlock { private final Wrap myDictWrapping; private final boolean myEmptySequence; - public PyBlock(final PyBlock parent, - final ASTNode node, - final Alignment alignment, - final Indent indent, - final Wrap wrap, - final PyBlockContext context) { + public PyBlock(@Nullable PyBlock parent, + @NotNull ASTNode node, + @Nullable Alignment alignment, + @NotNull Indent indent, + @Nullable Wrap wrap, + @NotNull PyBlockContext context) { myParent = parent; myAlignment = alignment; myIndent = indent; @@ -117,11 +116,13 @@ public class PyBlock implements ASTBlock { } } + @Override @NotNull public ASTNode getNode() { return myNode; } + @Override @NotNull public TextRange getTextRange() { return myNode.getTextRange(); @@ -134,14 +135,12 @@ public class PyBlock implements ASTBlock { return myChildAlignment; } + @Override @NotNull public List getSubBlocks() { if (mySubBlocks == null) { mySubBlockByNode = buildSubBlocks(); mySubBlocks = new ArrayList(mySubBlockByNode.values()); - if (DUMP_FORMATTING_BLOCKS) { - dumpSubBlocks(); - } } return Collections.unmodifiableList(mySubBlocks); } @@ -174,7 +173,8 @@ public class PyBlock implements ASTBlock { return Collections.unmodifiableMap(blocks); } - private PyBlock buildSubBlock(ASTNode child) { + @NotNull + private PyBlock buildSubBlock(@NotNull ASTNode child) { final IElementType parentType = myNode.getElementType(); final ASTNode grandParentNode = myNode.getTreeParent(); @@ -248,7 +248,7 @@ public class PyBlock implements ASTBlock { } } - PyCodeStyleSettings settings = CodeStyleSettingsManager.getSettings(child.getPsi().getProject()).getCustomSettings(PyCodeStyleSettings.class); + final PyCodeStyleSettings settings = CodeStyleSettingsManager.getSettings(child.getPsi().getProject()).getCustomSettings(PyCodeStyleSettings.class); if (parentType == PyElementTypes.LIST_LITERAL_EXPRESSION || parentType == PyElementTypes.LIST_COMP_EXPRESSION) { if (childType == PyTokenTypes.RBRACKET || childType == PyTokenTypes.LBRACKET) { childIndent = Indent.getNoneIndent(); @@ -518,7 +518,7 @@ public class PyBlock implements ASTBlock { return type != PyElementTypes.BINARY_EXPRESSION; } - private static Alignment getAlignmentOfChild(PyBlock b, int childNum) { + private static Alignment getAlignmentOfChild(@NotNull PyBlock b, int childNum) { if (b.getSubBlocks().size() > childNum) { final ChildAttributes attributes = b.getChildAttributes(childNum); return attributes.getAlignment(); @@ -526,7 +526,7 @@ public class PyBlock implements ASTBlock { return null; } - private static boolean isIndentNext(ASTNode child) { + private static boolean isIndentNext(@NotNull ASTNode child) { final PsiElement psi = PsiTreeUtil.getParentOfType(child.getPsi(), PyStatement.class); return psi instanceof PyIfStatement || @@ -540,7 +540,7 @@ public class PyBlock implements ASTBlock { psi instanceof PyWhileStatement; } - private static boolean isSubscriptionOperand(ASTNode child) { + private static boolean isSubscriptionOperand(@NotNull ASTNode child) { return child.getTreeParent().getElementType() == PyElementTypes.SUBSCRIPTION_EXPRESSION && child.getPsi() == ((PySubscriptionExpression)child.getTreeParent().getPsi()).getOperand(); } @@ -562,7 +562,7 @@ public class PyBlock implements ASTBlock { return null; } - private boolean isSliceOperand(ASTNode child) { + private boolean isSliceOperand(@NotNull ASTNode child) { if (myNode.getPsi() instanceof PySliceExpression) { final PySliceExpression sliceExpression = (PySliceExpression)myNode.getPsi(); final PyExpression operand = sliceExpression.getOperand(); @@ -571,7 +571,7 @@ public class PyBlock implements ASTBlock { return false; } - private static boolean isAfterStatementList(ASTNode child) { + private static boolean isAfterStatementList(@NotNull ASTNode child) { final PsiElement prev = child.getPsi().getPrevSibling(); if (!(prev instanceof PyStatement)) { return false; @@ -580,7 +580,7 @@ public class PyBlock implements ASTBlock { return lastChild.getParent() instanceof PyStatementList; } - private boolean needListAlignment(ASTNode child) { + private boolean needListAlignment(@NotNull ASTNode child) { final IElementType childType = child.getElementType(); if (PyTokenTypes.OPEN_BRACES.contains(childType)) { return false; @@ -616,7 +616,7 @@ public class PyBlock implements ASTBlock { } @Nullable - private static ASTNode findPrevNonSpaceNode(ASTNode node) { + private static ASTNode findPrevNonSpaceNode(@NotNull ASTNode node) { do { node = node.getTreePrev(); } @@ -671,37 +671,28 @@ public class PyBlock implements ASTBlock { return false; } - private void dumpSubBlocks() { - System.out.println("Subblocks of " + myNode.getPsi() + ":"); - for (Block block : mySubBlocks) { - if (block instanceof PyBlock) { - System.out.println(" " + ((PyBlock)block).getNode().getPsi().toString() + " " + block.getTextRange().getStartOffset() + ":" + block - .getTextRange().getLength()); - } - else { - System.out.println(" "); - } - } - } - + @Override @Nullable public Wrap getWrap() { return myWrap; } + @Override @Nullable public Indent getIndent() { assert myIndent != null; return myIndent; } + @Override @Nullable public Alignment getAlignment() { return myAlignment; } + @Override @Nullable - public Spacing getSpacing(Block child1, @NotNull Block child2) { + public Spacing getSpacing(@Nullable Block child1, @NotNull Block child2) { if (child1 instanceof ASTBlock && child2 instanceof ASTBlock) { final ASTNode node1 = ((ASTBlock)child1).getNode(); ASTNode node2 = ((ASTBlock)child2).getNode(); @@ -764,7 +755,8 @@ public class PyBlock implements ASTBlock { return myContext.getSpacingBuilder().getSpacing(this, child1, child2); } - private Spacing getBlankLinesForOption(final int option) { + @NotNull + private Spacing getBlankLinesForOption(int option) { final int blankLines = option + 1; return Spacing.createSpacing(0, 0, blankLines, myContext.getSettings().KEEP_LINE_BREAKS, @@ -781,6 +773,7 @@ public class PyBlock implements ASTBlock { return false; } + @Override @NotNull public ChildAttributes getChildAttributes(int newChildIndex) { int statementListsBelow = 0; @@ -812,8 +805,8 @@ public class PyBlock implements ASTBlock { // but I don't quite understand why it is necessary and why the formatter // doesn't request childAttributes from the correct block while (lastChild != null) { - final IElementType last_type = lastChild.getElementType(); - if (last_type == PyElementTypes.STATEMENT_LIST && hasLineBreaksBeforeInSameParent(lastChild, 1)) { + final IElementType lastType = lastChild.getElementType(); + if (lastType == PyElementTypes.STATEMENT_LIST && hasLineBreaksBeforeInSameParent(lastChild, 1)) { if (dedentAfterLastStatement((PyStatementList)lastChild.getPsi())) { break; } @@ -856,7 +849,7 @@ public class PyBlock implements ASTBlock { return new ChildAttributes(childIndent, childAlignment); } - private static boolean dedentAfterLastStatement(PyStatementList statementList) { + private static boolean dedentAfterLastStatement(@NotNull PyStatementList statementList) { final PyStatement[] statements = statementList.getStatements(); if (statements.length == 0) { return false; @@ -885,6 +878,7 @@ public class PyBlock implements ASTBlock { return null; } + @NotNull private Indent getChildIndent(int newChildIndex) { final ASTNode afterNode = getAfterNode(newChildIndex); final ASTNode lastChild = getLastNonSpaceChild(myNode, false); @@ -930,12 +924,12 @@ public class PyBlock implements ASTBlock { final PsiDocumentManager docMgr = PsiDocumentManager.getInstance(exprItem.getProject()); final Document doc = docMgr.getDocument(exprItem.getContainingFile()); if (doc != null) { - int line_num = doc.getLineNumber(exprItem.getTextOffset()); - final int item_col = exprItem.getTextOffset() - doc.getLineStartOffset(line_num); - final PsiElement here_elt = getNode().getPsi(); - line_num = doc.getLineNumber(here_elt.getTextOffset()); - final int node_col = here_elt.getTextOffset() - doc.getLineStartOffset(line_num); - final int padding = item_col - node_col; + int lineNum = doc.getLineNumber(exprItem.getTextOffset()); + final int itemCol = exprItem.getTextOffset() - doc.getLineStartOffset(lineNum); + final PsiElement hereElt = getNode().getPsi(); + lineNum = doc.getLineNumber(hereElt.getTextOffset()); + final int nodeCol = hereElt.getTextOffset() - doc.getLineStartOffset(lineNum); + final int padding = itemCol - nodeCol; if (padding > 0) { // negative is a syntax error, but possible return Indent.getSpaceIndent(padding); } @@ -984,7 +978,7 @@ public class PyBlock implements ASTBlock { return getSubBlockByIndex(prevIndex).getNode(); } - private static ASTNode getLastNonSpaceChild(ASTNode node, boolean acceptError) { + private static ASTNode getLastNonSpaceChild(@NotNull ASTNode node, boolean acceptError) { ASTNode lastChild = node.getLastChildNode(); while (lastChild != null && (lastChild.getElementType() == TokenType.WHITE_SPACE || (!acceptError && lastChild.getPsi() instanceof PsiErrorElement))) { @@ -993,6 +987,7 @@ public class PyBlock implements ASTBlock { return lastChild; } + @Override public boolean isIncomplete() { // if there's something following us, we're not incomplete if (!PsiTreeUtil.hasErrorElements(myNode.getPsi())) { @@ -1034,7 +1029,7 @@ public class PyBlock implements ASTBlock { return false; } - private static boolean isIncompleteCall(ASTNode node) { + private static boolean isIncompleteCall(@NotNull ASTNode node) { if (node.getElementType() == PyElementTypes.CALL_EXPRESSION) { final PyCallExpression callExpression = (PyCallExpression)node.getPsi(); final PyArgumentList argumentList = callExpression.getArgumentList(); @@ -1045,6 +1040,7 @@ public class PyBlock implements ASTBlock { return false; } + @Override public boolean isLeaf() { return myNode.getFirstChildNode() == null; } From c9a2a6396f42b8740fd8f9e5e87fc30782a9c26f Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Mon, 2 Nov 2015 16:09:29 +0300 Subject: [PATCH 107/124] PY-13304 Always use continuation indent after function arguments It probably conflicts with existing fix for PY-12749. --- .../jetbrains/python/formatter/PyBlock.java | 19 ++----------------- ...estedFunctionCallsInWithStatement_after.py | 2 +- ...hangingIndentInNamedArgumentValue_after.py | 2 +- .../noAlignForMethodArguments_after.py | 2 +- .../formatter/noWrapBeforeParen_after.py | 2 +- .../formatter/setLiteralInArgList_after.py | 4 ++-- ...functionCallWithCommentNotInlined.after.py | 6 +++--- .../com/jetbrains/python/PyIndentTest.java | 3 +-- 8 files changed, 12 insertions(+), 28 deletions(-) diff --git a/python/src/com/jetbrains/python/formatter/PyBlock.java b/python/src/com/jetbrains/python/formatter/PyBlock.java index 55d6eaad1261..9269c742eff3 100644 --- a/python/src/com/jetbrains/python/formatter/PyBlock.java +++ b/python/src/com/jetbrains/python/formatter/PyBlock.java @@ -323,13 +323,8 @@ public class PyBlock implements ASTBlock { if (childType == PyTokenTypes.RPAR) { childIndent = Indent.getNoneIndent(); } - else { - if (parentType == PyElementTypes.PARAMETER_LIST || argumentMayHaveSameIndentAsFollowingStatementList()) { - childIndent = Indent.getContinuationIndent(); - } - else { - childIndent = Indent.getNormalIndent(); - } + else if (childType != PyTokenTypes.LPAR){ + childIndent = Indent.getContinuationIndent(); } } else if (parentType == PyElementTypes.SUBSCRIPTION_EXPRESSION) { @@ -426,16 +421,6 @@ public class PyBlock implements ASTBlock { return node.getPsi() instanceof PySequenceExpression && ((PySequenceExpression)node.getPsi()).isEmpty(); } - private boolean argumentMayHaveSameIndentAsFollowingStatementList() { - // This check is supposed to prevent PEP8's error: Continuation line with the same indent as next logical line - final PsiElement header = getControlStatementHeader(myNode); - if (header instanceof PyStatementListContainer) { - final PyStatementList statementList = ((PyStatementListContainer)header).getStatementList(); - return PyUtil.onSameLine(header, myNode.getPsi()) && !PyUtil.onSameLine(header, statementList); - } - return false; - } - // Check https://www.python.org/dev/peps/pep-0008/#indentation private static boolean hasHangingIndent(@NotNull PsiElement elem) { if (elem instanceof PyCallExpression) { diff --git a/python/testData/formatter/continuationIndentIsNotUsedForNestedFunctionCallsInWithStatement_after.py b/python/testData/formatter/continuationIndentIsNotUsedForNestedFunctionCallsInWithStatement_after.py index c867a3f0451a..9a4e5063b2ab 100644 --- a/python/testData/formatter/continuationIndentIsNotUsedForNestedFunctionCallsInWithStatement_after.py +++ b/python/testData/formatter/continuationIndentIsNotUsedForNestedFunctionCallsInWithStatement_after.py @@ -1,4 +1,4 @@ with raises_assertion( has_string('Missing download_urls: {}, {}'.format( - self.other_download_url, self.another_download_url))): + self.other_download_url, self.another_download_url))): fixture.assert_detail_page_yields_expected() diff --git a/python/testData/formatter/hangingIndentInNamedArgumentValue_after.py b/python/testData/formatter/hangingIndentInNamedArgumentValue_after.py index 4585528e01cd..1102984b4b98 100644 --- a/python/testData/formatter/hangingIndentInNamedArgumentValue_after.py +++ b/python/testData/formatter/hangingIndentInNamedArgumentValue_after.py @@ -1,3 +1,3 @@ funcWithLongName(x=[ ], - y=42) + y=42) diff --git a/python/testData/formatter/noAlignForMethodArguments_after.py b/python/testData/formatter/noAlignForMethodArguments_after.py index 5682f4ca4f45..740f638adf4c 100644 --- a/python/testData/formatter/noAlignForMethodArguments_after.py +++ b/python/testData/formatter/noAlignForMethodArguments_after.py @@ -2,4 +2,4 @@ def long_method_name(bar, baz): pass long_method_name("long string one", - "long string two") + "long string two") diff --git a/python/testData/formatter/noWrapBeforeParen_after.py b/python/testData/formatter/noWrapBeforeParen_after.py index 5ab3054984db..003f387c408c 100644 --- a/python/testData/formatter/noWrapBeforeParen_after.py +++ b/python/testData/formatter/noWrapBeforeParen_after.py @@ -4,4 +4,4 @@ def foo(): if comments: for comment in comments: record += ' \n' + ca + '=' + quoteattr(comment[ca]) + ' ' for ca in comment) + '/>\n' diff --git a/python/testData/formatter/setLiteralInArgList_after.py b/python/testData/formatter/setLiteralInArgList_after.py index 9c2f75d6dca6..48bec3381227 100644 --- a/python/testData/formatter/setLiteralInArgList_after.py +++ b/python/testData/formatter/setLiteralInArgList_after.py @@ -1,3 +1,3 @@ self.assertEqual( - {"000000000000", "111111111111"}, - foo['bar']['baz']) + {"000000000000", "111111111111"}, + foo['bar']['baz']) diff --git a/python/testData/refactoring/introduceVariable/functionCallWithCommentNotInlined.after.py b/python/testData/refactoring/introduceVariable/functionCallWithCommentNotInlined.after.py index 3140c9b2ab96..f73d8462c0c9 100644 --- a/python/testData/refactoring/introduceVariable/functionCallWithCommentNotInlined.after.py +++ b/python/testData/refactoring/introduceVariable/functionCallWithCommentNotInlined.after.py @@ -1,8 +1,8 @@ import subprocess as sp a = sp.check_output( - args=['python', '-c', 'print("Spam")'], - # read errors too - stderr=sp.STDOUT + args=['python', '-c', 'print("Spam")'], + # read errors too + stderr=sp.STDOUT ) print(a) \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/PyIndentTest.java b/python/testSrc/com/jetbrains/python/PyIndentTest.java index 0164e14fc5ce..d6c09b817227 100644 --- a/python/testSrc/com/jetbrains/python/PyIndentTest.java +++ b/python/testSrc/com/jetbrains/python/PyIndentTest.java @@ -16,7 +16,6 @@ package com.jetbrains.python; import com.intellij.openapi.actionSystem.IdeActions; -import com.intellij.openapi.command.CommandProcessor; import com.intellij.psi.codeStyle.CodeStyleSettingsManager; import com.jetbrains.python.fixtures.PyTestCase; @@ -200,7 +199,7 @@ public class PyIndentTest extends PyTestCase { public void testEnterInNonEmptyArgList() { // PY-1947 doTest("Task(params=1)", "Task(\n" + - " params=1)"); + " params=1)"); } public void testEnterInNonClosedArgList() { // PY-4863 From e674879b7feb5c3594c113d2cbd810fe0c8ee987 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Fri, 6 Nov 2015 20:56:09 +0300 Subject: [PATCH 108/124] PY-17094 Quickfix that adds Py3 return type annotation handles compound statements inside function --- .../SpecifyTypeInPy3AnnotationsIntention.java | 42 ++++++++++++------- ...rReturnTypeInPy3AnnotationLocalFunction.py | 4 ++ .../afterReturnTypeInPy3AnnotationNoColon.py | 4 ++ ...eReturnTypeInPy3AnnotationLocalFunction.py | 4 ++ .../beforeReturnTypeInPy3AnnotationNoColon.py | 4 ++ .../python/intentions/PyIntentionTest.java | 9 ++++ 6 files changed, 52 insertions(+), 15 deletions(-) create mode 100644 python/testData/intentions/afterReturnTypeInPy3AnnotationLocalFunction.py create mode 100644 python/testData/intentions/afterReturnTypeInPy3AnnotationNoColon.py create mode 100644 python/testData/intentions/beforeReturnTypeInPy3AnnotationLocalFunction.py create mode 100644 python/testData/intentions/beforeReturnTypeInPy3AnnotationNoColon.py diff --git a/python/src/com/jetbrains/python/codeInsight/intentions/SpecifyTypeInPy3AnnotationsIntention.java b/python/src/com/jetbrains/python/codeInsight/intentions/SpecifyTypeInPy3AnnotationsIntention.java index c6f13a67839f..dd3f1aae4f75 100644 --- a/python/src/com/jetbrains/python/codeInsight/intentions/SpecifyTypeInPy3AnnotationsIntention.java +++ b/python/src/com/jetbrains/python/codeInsight/intentions/SpecifyTypeInPy3AnnotationsIntention.java @@ -17,19 +17,23 @@ package com.jetbrains.python.codeInsight.intentions; import com.intellij.codeInsight.CodeInsightUtilCore; import com.intellij.codeInsight.template.*; +import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.fileEditor.OpenFileDescriptor; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiReference; import com.intellij.util.IncorrectOperationException; import com.jetbrains.python.PyBundle; import com.jetbrains.python.PyNames; +import com.jetbrains.python.PyTokenTypes; import com.jetbrains.python.psi.*; +import com.jetbrains.python.psi.impl.PyPsiUtils; import org.jetbrains.annotations.NotNull; /** @@ -68,7 +72,7 @@ public class SpecifyTypeInPy3AnnotationsIntention extends TypeIntention { annotateParameter(project, editor, parameter); } else { - annotateReturnType(project, elementAt); + annotateReturnType(project, editor.getDocument(), elementAt); } } @@ -99,24 +103,32 @@ public class SpecifyTypeInPy3AnnotationsIntention extends TypeIntention { } } - private void annotateReturnType(Project project, PsiElement resolved) { - final PyElementGenerator elementGenerator = PyElementGenerator.getInstance(project); - + private void annotateReturnType(Project project, Document document, PsiElement resolved) { PyCallable callable = getCallable(resolved); if (callable instanceof PyFunction) { - final String functionSignature = "def " + callable.getName() + callable.getParameterList().getText(); - String functionText = functionSignature + - " -> object:"; - final PyStatementList statementList = ((PyFunction)callable).getStatementList(); - for (PyStatement st : statementList.getStatements()) { - functionText = functionText + "\n\t" + st.getText(); - } - final PyFunction function = elementGenerator.createFromText(LanguageLevel.forElement(callable), PyFunction.class, - functionText); - callable = (PyFunction)callable.replace(function); - callable = CodeInsightUtilCore.forcePsiPostprocessAndRestoreElement(callable); + final String annotationText = " -> " + PyNames.OBJECT; + + final PsiElement prevElem = PyPsiUtils.getPrevNonCommentSibling(((PyFunction)callable).getStatementList(), true); + assert prevElem != null; + final PsiDocumentManager manager = PsiDocumentManager.getInstance(project); + try { + final TextRange range = prevElem.getTextRange(); + manager.doPostponedOperationsAndUnblockDocument(document); + if (prevElem.getNode().getElementType() == PyTokenTypes.COLON) { + document.insertString(range.getStartOffset(), annotationText); + } + else { + document.insertString(range.getEndOffset(), annotationText + ":"); + } + } + finally { + manager.commitDocument(document); + } + + + callable = CodeInsightUtilCore.forcePsiPostprocessAndRestoreElement(callable); final PyAnnotation annotation = ((PyFunction)callable).getAnnotation(); assert annotation != null; final PyExpression annotationValue = annotation.getValue(); diff --git a/python/testData/intentions/afterReturnTypeInPy3AnnotationLocalFunction.py b/python/testData/intentions/afterReturnTypeInPy3AnnotationLocalFunction.py new file mode 100644 index 000000000000..9d433078a827 --- /dev/null +++ b/python/testData/intentions/afterReturnTypeInPy3AnnotationLocalFunction.py @@ -0,0 +1,4 @@ +def foo() -> object: + @decorator + def bar(): + pass \ No newline at end of file diff --git a/python/testData/intentions/afterReturnTypeInPy3AnnotationNoColon.py b/python/testData/intentions/afterReturnTypeInPy3AnnotationNoColon.py new file mode 100644 index 000000000000..9d433078a827 --- /dev/null +++ b/python/testData/intentions/afterReturnTypeInPy3AnnotationNoColon.py @@ -0,0 +1,4 @@ +def foo() -> object: + @decorator + def bar(): + pass \ No newline at end of file diff --git a/python/testData/intentions/beforeReturnTypeInPy3AnnotationLocalFunction.py b/python/testData/intentions/beforeReturnTypeInPy3AnnotationLocalFunction.py new file mode 100644 index 000000000000..e3c6d23b4d68 --- /dev/null +++ b/python/testData/intentions/beforeReturnTypeInPy3AnnotationLocalFunction.py @@ -0,0 +1,4 @@ +def foo(): + @decorator + def bar(): + pass \ No newline at end of file diff --git a/python/testData/intentions/beforeReturnTypeInPy3AnnotationNoColon.py b/python/testData/intentions/beforeReturnTypeInPy3AnnotationNoColon.py new file mode 100644 index 000000000000..2ea3c54799c1 --- /dev/null +++ b/python/testData/intentions/beforeReturnTypeInPy3AnnotationNoColon.py @@ -0,0 +1,4 @@ +def foo() + @decorator + def bar(): + pass \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/intentions/PyIntentionTest.java b/python/testSrc/com/jetbrains/python/intentions/PyIntentionTest.java index 7d23e79313ff..3d218448a462 100644 --- a/python/testSrc/com/jetbrains/python/intentions/PyIntentionTest.java +++ b/python/testSrc/com/jetbrains/python/intentions/PyIntentionTest.java @@ -359,6 +359,15 @@ public class PyIntentionTest extends PyTestCase { public void testReturnTypeInPy3Annotation2() { //PY-8783 doTest(PyBundle.message("INTN.specify.return.type.in.annotation"), LanguageLevel.PYTHON32); } + + // PY-17094 + public void testReturnTypeInPy3AnnotationLocalFunction() { + doTest(PyBundle.message("INTN.specify.return.type.in.annotation"), LanguageLevel.PYTHON32); + } + + public void testReturnTypeInPy3AnnotationNoColon() { + doTest(PyBundle.message("INTN.specify.return.type.in.annotation"), LanguageLevel.PYTHON32); + } public void testTypeAnnotation3() { //PY-7087 doTypeAnnotationTest(); From c5036590077a174c7e53d516875f84e947072251 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Mon, 9 Nov 2015 11:58:20 +0100 Subject: [PATCH 109/124] IDEA-147584 Find dialog:Whole project scope includes library roots that are located under the project directory --- .../src/com/intellij/core/CoreProjectScopeBuilder.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/platform/core-impl/src/com/intellij/core/CoreProjectScopeBuilder.java b/platform/core-impl/src/com/intellij/core/CoreProjectScopeBuilder.java index 3f4c6e647d2c..cef8725406ba 100644 --- a/platform/core-impl/src/com/intellij/core/CoreProjectScopeBuilder.java +++ b/platform/core-impl/src/com/intellij/core/CoreProjectScopeBuilder.java @@ -96,7 +96,10 @@ public class CoreProjectScopeBuilder extends ProjectScopeBuilder { @Override public boolean contains(@NotNull VirtualFile file) { - return myFileIndexFacade.isInContent(file); + return myFileIndexFacade.isInContent(file) && + // skip libraries that can be under our project content (IDEA-147584) + !myFileIndexFacade.isInLibraryClasses(file) && + !myFileIndexFacade.isInLibrarySource(file); } @Override From 9bc4e4846734fdec7c0ad57b3e09d18bbe0c00a4 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Fri, 6 Nov 2015 18:01:58 +0300 Subject: [PATCH 110/124] thread leaks in tests --- .../intellij/psi/PsiConcurrencyStressTest.java | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/java/java-tests/testSrc/com/intellij/psi/PsiConcurrencyStressTest.java b/java/java-tests/testSrc/com/intellij/psi/PsiConcurrencyStressTest.java index 32fed469fecd..5e2f89a10f3c 100644 --- a/java/java-tests/testSrc/com/intellij/psi/PsiConcurrencyStressTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/PsiConcurrencyStressTest.java @@ -38,8 +38,11 @@ import com.intellij.testFramework.PsiTestUtil; import com.intellij.testFramework.SkipSlowTestLocally; import com.intellij.testFramework.Timings; import com.intellij.util.IncorrectOperationException; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; +import java.util.Collections; +import java.util.List; import java.util.Random; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -75,7 +78,7 @@ public class PsiConcurrencyStressTest extends DaemonAnalyzerTestCase { final CountDownLatch reads = new CountDownLatch(numOfThreads); final Random random = new Random(); - for (int i = 0; i < numOfThreads; i++) { + List threads = ContainerUtil.map(Collections.nCopies(numOfThreads, ""), i -> new Thread(() -> { for (int i1 = 0; i1 < readIterations; i1++) { if (myPsiManager == null) return; @@ -86,8 +89,8 @@ public class PsiConcurrencyStressTest extends DaemonAnalyzerTestCase { } reads.countDown(); - }, "stress thread" + i).start(); - } + }, "stress thread" + i)); + threads.forEach(Thread::start); final Document document = documentManager.getDocument(myFile); @@ -107,6 +110,15 @@ public class PsiConcurrencyStressTest extends DaemonAnalyzerTestCase { } assertTrue("Timed out", reads.await(5, TimeUnit.MINUTES)); + ContainerUtil.process(threads, thread -> { + try { + thread.join(); + return true; + } + catch (InterruptedException e) { + throw new RuntimeException(e); + } + }); } private static void mark(final String s) { From d8738eb7c8dc024c7c46f818b10f166f348aba31 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Fri, 6 Nov 2015 18:04:26 +0300 Subject: [PATCH 111/124] cleanup --- .../intellij/compiler/CompilerTestUtil.java | 42 ++++++++++--------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/java/testFramework/src/com/intellij/compiler/CompilerTestUtil.java b/java/testFramework/src/com/intellij/compiler/CompilerTestUtil.java index 011436ce06e2..ff9db05fd70a 100644 --- a/java/testFramework/src/com/intellij/compiler/CompilerTestUtil.java +++ b/java/testFramework/src/com/intellij/compiler/CompilerTestUtil.java @@ -16,7 +16,6 @@ package com.intellij.compiler; import com.intellij.compiler.server.BuildManager; -import com.intellij.openapi.application.AccessToken; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.Result; import com.intellij.openapi.application.WriteAction; @@ -34,6 +33,7 @@ import com.intellij.testFramework.EdtTestUtil; import com.intellij.util.SmartList; import com.intellij.util.ThrowableRunnable; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.TestOnly; import java.util.List; @@ -44,6 +44,7 @@ public class CompilerTestUtil { private CompilerTestUtil() { } + @TestOnly public static void setupJavacForTests(Project project) { CompilerConfigurationImpl compilerConfiguration = (CompilerConfigurationImpl)CompilerConfiguration.getInstance(project); compilerConfiguration.setDefaultCompiler(compilerConfiguration.getJavacCompiler()); @@ -55,6 +56,7 @@ public class CompilerTestUtil { public static void scanSourceRootsToRecompile(Project project) { } + @TestOnly public static void saveApplicationSettings() { EdtTestUtil.runInEdtAndWait(new Runnable() { @Override @@ -65,6 +67,7 @@ public class CompilerTestUtil { }); } + @TestOnly public static void saveApplicationComponent(final Object appComponent) { EdtTestUtil.runInEdtAndWait(new Runnable() { @Override @@ -79,6 +82,7 @@ public class CompilerTestUtil { ServiceKt.getStateStore(ApplicationManager.getApplication()).saveApplicationComponent(appComponent); } + @TestOnly public static void enableExternalCompiler() { final JavaAwareProjectJdkTableImpl table = JavaAwareProjectJdkTableImpl.getInstanceEx(); new WriteAction() { @@ -89,30 +93,30 @@ public class CompilerTestUtil { }.execute(); } + @TestOnly public static void disableExternalCompiler(@NotNull final Project project) { EdtTestUtil.runInEdtAndWait(new ThrowableRunnable() { @Override public void run() throws Throwable { - JavaAwareProjectJdkTableImpl table = JavaAwareProjectJdkTableImpl.getInstanceEx(); - AccessToken token = WriteAction.start(); - try { - Sdk internalJdk = table.getInternalJdk(); - List modulesToRestore = new SmartList(); - for (Module module : ModuleManager.getInstance(project).getModules()) { - Sdk sdk = ModuleRootManager.getInstance(module).getSdk(); - if (sdk != null && sdk.equals(internalJdk)) { - modulesToRestore.add(module); + final JavaAwareProjectJdkTableImpl table = JavaAwareProjectJdkTableImpl.getInstanceEx(); + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + Sdk internalJdk = table.getInternalJdk(); + List modulesToRestore = new SmartList(); + for (Module module : ModuleManager.getInstance(project).getModules()) { + Sdk sdk = ModuleRootManager.getInstance(module).getSdk(); + if (sdk != null && sdk.equals(internalJdk)) { + modulesToRestore.add(module); + } } + table.removeJdk(internalJdk); + for (Module module : modulesToRestore) { + ModuleRootModificationUtil.setModuleSdk(module, internalJdk); + } + BuildManager.getInstance().clearState(project); } - table.removeJdk(internalJdk); - for (Module module : modulesToRestore) { - ModuleRootModificationUtil.setModuleSdk(module, internalJdk); - } - BuildManager.getInstance().clearState(project); - } - finally { - token.finish(); - } + }); } }); } From be9e1fcba78dac8c9fb39df89c0105a2a2ceca99 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Fri, 6 Nov 2015 18:05:09 +0300 Subject: [PATCH 112/124] thread leaks --- .../util/xml/DomConcurrencyStressTest.java | 51 +++++++++++++------ 1 file changed, 35 insertions(+), 16 deletions(-) diff --git a/xml/dom-tests/tests/com/intellij/util/xml/DomConcurrencyStressTest.java b/xml/dom-tests/tests/com/intellij/util/xml/DomConcurrencyStressTest.java index c625a6a2070a..82f2f804c5c8 100644 --- a/xml/dom-tests/tests/com/intellij/util/xml/DomConcurrencyStressTest.java +++ b/xml/dom-tests/tests/com/intellij/util/xml/DomConcurrencyStressTest.java @@ -27,7 +27,10 @@ import com.intellij.psi.xml.XmlTag; import com.intellij.semantic.SemService; import com.intellij.testFramework.PlatformTestUtil; import com.intellij.testFramework.Timings; +import com.intellij.util.Function; +import com.intellij.util.Processor; import com.intellij.util.TimeoutUtil; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.xml.impl.DomFileElementImpl; import com.intellij.util.xml.impl.DomTestCase; import com.intellij.util.xml.reflect.DomExtender; @@ -35,6 +38,7 @@ import com.intellij.util.xml.reflect.DomExtenderEP; import com.intellij.util.xml.reflect.DomExtensionsRegistrar; import org.jetbrains.annotations.NotNull; +import java.util.Collections; import java.util.List; import java.util.Random; import java.util.concurrent.CountDownLatch; @@ -115,27 +119,42 @@ public class DomConcurrencyStressTest extends DomTestCase { for (int i=0; i exc = Ref.create(null); - final CountDownLatch reads = new CountDownLatch(8); - for (int j = 0; j < 8; j++) { - new Thread("dom concurrency"){ - @Override - public void run() { - try { - runnable.run(); + int N = 8; + final CountDownLatch reads = new CountDownLatch(N); + List threads = ContainerUtil.map(Collections.nCopies(N, ""), new Function() { + @Override + public Thread fun(String s) { + return new Thread("dom concurrency") { + @Override + public void run() { + try { + runnable.run(); + } + catch (Throwable e) { + exc.set(e); + } + finally { + reads.countDown(); + } } - catch (Throwable e) { - exc.set(e); - } - finally { - reads.countDown(); - } - } - }.start(); - } + }; + } + }); + ContainerUtil.process(threads, new Processor() { + @Override + public boolean process(Thread thread) { + thread.start(); + return true; + } + }); + reads.await(); if (!exc.isNull()) { throw exc.get(); } + for (Thread thread : threads) { + thread.join(); + } } } From 71eddca87402158bf376ab973eac02528af6ed32 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Fri, 6 Nov 2015 18:06:42 +0300 Subject: [PATCH 113/124] thread leaks --- .../testSrc/com/intellij/openapi/util/io/IoTestUtil.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/platform/util/testSrc/com/intellij/openapi/util/io/IoTestUtil.java b/platform/util/testSrc/com/intellij/openapi/util/io/IoTestUtil.java index 1e6e6deb03c8..ebc96ce401fd 100644 --- a/platform/util/testSrc/com/intellij/openapi/util/io/IoTestUtil.java +++ b/platform/util/testSrc/com/intellij/openapi/util/io/IoTestUtil.java @@ -208,7 +208,7 @@ public class IoTestUtil { private static int runCommand(final ProcessBuilder command) throws IOException, InterruptedException { command.redirectErrorStream(true); final Process process = command.start(); - new Thread(new Runnable() { + Thread thread = new Thread(new Runnable() { @Override public void run() { try { @@ -228,8 +228,11 @@ public class IoTestUtil { throw new RuntimeException(e); } } - },"io test").start(); - return process.waitFor(); + }, "io test"); + thread.start(); + int ret = process.waitFor(); + thread.join(); + return ret; } public static void assertTimestampsEqual(final long expected, final long actual) { From 61b352e94fada71b895e9b2d11ac8c9a1497c61f Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Mon, 9 Nov 2015 13:45:21 +0300 Subject: [PATCH 114/124] review cleanup --- platform/util/src/com/intellij/openapi/util/Disposer.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/platform/util/src/com/intellij/openapi/util/Disposer.java b/platform/util/src/com/intellij/openapi/util/Disposer.java index 4d597880f38d..5d9b94244bf6 100644 --- a/platform/util/src/com/intellij/openapi/util/Disposer.java +++ b/platform/util/src/com/intellij/openapi/util/Disposer.java @@ -132,7 +132,9 @@ public class Disposer { return ourDebugMode && ourTree.isEmpty(); } - // returns old value + /** + * @return old value + */ public static boolean setDebugMode(final boolean debugMode) { boolean oldValue = ourDebugMode; ourDebugMode = debugMode; From bc39c5d4029183b25cd4df801729174f254c347f Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Mon, 9 Nov 2015 13:53:58 +0300 Subject: [PATCH 115/124] thread leaks --- .../vcs/LocalChangesUnderRootsTest.java | 31 +++++++++++++++---- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/LocalChangesUnderRootsTest.java b/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/LocalChangesUnderRootsTest.java index 1ad2f8453f71..14d1d817b737 100644 --- a/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/LocalChangesUnderRootsTest.java +++ b/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/LocalChangesUnderRootsTest.java @@ -1,11 +1,26 @@ +/* + * 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 com.intellij.openapi.vcs; import com.intellij.openapi.util.Pair; import com.intellij.openapi.vcs.changes.Change; import com.intellij.openapi.vcs.changes.ChangeListManager; +import com.intellij.openapi.vcs.changes.ChangeListManagerImpl; import com.intellij.openapi.vcs.changes.ContentRevision; import com.intellij.openapi.vcs.changes.committed.MockAbstractVcs; -import com.intellij.testFramework.vcs.MockContentRevision; import com.intellij.openapi.vcs.changes.ui.ChangesComparator; import com.intellij.openapi.vcs.history.VcsRevisionNumber; import com.intellij.openapi.vcs.impl.LocalChangesUnderRoots; @@ -15,9 +30,8 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.testFramework.PlatformTestCase; import com.intellij.testFramework.VfsTestUtil; import com.intellij.testFramework.vcs.MockChangeListManager; +import com.intellij.testFramework.vcs.MockContentRevision; import com.intellij.vcsUtil.VcsUtil; -import org.junit.Before; -import org.junit.Test; import java.lang.reflect.Field; import java.util.*; @@ -31,7 +45,7 @@ public class LocalChangesUnderRootsTest extends PlatformTestCase { private MockChangeListManager myChangeListManager; private VirtualFile myBaseDir; - @Before + @Override protected void setUp() throws Exception { super.setUp(); @@ -43,6 +57,12 @@ public class LocalChangesUnderRootsTest extends PlatformTestCase { substituteChangeListManager(); } + @Override + protected void tearDown() throws Exception { + ((ChangeListManagerImpl) ChangeListManager.getInstance(myProject)).stopEveryThingIfInTestMode(); + super.tearDown(); + } + // This is not good, but declaring MockChangeListManager might break other tests private void substituteChangeListManager() throws NoSuchFieldException, IllegalAccessException { Field myChangeManager = LocalChangesUnderRoots.class.getDeclaredField("myChangeManager"); @@ -50,7 +70,6 @@ public class LocalChangesUnderRootsTest extends PlatformTestCase { myChangeManager.set(myLocalChangesUnderRoots, myChangeListManager); } - @Test public void testChangesInTwoGitRoots() { AllVcsesI myVcses = AllVcses.getInstance(myProject); myVcses.registerManually(new MockAbstractVcs(myProject, "Mock")); @@ -67,7 +86,7 @@ public class LocalChangesUnderRootsTest extends PlatformTestCase { Map> expected = new HashMap>(); expected.put(roots.get(0), Arrays.asList(changeBeforeCommunity, changeAfterCommunity)); - expected.put(roots.get(1), Arrays.asList(changeInCommunity)); + expected.put(roots.get(1), Collections.singletonList(changeInCommunity)); Map> changesUnderRoots = myLocalChangesUnderRoots.getChangesUnderRoots(roots); assertEqualMaps(expected, changesUnderRoots); From 4424c6b82a201fcf13d26ef7ba004cfe0919be4e Mon Sep 17 00:00:00 2001 From: Dmitry Trofimov Date: Thu, 5 Nov 2015 16:07:59 +0300 Subject: [PATCH 116/124] Run configuration environment variables should override auto configured ones (PY-17100) --- .../python/run/PythonCommandLineState.java | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/python/src/com/jetbrains/python/run/PythonCommandLineState.java b/python/src/com/jetbrains/python/run/PythonCommandLineState.java index 67b17b143a56..419bd0c65acd 100644 --- a/python/src/com/jetbrains/python/run/PythonCommandLineState.java +++ b/python/src/com/jetbrains/python/run/PythonCommandLineState.java @@ -16,6 +16,7 @@ package com.jetbrains.python.run; import com.google.common.collect.Lists; +import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.intellij.execution.DefaultExecutionResult; import com.intellij.execution.ExecutionException; @@ -51,7 +52,6 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.encoding.EncodingProjectManager; import com.intellij.remote.RemoteProcessControl; import com.intellij.util.PlatformUtils; -import com.intellij.util.containers.HashMap; import com.jetbrains.python.console.PyDebugConsoleBuilder; import com.jetbrains.python.debugger.PyDebugRunner; import com.jetbrains.python.debugger.PyDebuggerOptionsProvider; @@ -278,16 +278,14 @@ public abstract class PythonCommandLineState extends CommandLineState { } protected static void initEnvironment(Project project, GeneralCommandLine commandLine, PythonRunParams myConfig) { - Map env = myConfig.getEnvs(); - if (env == null) { - env = new HashMap(); - } - else { - env = new HashMap(env); - } + Map env = Maps.newHashMap(); setupEncodingEnvs(env, commandLine.getCharset()); + if (myConfig.getEnvs() != null) { + env.putAll(myConfig.getEnvs()); + } + addCommonEnvironmentVariables(env); commandLine.getEnvironment().clear(); From 050a823fbb95ba013bb515e43d20f36d59d69b46 Mon Sep 17 00:00:00 2001 From: "Vladislav.Soroka" Date: Mon, 9 Nov 2015 14:43:18 +0300 Subject: [PATCH 117/124] IDEA-147482 Notification running tests via gradle contains incorrect results --- .../test/runner/events/AfterTestEvent.java | 34 +++++++++++++++---- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/execution/test/runner/events/AfterTestEvent.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/execution/test/runner/events/AfterTestEvent.java index 6909af18b8c4..2123586e9fa8 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/execution/test/runner/events/AfterTestEvent.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/execution/test/runner/events/AfterTestEvent.java @@ -23,6 +23,7 @@ import com.intellij.util.ObjectUtils; import org.jetbrains.plugins.gradle.execution.test.runner.GradleTestsExecutionConsole; import org.jetbrains.plugins.gradle.util.XmlXpathHelper; +import java.util.ArrayList; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -54,14 +55,14 @@ public class AfterTestEvent extends AbstractTestEvent { catch (NumberFormatException ignored) { } + final CompositeRunnable runInEdt = new CompositeRunnable(); final TestEventResult result = getTestEventResultType(eventXml); switch (result) { case SUCCESS: - addToInvokeLater(new Runnable() { + runInEdt.add(new Runnable() { @Override public void run() { testProxy.setFinished(); - getResultsViewer().onTestFinished(testProxy); } }); break; @@ -102,7 +103,7 @@ public class AfterTestEvent extends AbstractTestEvent { } final Couple finalComparisonPair = comparisonPair; - addToInvokeLater(new Runnable() { + runInEdt.add(new Runnable() { @Override public void run() { if (finalComparisonPair != null) { @@ -111,9 +112,10 @@ public class AfterTestEvent extends AbstractTestEvent { else { testProxy.setTestFailed(exceptionMsg, stackTrace, "error".equals(failureType)); } - }}); + } + }); } - addToInvokeLater(new Runnable() { + runInEdt.add(new Runnable() { @Override public void run() { getResultsViewer().onTestFailed(testProxy); @@ -121,10 +123,10 @@ public class AfterTestEvent extends AbstractTestEvent { }); break; case SKIPPED: - testProxy.setTestIgnored(null, null); - addToInvokeLater(new Runnable() { + runInEdt.add(new Runnable() { @Override public void run() { + testProxy.setTestIgnored(null, null); getResultsViewer().onTestIgnored(testProxy); } }); @@ -132,6 +134,15 @@ public class AfterTestEvent extends AbstractTestEvent { case UNKNOWN_RESULT: break; } + + runInEdt.add(new Runnable() { + @Override + public void run() { + getResultsViewer().onTestFinished(testProxy); + } + }); + + addToInvokeLater(runInEdt); } private static Couple parseComparisonMessage(String message, final String regex) { @@ -141,4 +152,13 @@ public class AfterTestEvent extends AbstractTestEvent { } return null; } + + private static class CompositeRunnable extends ArrayList implements Runnable { + @Override + public void run() { + for (Runnable runnable : this) { + runnable.run(); + } + } + } } From 035ee662b854128c6435a94768977c34cfea5866 Mon Sep 17 00:00:00 2001 From: Sergey Simonchik Date: Mon, 9 Nov 2015 15:22:46 +0300 Subject: [PATCH 118/124] macros: fix ignoreCase comparison; add more tests --- .../ide/macro/FileDirPathFromParentMacro.java | 4 +-- .../intellij/ide/macro/MacroManagerTest.java | 26 +++++++++++++++---- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/macro/FileDirPathFromParentMacro.java b/platform/lang-impl/src/com/intellij/ide/macro/FileDirPathFromParentMacro.java index faee0d18ab2f..c7a70bf1a4cb 100644 --- a/platform/lang-impl/src/com/intellij/ide/macro/FileDirPathFromParentMacro.java +++ b/platform/lang-impl/src/com/intellij/ide/macro/FileDirPathFromParentMacro.java @@ -65,7 +65,7 @@ public class FileDirPathFromParentMacro extends Macro { if (ind >= 0) { return surroundedDirPath.substring(ind + surroundedSubDir.length()); } - return dirPath; + return dirPath.endsWith(PATH_DELIMITER) ? dirPath : dirPath + PATH_DELIMITER; } private static int lastIndexOf(@NotNull CharSequence buffer, @NotNull String pattern, int maxIndex, boolean ignoreCase) { @@ -78,7 +78,7 @@ public class FileDirPathFromParentMacro extends Macro { boolean found = true; for (int j = 0; j < patternLength; j++) { if (ignoreCase) { - if (StringUtil.charsEqualIgnoreCase(pattern.charAt(j), buffer.charAt(i + j))) { + if (!StringUtil.charsEqualIgnoreCase(pattern.charAt(j), buffer.charAt(i + j))) { found = false; break; } diff --git a/platform/lang-impl/testSources/com/intellij/ide/macro/MacroManagerTest.java b/platform/lang-impl/testSources/com/intellij/ide/macro/MacroManagerTest.java index 1e75aa12409e..316b9eb1f187 100644 --- a/platform/lang-impl/testSources/com/intellij/ide/macro/MacroManagerTest.java +++ b/platform/lang-impl/testSources/com/intellij/ide/macro/MacroManagerTest.java @@ -20,6 +20,7 @@ import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.actionSystem.impl.SimpleDataContext; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiFile; import com.intellij.testFramework.fixtures.CodeInsightFixtureTestCase; @@ -37,7 +38,7 @@ public class MacroManagerTest extends CodeInsightFixtureTestCase { public DataContext getContext(VirtualFile file) { Project project = myFixture.getProject(); - Map dataId2data = new THashMap(); + Map dataId2data = new THashMap<>(); dataId2data.put(CommonDataKeys.PROJECT.getName(), project); dataId2data.put(CommonDataKeys.VIRTUAL_FILE.getName(), file); dataId2data.put(PlatformDataKeys.PROJECT_FILE_DIRECTORY.getName(), project.getBaseDir()); @@ -50,13 +51,28 @@ public class MacroManagerTest extends CodeInsightFixtureTestCase { "ans: $FileParentDir(bar)$ ", "ans: " + myFixture.getTempDirPath() + File.separator + "foo " ); - } - - public void testFileDirPathFromParentMacro() throws Throwable { doTest( - "foo/bar/baz/test.txt", + "foo/bar/baz/test2.txt", "ans: $FileDirPathFromParent(bar)$ ", "ans: baz/ " ); + doTest( + "foo/bar/baz/test3.txt", + "ans: $FileDirPathFromParent(foo/bar)$ ", + "ans: baz/ " + ); + doTest( + "foo/bar/baz/test4.txt", + "ans: $FileDirPathFromParent(foo/bar/baz/)$ ", + "ans: " + ); + } + + public void testFileDirPathFromParentMacro_NoParentFound() throws Throwable { + PsiFile file = myFixture.addFileToProject("foo/bar/baz/test.txt", ""); + String args = "ans: $FileDirPathFromParent(qqq/)$ "; + String actual = MacroManager.getInstance().expandMacrosInString(args, false, getContext(file.getVirtualFile())); + String expected = "ans: " + StringUtil.trimEnd(file.getVirtualFile().getParent().getPath(), "/") + "/ "; + assertEquals(expected, actual); } } From 7a106036a322e02bbe8df411b4c2d2b14d48054c Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Mon, 9 Nov 2015 13:46:35 +0100 Subject: [PATCH 119/124] [test framework] bare test fixture extended --- .../intellij/testFramework/fixtures/BareTestFixture.java | 6 +++++- .../testFramework/fixtures/BareTestFixtureTestCase.java | 6 ++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/platform/testFramework/src/com/intellij/testFramework/fixtures/BareTestFixture.java b/platform/testFramework/src/com/intellij/testFramework/fixtures/BareTestFixture.java index 5c944017eccc..04c6fa4bda7d 100644 --- a/platform/testFramework/src/com/intellij/testFramework/fixtures/BareTestFixture.java +++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/BareTestFixture.java @@ -15,7 +15,11 @@ */ package com.intellij.testFramework.fixtures; +import com.intellij.openapi.Disposable; + /** * A fixture which provides only {@link com.intellij.openapi.application.Application application} and app-level components. */ -public interface BareTestFixture extends IdeaTestFixture { } \ No newline at end of file +public interface BareTestFixture extends IdeaTestFixture { + Disposable getTestRootDisposable(); +} \ No newline at end of file diff --git a/platform/testFramework/src/com/intellij/testFramework/fixtures/BareTestFixtureTestCase.java b/platform/testFramework/src/com/intellij/testFramework/fixtures/BareTestFixtureTestCase.java index aa43d7db999d..25212b12b2d8 100644 --- a/platform/testFramework/src/com/intellij/testFramework/fixtures/BareTestFixtureTestCase.java +++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/BareTestFixtureTestCase.java @@ -15,6 +15,7 @@ */ package com.intellij.testFramework.fixtures; +import com.intellij.openapi.Disposable; import com.intellij.testFramework.PlatformTestUtil; import org.jetbrains.annotations.NotNull; import org.junit.After; @@ -43,4 +44,9 @@ public abstract class BareTestFixtureTestCase { protected final String getTestName(boolean lowercaseFirstLetter) { return PlatformTestUtil.getTestName(myNameRule.getMethodName(), lowercaseFirstLetter); } + + @NotNull + public final Disposable getTestRootDisposable() { + return myFixture.getTestRootDisposable(); + } } \ No newline at end of file From a6bf2c11ed2d4be70d6b3033a884fb30b945099e Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Mon, 9 Nov 2015 15:48:55 +0300 Subject: [PATCH 120/124] consistent coordinate calculations for editor.new.rendering --- .../intellij/openapi/editor/actions/EditorActionUtil.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/EditorActionUtil.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/EditorActionUtil.java index c7947de91e53..6829bd8a09a1 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/EditorActionUtil.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/EditorActionUtil.java @@ -451,12 +451,14 @@ public class EditorActionUtil { int logLineEndOffset = document.getLineEndOffset(logLine); LogicalPosition logLineStart = editor.offsetToLogicalPosition(logLineStartOffset); VisualPosition visLineStart = editor.logicalToVisualPosition(logLineStart); + boolean newRendering = editor instanceof EditorImpl && ((EditorImpl)editor).myUseNewRendering; boolean softWrapIntroducedLine = visLineStart.line != visualLineNumber; if (!softWrapIntroducedLine) { int offset = findFirstNonSpaceOffsetInRange(document.getCharsSequence(), logLineStartOffset, logLineEndOffset); if (offset >= 0) { - return EditorUtil.calcColumnNumber(editor, document.getCharsSequence(), logLineStartOffset, offset); + return newRendering ? editor.offsetToVisualPosition(offset).column : + EditorUtil.calcColumnNumber(editor, document.getCharsSequence(), logLineStartOffset, offset); } else { return -1; @@ -491,6 +493,7 @@ public class EditorActionUtil { int end = findFirstNonSpaceOffsetInRange(softWrapText, j, softWrapTextLength); if (end >= 0) { + assert !newRendering : "Unexpected soft wrap text"; // Non space symbol is contained at soft wrap text after offset that corresponds to the target visual line start. if (nextSoftWrapLineFeedOffset < 0 || end < nextSoftWrapLineFeedOffset) { return EditorUtil.calcColumnNumber(editor, softWrapText, j, end); @@ -507,7 +510,8 @@ public class EditorActionUtil { } int end = findFirstNonSpaceOffsetInRange(document.getCharsSequence(), softWrap.getStart(), logLineEndOffset); if (end >= 0) { - return EditorUtil.calcColumnNumber(editor, document.getCharsSequence(), softWrap.getStart(), end); + return newRendering ? editor.offsetToVisualPosition(end).column : + EditorUtil.calcColumnNumber(editor, document.getCharsSequence(), softWrap.getStart(), end); } else { return -1; From 749aeb1138b0fd22a153ce0001bc6f88b4e45b03 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Mon, 9 Nov 2015 16:00:03 +0300 Subject: [PATCH 121/124] introduce timeout for hanging highlighting tests --- .../codeInsight/daemon/impl/DaemonCodeAnalyzerImpl.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonCodeAnalyzerImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonCodeAnalyzerImpl.java index f6b857334c01..1e3ee7746669 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonCodeAnalyzerImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonCodeAnalyzerImpl.java @@ -27,6 +27,7 @@ import com.intellij.codeInsight.daemon.ReferenceImporter; import com.intellij.codeInsight.hint.HintManager; import com.intellij.codeInsight.intention.impl.FileLevelIntentionComponent; import com.intellij.codeInsight.intention.impl.IntentionHintComponent; +import com.intellij.diagnostic.ThreadDumper; import com.intellij.ide.PowerSaveMode; import com.intellij.lang.annotation.HighlightSeverity; import com.intellij.openapi.Disposable; @@ -343,7 +344,8 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzerEx implements Pers final DaemonProgressIndicator progress = createUpdateProgress(); myPassExecutorService.submitPasses(map, progress); try { - while (progress.isRunning()) { + long start = System.currentTimeMillis(); + while (progress.isRunning() && System.currentTimeMillis() < start + 5*60*1000) { wrap(new ThrowableRunnable() { @Override public void run() throws Throwable { @@ -358,6 +360,9 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzerEx implements Pers } }); } + if (progress.isRunning()) { + throw new RuntimeException("Highlighting still running after "+(System.currentTimeMillis()-start)/1000+" seconds.\n"+ ThreadDumper.dumpThreadsToString()); + } final HighlightingSessionImpl session = (HighlightingSessionImpl)HighlightingSessionImpl.getOrCreateHighlightingSession(file, textEditors.get(0).getEditor(), progress, null); From f0eb6d989c787b9ae0f6d49a48e49851fe2eb13d Mon Sep 17 00:00:00 2001 From: Philipp Smorygo Date: Mon, 9 Nov 2015 16:04:20 +0300 Subject: [PATCH 122/124] OC-9697 Include ObjC symbols into search everywhere fix duplication, add custom renderer --- .../DefaultSearchEverywhereClassifier.java | 9 +++ .../ide/actions/SearchEverywhereAction.java | 68 ++++++++++++------- .../actions/SearchEverywhereClassifier.java | 15 ++++ 3 files changed, 66 insertions(+), 26 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/actions/DefaultSearchEverywhereClassifier.java b/platform/lang-impl/src/com/intellij/ide/actions/DefaultSearchEverywhereClassifier.java index f77d294d1aaa..2556599838f6 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/DefaultSearchEverywhereClassifier.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/DefaultSearchEverywhereClassifier.java @@ -22,6 +22,9 @@ import com.intellij.psi.PsiFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import javax.swing.*; +import java.awt.*; + public class DefaultSearchEverywhereClassifier implements SearchEverywhereClassifier { @Override public boolean isClass(@Nullable Object o) { @@ -47,4 +50,10 @@ public class DefaultSearchEverywhereClassifier implements SearchEverywhereClassi } return null; } + + @Nullable + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + return null; + } } diff --git a/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java b/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java index 5899bf88f37a..d6118511a107 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java @@ -1107,23 +1107,29 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA Matcher matcher = NameUtil.buildMatcher(pattern, 0, true, true); if (isMoreItem(index)) { cmp = More.get(isSelected); - } else if (value instanceof VirtualFile - && myProject != null - && ((((VirtualFile)value).isDirectory() && (file = PsiManager.getInstance(myProject).findDirectory((VirtualFile)value)) != null ) - || (file = PsiManager.getInstance(myProject).findFile((VirtualFile)value)) != null)) { - myFileRenderer.setPatternMatcher(matcher); - cmp = myFileRenderer.getListCellRendererComponent(list, file, index, isSelected, cellHasFocus); - } else if (value instanceof PsiElement) { - myFileRenderer.setPatternMatcher(matcher); - cmp = myFileRenderer.getListCellRendererComponent(list, value, index, isSelected, isSelected); - } else if (value instanceof GotoActionModel.ActionWrapper) { - cmp = myActionsRenderer.getListCellRendererComponent(list, new GotoActionModel.MatchedValue(((GotoActionModel.ActionWrapper)value), pattern), index, isSelected, isSelected); } else { - cmp = super.getListCellRendererComponent(list, value, index, isSelected, isSelected); - final JPanel p = new JPanel(new BorderLayout()); - p.setBackground(UIUtil.getListBackground(isSelected)); - p.add(cmp, BorderLayout.CENTER); - cmp = p; + cmp = SearchEverywhereClassifier.EP_Manager.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + } + + if (cmp == null) { + if (value instanceof VirtualFile + && myProject != null + && ((((VirtualFile)value).isDirectory() && (file = PsiManager.getInstance(myProject).findDirectory((VirtualFile)value)) != null) + || (file = PsiManager.getInstance(myProject).findFile((VirtualFile)value)) != null)) { + myFileRenderer.setPatternMatcher(matcher); + cmp = myFileRenderer.getListCellRendererComponent(list, file, index, isSelected, cellHasFocus); + } else if (value instanceof PsiElement) { + myFileRenderer.setPatternMatcher(matcher); + cmp = myFileRenderer.getListCellRendererComponent(list, value, index, isSelected, isSelected); + } else if (value instanceof GotoActionModel.ActionWrapper) { + cmp = myActionsRenderer.getListCellRendererComponent(list, new GotoActionModel.MatchedValue(((GotoActionModel.ActionWrapper)value), pattern), index, isSelected, isSelected); + } else { + cmp = super.getListCellRendererComponent(list, value, index, isSelected, isSelected); + final JPanel p = new JPanel(new BorderLayout()); + p.setBackground(UIUtil.getListBackground(isSelected)); + p.add(cmp, BorderLayout.CENTER); + cmp = p; + } } if (myLocationString != null || value instanceof BooleanOptionDescription) { final JPanel panel = new JPanel(new BorderLayout()); @@ -1739,13 +1745,18 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA @Override public boolean process(Object o) { if (SearchEverywhereClassifier.EP_Manager.isSymbol(o) && !myListModel.contains(o) && !symbols.contains(o)) { + PsiElement element = null; + if (o instanceof PsiElement) { + element = (PsiElement)o; + } + else if (o instanceof PsiElementNavigationItem) { + element = ((PsiElementNavigationItem)o).getTargetElement(); + } VirtualFile virtualFile = SearchEverywhereClassifier.EP_Manager.getVirtualFile(o); //some elements are non-physical like DB columns - if (o instanceof PsiElementNavigationItem) { - o = ((PsiElementNavigationItem)o).getTargetElement(); - } - if ((o instanceof PsiElement && ((PsiElement)o).getContainingFile() == null) || - (virtualFile != null && (includeLibs || scope.accept(virtualFile)))) { + boolean isElementWithoutFile = element != null && element.getContainingFile() == null; + boolean isFileInScope = virtualFile != null && (includeLibs || scope.accept(virtualFile)); + if (isElementWithoutFile || isFileInScope) { symbols.add(o); } } @@ -1775,13 +1786,18 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA classes.needMore = true; return false; } + + PsiElement element = null; + if (o instanceof PsiElement) { + element = (PsiElement)o; + } + else if (o instanceof PsiElementNavigationItem) { + element = ((PsiElementNavigationItem)o).getTargetElement(); + } classes.add(o); - if (o instanceof PsiElementNavigationItem) { - o = ((PsiElementNavigationItem)o).getTargetElement(); - } - if (o instanceof PsiNamedElement) { - final String name = ((PsiNamedElement)o).getName(); + if (element instanceof PsiNamedElement) { + final String name = ((PsiNamedElement)element).getName(); VirtualFile virtualFile = SearchEverywhereClassifier.EP_Manager.getVirtualFile(o); if (virtualFile != null) { if (StringUtil.equals(name, virtualFile.getNameWithoutExtension())) { diff --git a/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereClassifier.java b/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereClassifier.java index df01b72c04f5..7b9936f46166 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereClassifier.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereClassifier.java @@ -21,6 +21,9 @@ import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import javax.swing.*; +import java.awt.*; + /** * @author Philipp Smorygo */ @@ -50,6 +53,15 @@ public interface SearchEverywhereClassifier { } return null; } + + @Nullable + public static Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { + for (SearchEverywhereClassifier classifier : Extensions.getExtensions(SearchEverywhereClassifier.EP_NAME)) { + Component component = classifier.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + if (component != null) return component; + } + return null; + } } ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.searchEverywhereClassifier"); @@ -60,4 +72,7 @@ public interface SearchEverywhereClassifier { @Nullable VirtualFile getVirtualFile(@NotNull Object o); + + @Nullable + Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus); } From 57071f66475c70149ae5b79d3dac42cba531050c Mon Sep 17 00:00:00 2001 From: nik Date: Mon, 9 Nov 2015 16:19:08 +0300 Subject: [PATCH 123/124] readme updated: IDEA 15.0 is now required to develop IDEA project --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d0527fe4a451..bb90aa7591a1 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # IntelliJ IDEA Community Edition ### Building and Running from the IDE -To develop IntelliJ IDEA, you can use either IntelliJ IDEA Community Edition or IntelliJ IDEA Ultimate not older than 14.1.5. To build and run the code: +To develop IntelliJ IDEA, you can use either IntelliJ IDEA Community Edition or IntelliJ IDEA Ultimate not older than 15.0. To build and run the code: * Run **getPlugins.sh** / **getPlugins.bat** from the project root directory to check out additional modules. * If this git repository is not on 'master' branch you need to checkout the same branches/tags in android and android/tools-base git repositories. * Open the project. From ec1f3730071b3af221894718b9d61cbf16b020a6 Mon Sep 17 00:00:00 2001 From: Sergey Ignatov Date: Mon, 9 Nov 2015 14:25:06 +0100 Subject: [PATCH 124/124] rename on IDEA-CR-6432 --- plugins/devkit/src/inspections/StatefulEpInspection.java | 2 +- plugins/devkit/src/util/ExtensionPointLocator.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/devkit/src/inspections/StatefulEpInspection.java b/plugins/devkit/src/inspections/StatefulEpInspection.java index ee97296bf201..5b102c4fd4e7 100644 --- a/plugins/devkit/src/inspections/StatefulEpInspection.java +++ b/plugins/devkit/src/inspections/StatefulEpInspection.java @@ -38,7 +38,7 @@ public class StatefulEpInspection extends DevKitInspectionBase { if (fields.length == 0) return super.checkClass(psiClass, manager, isOnTheFly); final boolean isQuickFix = InheritanceUtil.isInheritor(psiClass, LocalQuickFix.class.getCanonicalName()); final boolean isProjectComponent = InheritanceUtil.isInheritor(psiClass, ProjectComponent.class.getCanonicalName()); - if (isQuickFix || ExtensionPointLocator.isImplementedEp(psiClass)) { + if (isQuickFix || ExtensionPointLocator.isRegisteredExtension(psiClass)) { List result = ContainerUtil.newArrayList(); for (final PsiField field : fields) { for (Class c : new Class[]{PsiElement.class, PsiReference.class, Project.class}) { diff --git a/plugins/devkit/src/util/ExtensionPointLocator.java b/plugins/devkit/src/util/ExtensionPointLocator.java index 4f7beac31eda..34ba0c37cf2f 100644 --- a/plugins/devkit/src/util/ExtensionPointLocator.java +++ b/plugins/devkit/src/util/ExtensionPointLocator.java @@ -92,7 +92,7 @@ public class ExtensionPointLocator { return GlobalSearchScope.filesScope(project, candidates); } - public static boolean isImplementedEp(@NotNull PsiClass psiClass) { + public static boolean isRegisteredExtension(@NotNull PsiClass psiClass) { String name = psiClass.getQualifiedName(); if (name == null) return false;