From 0dbb20d42b61f1d74b25767f6b43c8624a9a82fa Mon Sep 17 00:00:00 2001 From: Vasily Pisar Date: Tue, 19 Jan 2016 09:00:35 +0300 Subject: [PATCH 001/107] CPP-3088 Kill CMake processes when exiting IDE - minor helper method --- .../intellij/execution/process/ProcessOutput.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/platform/platform-api/src/com/intellij/execution/process/ProcessOutput.java b/platform/platform-api/src/com/intellij/execution/process/ProcessOutput.java index 552474500c86..3f7fd0924943 100644 --- a/platform/platform-api/src/com/intellij/execution/process/ProcessOutput.java +++ b/platform/platform-api/src/com/intellij/execution/process/ProcessOutput.java @@ -26,6 +26,8 @@ import java.util.List; * @author yole */ public class ProcessOutput { + private static final int ERROR_EXIT_CODE = -1; + private final StringBuilder myStdoutBuilder = new StringBuilder(); private final StringBuilder myStderrBuilder = new StringBuilder(); private int myExitCode; @@ -33,7 +35,7 @@ public class ProcessOutput { private boolean myCancelled; public ProcessOutput() { - myExitCode = -1; // until set explicitly, exit code denotes an error. + myExitCode = ERROR_EXIT_CODE; // until set explicitly, exit code denotes an error. } public ProcessOutput(final int exitCode) { @@ -107,6 +109,14 @@ public class ProcessOutput { return myExitCode; } + /** + * @return true if exit code wasn't set and is still set to default value (this might happen, + * for example, when our CapturingProcessHandler.runProcess() is interrupted) + */ + public boolean hasErrorExitCode() { + return getExitCode() == ERROR_EXIT_CODE; + } + public void setTimeout() { myTimeout = true; } From a02562cadb6b77d6cf8939419b6cf692eca8bf8b Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Sat, 18 Jun 2016 21:13:20 +0200 Subject: [PATCH 002/107] IG: fix "'if' statement with identical branches" false positive --- .../IfStatementWithIdenticalBranchesInspection.java | 8 +++++--- .../IfStatementWithIdenticalBranches.java | 10 ++++++++++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/IfStatementWithIdenticalBranchesInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/IfStatementWithIdenticalBranchesInspection.java index 132d88cfd5e8..814fee1e2edb 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/IfStatementWithIdenticalBranchesInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/IfStatementWithIdenticalBranchesInspection.java @@ -174,8 +174,8 @@ public class IfStatementWithIdenticalBranchesInspection @Override public void visitIfStatement(@NotNull PsiIfStatement ifStatement) { super.visitIfStatement(ifStatement); - final PsiStatement elseBranch = unwrap(ifStatement.getElseBranch()); - final PsiStatement thenBranch = unwrap(ifStatement.getThenBranch()); + final PsiStatement elseBranch = ifStatement.getElseBranch(); + final PsiStatement thenBranch = ifStatement.getThenBranch(); if (thenBranch == null) { return; } @@ -194,7 +194,9 @@ public class IfStatementWithIdenticalBranchesInspection } } - private boolean isDuplicate(@NotNull PsiElement element1, @NotNull PsiElement element2) { + private boolean isDuplicate(@NotNull PsiStatement element1, @NotNull PsiStatement element2) { + element1 = unwrap(element1); + element2 = unwrap(element2); final InputVariables inputVariables = new InputVariables(Collections.emptyList(), element1.getProject(), new LocalSearchScope(element1), false); final DuplicatesFinder finder = new DuplicatesFinder(new PsiElement[]{element1}, inputVariables, null, Collections.emptyList()); diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/if_statement_with_identical_branches/IfStatementWithIdenticalBranches.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/if_statement_with_identical_branches/IfStatementWithIdenticalBranches.java index 4c57ca5c142d..89b141cfdf73 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/if_statement_with_identical_branches/IfStatementWithIdenticalBranches.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/if_statement_with_identical_branches/IfStatementWithIdenticalBranches.java @@ -214,4 +214,14 @@ class NotADup { private Object bar(Object x) { return null; } + + void nesting(int i, int j) { + if (i == 2) { + System.out.println("2"); + } else { + if (j == 2) { + System.out.println("2"); + } + } + } } From 78b84acd0f9d568692accf93181c9ad191b917b8 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Mon, 20 Jun 2016 17:08:20 +0200 Subject: [PATCH 003/107] consider local variables with or without final modifier equal in duplicates finder --- .../util/duplicates/DuplicatesFinder.java | 37 +++++++++++++++++++ .../LocalVariableAnnotationsOrder.java | 13 +++++++ .../LocalVariableAnnotationsOrder_after.java | 16 ++++++++ .../LocalVariableModifierList.java | 11 ++++++ .../LocalVariableModifierList_after.java | 14 +++++++ .../extractMethod/MethodAnnotations.java | 21 +++++++++++ .../MethodAnnotations_after.java | 20 ++++++++++ .../refactoring/ExtractMethodTest.java | 12 ++++++ 8 files changed, 144 insertions(+) create mode 100644 java/java-tests/testData/refactoring/extractMethod/LocalVariableAnnotationsOrder.java create mode 100644 java/java-tests/testData/refactoring/extractMethod/LocalVariableAnnotationsOrder_after.java create mode 100644 java/java-tests/testData/refactoring/extractMethod/LocalVariableModifierList.java create mode 100644 java/java-tests/testData/refactoring/extractMethod/LocalVariableModifierList_after.java create mode 100644 java/java-tests/testData/refactoring/extractMethod/MethodAnnotations.java create mode 100644 java/java-tests/testData/refactoring/extractMethod/MethodAnnotations_after.java diff --git a/java/java-analysis-impl/src/com/intellij/refactoring/util/duplicates/DuplicatesFinder.java b/java/java-analysis-impl/src/com/intellij/refactoring/util/duplicates/DuplicatesFinder.java index 1da4eb7fd6b8..2a7b7963145b 100644 --- a/java/java-analysis-impl/src/com/intellij/refactoring/util/duplicates/DuplicatesFinder.java +++ b/java/java-analysis-impl/src/com/intellij/refactoring/util/duplicates/DuplicatesFinder.java @@ -30,6 +30,7 @@ import com.intellij.refactoring.extractMethod.InputVariables; import com.intellij.refactoring.util.RefactoringChangeUtil; import com.intellij.util.ArrayUtil; import com.intellij.util.IncorrectOperationException; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.IntArrayList; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -518,6 +519,8 @@ public class DuplicatesFinder { final PsiJavaCodeReferenceElement candidateQualifier = ((PsiSuperExpression)candidate).getQualifier(); return contextClass == (candidateQualifier != null ? candidateQualifier.resolve() : PsiTreeUtil.getContextOfType(candidate, PsiClass.class)); } + } else if (pattern instanceof PsiModifierList) { + return candidate instanceof PsiModifierList && matchModifierList((PsiModifierList)pattern, (PsiModifierList)candidate); } PsiElement[] children1 = getFilteredChildren(pattern); @@ -541,6 +544,40 @@ public class DuplicatesFinder { return true; } + private static boolean matchModifierList(PsiModifierList modifierList1, PsiModifierList modifierList2) { + if (!(modifierList1.getParent() instanceof PsiLocalVariable)) { + // local variables can only have a final modifier, and are considered equivalent with or without it. + for (String modifier : PsiModifier.MODIFIERS) { + if (modifierList1.hasModifierProperty(modifier)) { + if (!modifierList2.hasModifierProperty(modifier)) { + return false; + } + } + else if (modifierList2.hasModifierProperty(modifier)) { + return false; + } + } + } + final List annotations1 = ContainerUtil.newArrayList(modifierList1.getAnnotations()); + final List annotations2 = ContainerUtil.newArrayList(modifierList2.getAnnotations()); + annotations1.removeIf(a -> CommonClassNames.JAVA_LANG_OVERRIDE.equals(a.getQualifiedName())); + annotations2.removeIf(a -> CommonClassNames.JAVA_LANG_OVERRIDE.equals(a.getQualifiedName())); + if (annotations1.size() != annotations2.size()) { + return false; + } + for (final Iterator iterator = annotations1.iterator(); iterator.hasNext(); ) { + final PsiAnnotation annotation1 = iterator.next(); + for (final Iterator iterator2 = annotations2.iterator(); iterator2.hasNext(); ) { + final PsiAnnotation annotation2 = iterator2.next(); + if (PsiEquivalenceUtil.areElementsEquivalent(annotation1, annotation2)) { + iterator.remove(); + iterator2.remove(); + } + } + } + return true; + } + private static boolean checkParameterModification(PsiExpression expression, final IElementType sign, PsiExpression candidate) { diff --git a/java/java-tests/testData/refactoring/extractMethod/LocalVariableAnnotationsOrder.java b/java/java-tests/testData/refactoring/extractMethod/LocalVariableAnnotationsOrder.java new file mode 100644 index 000000000000..7fa69c17de76 --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethod/LocalVariableAnnotationsOrder.java @@ -0,0 +1,13 @@ +class C { + { + @B @A int i = 0; + System.out.println(i); + } + + void f() { + @A @B int j = 0; + System.out.println(j); + } +} +@interface A {} +@interface B {} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractMethod/LocalVariableAnnotationsOrder_after.java b/java/java-tests/testData/refactoring/extractMethod/LocalVariableAnnotationsOrder_after.java new file mode 100644 index 000000000000..54630c858b1d --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethod/LocalVariableAnnotationsOrder_after.java @@ -0,0 +1,16 @@ +class C { + { + newMethod(); + } + + void f() { + newMethod(); + } + + private void newMethod() { + @A @B int j = 0; + System.out.println(j); + } +} +@interface A {} +@interface B {} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractMethod/LocalVariableModifierList.java b/java/java-tests/testData/refactoring/extractMethod/LocalVariableModifierList.java new file mode 100644 index 000000000000..d9d2f99e4e0b --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethod/LocalVariableModifierList.java @@ -0,0 +1,11 @@ +class C { + { + int i = 0; + System.out.println(i); + } + + void f() { + final int j = 0; + System.out.println(j); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractMethod/LocalVariableModifierList_after.java b/java/java-tests/testData/refactoring/extractMethod/LocalVariableModifierList_after.java new file mode 100644 index 000000000000..e6792368059f --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethod/LocalVariableModifierList_after.java @@ -0,0 +1,14 @@ +class C { + { + newMethod(); + } + + void f() { + newMethod(); + } + + private void newMethod() { + final int j = 0; + System.out.println(j); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractMethod/MethodAnnotations.java b/java/java-tests/testData/refactoring/extractMethod/MethodAnnotations.java new file mode 100644 index 000000000000..a21035126650 --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethod/MethodAnnotations.java @@ -0,0 +1,21 @@ +class Test10 { + void test() { + new Super() { + int get() { + return 0; + } + }; + + new Super() { + @Override + int get() { + return 0; + } + }; + } +} +class Super { + int get() { + return 1; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/extractMethod/MethodAnnotations_after.java b/java/java-tests/testData/refactoring/extractMethod/MethodAnnotations_after.java new file mode 100644 index 000000000000..1c7baecdfe26 --- /dev/null +++ b/java/java-tests/testData/refactoring/extractMethod/MethodAnnotations_after.java @@ -0,0 +1,20 @@ +class Test10 { + void test() { + newMethod(); + + newMethod(); + } + + private void newMethod() { + new Super() { + int get() { + return 0; + } + }; + } +} +class Super { + int get() { + return 1; + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodTest.java b/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodTest.java index bfe820f7197f..a84f0d143dab 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/ExtractMethodTest.java @@ -805,6 +805,18 @@ public class ExtractMethodTest extends LightCodeInsightTestCase { doTest(); } + public void testLocalVariableModifierList() throws Exception { + doTest(); + } + + public void testLocalVariableAnnotationsOrder() throws Exception { + doTest(); + } + + public void testMethodAnnotations() throws Exception { + doTest(); + } + public void testQualifyWhenConflictingNamePresent() throws Exception { final CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject()); settings.ELSE_ON_NEW_LINE = true; From 368aa2f5ca942720b271fba394eb48a635e3e8d0 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Thu, 23 Jun 2016 14:43:21 +0200 Subject: [PATCH 004/107] IDEA-96532 (Orders in Severities Editor and in Severity Chooser are opposite) --- .../codeInspection/ui/LevelChooserAction.java | 22 ++++++++----------- .../ui/filter/InspectionFilterAction.java | 5 ++--- .../ui/table/SeverityRenderer.java | 7 +++--- 3 files changed, 14 insertions(+), 20 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/LevelChooserAction.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/LevelChooserAction.java index 660d7b4fb1b2..0920f870d296 100644 --- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/LevelChooserAction.java +++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/LevelChooserAction.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,7 +19,6 @@ import com.intellij.codeHighlighting.HighlightDisplayLevel; import com.intellij.codeInsight.daemon.impl.HighlightInfoType; import com.intellij.codeInsight.daemon.impl.SeverityRegistrar; import com.intellij.codeInsight.daemon.impl.SeverityUtil; -import com.intellij.codeInspection.ex.InspectionProfileImpl; import com.intellij.codeInspection.ex.SeverityEditorDialog; import com.intellij.lang.annotation.HighlightSeverity; import com.intellij.openapi.actionSystem.AnActionEvent; @@ -28,13 +27,13 @@ import com.intellij.openapi.actionSystem.Presentation; import com.intellij.openapi.actionSystem.ex.ComboBoxAction; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.DumbAwareAction; -import com.intellij.profile.codeInspection.SeverityProvider; import com.intellij.profile.codeInspection.ui.table.SeverityRenderer; import org.jetbrains.annotations.NotNull; import javax.swing.*; -import java.util.SortedSet; -import java.util.TreeSet; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; /** * @author Dmitry Batkovich @@ -83,23 +82,20 @@ public abstract class LevelChooserAction extends ComboBoxAction implements DumbA return group; } - public static SortedSet getSeverities(final SeverityRegistrar severityRegistrar) { + public static List getSeverities(final SeverityRegistrar severityRegistrar) { return getSeverities(severityRegistrar, true); } - public static SortedSet getSeverities(final SeverityRegistrar severityRegistrar, - boolean includeDoNotShow) { - final SortedSet severities = new TreeSet(severityRegistrar); + public static List getSeverities(final SeverityRegistrar severityRegistrar, + boolean includeDoNotShow) { + final List severities = new ArrayList(); for (final SeverityRegistrar.SeverityBasedTextAttributes type : SeverityUtil.getRegisteredHighlightingInfoTypes(severityRegistrar)) { severities.add(type.getSeverity()); } - severities.add(HighlightSeverity.ERROR); - severities.add(HighlightSeverity.WARNING); - severities.add(HighlightSeverity.WEAK_WARNING); - severities.add(HighlightSeverity.GENERIC_SERVER_ERROR_OR_WARNING); if (includeDoNotShow) { severities.add(HighlightSeverity.INFORMATION); } + Collections.sort(severities, (a, b) -> -severityRegistrar.compare(a, b)); return severities; } diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/filter/InspectionFilterAction.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/filter/InspectionFilterAction.java index 9db40ed9ea99..d17160502620 100644 --- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/filter/InspectionFilterAction.java +++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/filter/InspectionFilterAction.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -82,8 +82,7 @@ public class InspectionFilterAction extends DefaultActionGroup implements Toggle addAction(new ShowOnlyModifiedInspectionsAction()); addSeparator(); - final SortedSet severities = LevelChooserAction.getSeverities(mySeverityRegistrar); - for (final HighlightSeverity severity : severities) { + for (final HighlightSeverity severity : LevelChooserAction.getSeverities(mySeverityRegistrar)) { add(new ShowWithSpecifiedSeverityInspectionsAction(severity)); } addSeparator(); diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/SeverityRenderer.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/SeverityRenderer.java index 5db2970d8d9f..b8fea3dec0f6 100644 --- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/SeverityRenderer.java +++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/table/SeverityRenderer.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,7 +23,6 @@ import com.intellij.openapi.ui.popup.LightweightWindowEvent; import com.intellij.profile.codeInspection.SeverityProvider; import com.intellij.profile.codeInspection.ui.LevelChooserAction; import com.intellij.profile.codeInspection.ui.SingleInspectionProfilePanel; -import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.ColorIcon; import com.intellij.util.ui.UIUtil; @@ -33,7 +32,7 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.event.MouseEvent; import java.util.EventObject; -import java.util.SortedSet; +import java.util.List; /** * @author Dmitry Batkovich @@ -49,7 +48,7 @@ public class SeverityRenderer extends ComboBoxTableRenderer { } public static SeverityRenderer create(final InspectionProfileImpl inspectionProfile, @Nullable final Runnable onClose) { - final SortedSet severities = + final List severities = LevelChooserAction.getSeverities(((SeverityProvider)inspectionProfile.getProfileManager()).getOwnSeverityRegistrar()); return new SeverityRenderer(ContainerUtil.map2Array(severities, new SeverityState[severities.size()], severity -> new SeverityState(severity, true, false)), onClose); } From 9d1b98f640bc7e3485315b2d24ab06e69541b14c Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Thu, 23 Jun 2016 14:43:59 +0200 Subject: [PATCH 005/107] render severities in editor the same as in the profile panel --- .../intellij/codeInspection/ex/SeverityEditorDialog.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/SeverityEditorDialog.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/SeverityEditorDialog.java index 43a7e4df55e7..443b9e60fa3a 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ex/SeverityEditorDialog.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/SeverityEditorDialog.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2015 JetBrains s.r.o. + * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -42,6 +42,7 @@ import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.InputValidator; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.*; import com.intellij.ui.components.JBList; import org.jdom.Element; @@ -91,7 +92,8 @@ public class SeverityEditorDialog extends DialogWrapper { public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { final Component rendererComponent = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); if (value instanceof SeverityBasedTextAttributes) { - setText(((SeverityBasedTextAttributes)value).getSeverity().getName()); + final HighlightSeverity severity = ((SeverityBasedTextAttributes)value).getSeverity(); + setText(StringUtil.capitalizeWords(severity.getName().toLowerCase(), true)); } return rendererComponent; } @@ -124,7 +126,7 @@ public class SeverityEditorDialog extends DialogWrapper { final ListModel listModel = myOptionsList.getModel(); for (int i = 0; i < listModel.getSize(); i++) { final String severityName = ((SeverityBasedTextAttributes)listModel.getElementAt(i)).getSeverity().myName; - if (Comparing.strEqual(severityName, inputString)) return false; + if (Comparing.strEqual(severityName, inputString, false)) return false; } return true; } From 687ee936bb7e5cedc8eb3b54bf59c75a3753313b Mon Sep 17 00:00:00 2001 From: nik Date: Thu, 23 Jun 2016 16:00:01 +0300 Subject: [PATCH 006/107] fixed showing 'Convert Project' dialog when opening a project in old format (IDEA-157691) --- .../project/impl/ProjectManagerImpl.java | 70 ++++++++++--------- 1 file changed, 37 insertions(+), 33 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java index 1899bb294b43..0cc2487e0846 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java @@ -384,19 +384,31 @@ public class ProjectManagerImpl extends ProjectManagerEx implements Disposable { } @Override - public Project loadAndOpenProject(@NotNull final String filePath) throws IOException { - Project project = myProgressManager.run(new Task.WithResult(null, ProjectBundle.message("project.load.progress"), true) { - @Override - protected Project compute(@NotNull ProgressIndicator indicator) throws IOException { - final Project project = convertAndLoadProject(filePath); - if (project == null) { - return null; + public Project loadAndOpenProject(@NotNull final String originalFilePath) throws IOException { + final String filePath = toCanonicalName(originalFilePath); + final ConversionResult conversionResult = ConversionService.getInstance().convert(filePath); + Project project; + if (conversionResult.openingIsCanceled()) { + project = null; + } + else { + project = myProgressManager.run(new Task.WithResult(null, ProjectBundle.message("project.load.progress"), true) { + @Override + protected Project compute(@NotNull ProgressIndicator indicator) throws IOException { + final Project project = loadProjectWithProgress(filePath); + if (project == null) { + return null; + } + + if (!conversionResult.conversionNotNeeded()) { + StartupManager.getInstance(project).registerPostStartupActivity(() -> conversionResult.postStartupActivity(project)); + } + openProject(project); + return project; } + }); + } - openProject(project); - return project; - } - }); if (project == null) { WelcomeFrame.showIfNoProjectOpened(); return null; @@ -423,20 +435,9 @@ public class ProjectManagerImpl extends ProjectManagerEx implements Disposable { return null; } - final Project project; - try { - project = loadProjectWithProgress(filePath); - if (project == null) return null; - } - catch (ProcessCanceledException e) { - return null; - } - catch (Throwable t) { - LOG.info(t); - throw new IOException(t); - } + final Project project = loadProjectWithProgress(filePath); - if (!conversionResult.conversionNotNeeded()) { + if (project != null && !conversionResult.conversionNotNeeded()) { StartupManager.getInstance(project).registerPostStartupActivity(() -> conversionResult.postStartupActivity(project)); } return project; @@ -449,23 +450,26 @@ public class ProjectManagerImpl extends ProjectManagerEx implements Disposable { * @return the project, or null if the user has cancelled opening the project. */ @Nullable - private Project loadProjectWithProgress(@NotNull final String filePath) { - final ProjectImpl project = createProject(null, toCanonicalName(filePath), false); - if (myProgressManager.getProgressIndicator() != null) { - initProject(project, null); - return project; - } + private Project loadProjectWithProgress(@NotNull String filePath) throws IOException { try { + final ProjectImpl project = createProject(null, toCanonicalName(filePath), false); + if (myProgressManager.getProgressIndicator() != null) { + initProject(project, null); + return project; + } myProgressManager.runProcessWithProgressSynchronously((ThrowableComputable)() -> { initProject(project, null); return project; }, ProjectBundle.message("project.load.progress"), canCancelProjectLoading(), project); + return project; } - catch (ProcessCanceledException ignore) { + catch (ProcessCanceledException e) { return null; } - - return project; + catch (Throwable t) { + LOG.info(t); + throw new IOException(t); + } } private static void notifyProjectOpenFailed() { From 6da337aa6b287603e58e96b9058808c2801dfe22 Mon Sep 17 00:00:00 2001 From: "Ilya.Kazakevich" Date: Thu, 23 Jun 2016 16:32:33 +0300 Subject: [PATCH 007/107] Nullable error fix --- .../python/psi/impl/PyJavaImportCandidateProvider.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/python/pluginJava/com/jetbrains/python/psi/impl/PyJavaImportCandidateProvider.java b/python/pluginJava/com/jetbrains/python/psi/impl/PyJavaImportCandidateProvider.java index a8673fb642c4..90a667299d84 100644 --- a/python/pluginJava/com/jetbrains/python/psi/impl/PyJavaImportCandidateProvider.java +++ b/python/pluginJava/com/jetbrains/python/psi/impl/PyJavaImportCandidateProvider.java @@ -41,7 +41,11 @@ public class PyJavaImportCandidateProvider implements PyImportCandidateProvider PsiShortNamesCache cache = PsiShortNamesCache.getInstance(project); final PsiClass[] classesByName = cache.getClassesByName(name, scope); for (PsiClass psiClass : classesByName) { - final QualifiedName packageQName = QualifiedName.fromDottedString(psiClass.getQualifiedName()).removeLastComponent(); + final String qualifiedName = psiClass.getQualifiedName(); + if (qualifiedName == null) { + continue; + } + final QualifiedName packageQName = QualifiedName.fromDottedString(qualifiedName).removeLastComponent(); quickFix.addImport(psiClass, psiClass.getContainingFile(), packageQName); } } From 65febf2b11ff15b373ebb8bfb7b22815703c7546 Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Thu, 23 Jun 2016 16:55:14 +0300 Subject: [PATCH 008/107] Ignore possible discrepancies between dir(x) and x.__dict__ (PY-19349) --- python/helpers/pycharm_generator_utils/module_redeclarator.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/python/helpers/pycharm_generator_utils/module_redeclarator.py b/python/helpers/pycharm_generator_utils/module_redeclarator.py index a79a91ed4dd3..fd34c3ad7c37 100644 --- a/python/helpers/pycharm_generator_utils/module_redeclarator.py +++ b/python/helpers/pycharm_generator_utils/module_redeclarator.py @@ -684,7 +684,9 @@ class ModuleRedeclarator(object): try: item = getattr(p_class, item_name) # let getters do the magic except AttributeError: - item = field_source[item_name] # have it raw + item = field_source.get(item_name) # have it raw + if item is None: + continue except Exception: continue if is_callable(item) and not isinstance(item, type): From 55faead0d8e6563735d3dc23b6238002ed75f3d9 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Thu, 23 Jun 2016 15:45:03 +0200 Subject: [PATCH 009/107] disable custom frame decoration for IntelliJ laf --- .../src/com/intellij/openapi/wm/impl/IdeRootPane.java | 2 +- 1 file changed, 1 insertion(+), 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 5037e0edc2e8..574524d3f569 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 @@ -89,7 +89,7 @@ public class IdeRootPane extends JRootPane implements UISettingsListener { private boolean myFullScreen; public IdeRootPane(ActionManagerEx actionManager, DataManager dataManager, Application application, final IdeFrame frame) { - if (SystemInfo.isWindows && (UIUtil.isUnderDarcula() || UIUtil.isUnderIntelliJLaF()) && frame instanceof IdeFrameImpl) { + if (SystemInfo.isWindows && (UIUtil.isUnderDarcula() /*|| UIUtil.isUnderIntelliJLaF()*/) && frame instanceof IdeFrameImpl) { //setUI(DarculaRootPaneUI.createUI(this)); setWindowDecorationStyle(FRAME); } From f5938e69737c7d22e5c698e534f6694f88228593 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Thu, 23 Jun 2016 15:46:46 +0200 Subject: [PATCH 010/107] optimize png --- platform/icons/src/icon.png | Bin 2456 -> 1736 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/platform/icons/src/icon.png b/platform/icons/src/icon.png index 5af892c1ec5fe5a7f6281c76866e4eb678f29bd1..78b2f6c13262fa329fa861923fbd700931315a40 100644 GIT binary patch delta 1721 zcmV;q21faq6UYsaBYy^uNkl%p6hy#D#jz%xW~#B29+PF7SOPtW(6D&OLr8gv>%Z?@ z_b$t_sLbrn{ATW+bI<+%&e?Om-4z{)eqUrvzhuokouB+>pMQVCZ(RZFzU~N2JbXP^ zkyjs*npV9q`-QX5zP9kw$n7(aM(-7yjum)glgnX zfjbg8di@h{YyLWP1SFz0FbPe;oAA$*n{hQH6}8d~R6M0lHhti}4k`vN^Aag!u&n3uTz;ga1|aeo`mC$Ln0dhq5XiA9@!gXoXY%ttA-$5bF7Ab`hIKxjASetiP6 z_%98clSwSzREY&Ce}K-uJVglB>Cb(G?`lXS5`P0ifN|SM`WegPPZ>@K6)S|iQiI@E z{)DLCf6XNpO0^%|^VjkP=Zc>kzP`Q&gaG5Vk@Pd3d+BqmTz?K!tPs4p7J-}pLco?f z46aK0*Ho{AMBg@H|C~Y8xZK{>_nZMvqu9rGa4}?qX{0F%@F+{Un}b2rtEFwTu{%=!tW{x&SX3ZXJ==N;-UDJLL1?sY=45A zvKdb(ufsK~_1+3}Pi<{2zte|9xbH#OZ@J0`KAL+AcDY@!<+@c}k6~QYEy~OlS!8f-GCA)9G7QOQ`X-Zk1zw%7~OyxN^XI8>C zvksG})Y=kkw&SVliK*P$Q023s<2Qz8`v`@O*61)wd$(t_R#$p3=0KpafK^d!Q8WEo zMTx8s)QO^)A{53R1c`zEa$P35G`er9@UYm0vQKl457`3WCc5@Pa+!T<*BLloThE6nV`MJhuW}Eb-!Vm zM`?9B3jg%=RUa*7lN81c5un+<%|iFbmfS9mIdD?HAFM?W@p9BO+ljT^Ukai6Wp16Q z>VB7=;bv}(xfM80@G?vMpug0nY+HR?B-VC~rqI2_`4`uneVLu8hZ*}n$_T?gMw~?J$jbWOx%^0C^#&S^K=rm?wFiSI|LCSs-N!b!YTIlfE z3LQ&QeU$AZr6N+OqlG#uWyu*GI^Q3C=e@4?w>;N5LzyBlkQv10;vq9ltq_pSz(f4dWH^~mUSh$s{f`Ad{P znF11c0w#!tT3gZ)2n2|+g(A>4C?whfM8Xkh7~B?yfLp>5SOgr4goCReL=sKFU}3$8 zq}5oG8y*rY67jJxm{=@^icwIWAP9!AwY7!8kuW6EQi8A)Msh{82urTeV9f)ODWnV7 zd=Z<+1y?-M0(s#gJVc`OuM{|ZGWnZhu5h(bl9It9XnYs~3WsqxD|vlI3q@Yczh!(E zE%b@xGhtp#Aun7&m-K^Wutt{D?w@hy!{mxwiFk;_0%fonSTqKXwsAsQ zqma%71j51WcNUC-C9%!q&P+ z3Fe7-!eAaBBoMxK3pDX#a~V9b&~&A|t7@47_5mh?B;awtul2#QzoUWRY-8h$LZHwH zYq&%|+6jSzJ2^YTZHZ_{48h3}vdU$AC-+sZ)&J$fBw}DI&HbNdubCthv~v75x{}Mc z;b(Fs6EBdAw!_O9V*psc(Us`v6ERfb7aHc{tZ9c5&h?LQPUY-zGd+9vh!u|5R^da| z0E1&oF7|7?ChUywRGByu13JL>$@hPPu+!{s$!?V)vEy?{O6N;dlfc1@5W4wE$Rn-S zIozh<7V-3l?#C@n4NW7HG-KNxGpA>wU(^U)|3y%E*mc=2hPq2>{0iw&F^Nqv41;@Q z?>mOw;G*dVfBjbR7roK3Y6D&$fRxY7>MDHZ*Ld*(bd*2&-uLx!!ts)aJMQ(x>C792 z&F8kgpot3|tAoZ0Digf@+NwyjO*+zP@T-?5I8&A;p>;)Z^jFvN?PfqOO~0q|=RT`X zODN@p>pC~wpHHljwv4J~O$=c}TS>p)sA5@g>5aV9w zr+>Kg1_;UJO_qSLz0yAIC(jhMn+Fgnh04j7oj9)tUhag)ZaLNPU+PfYsfF$?rG20_ zy3-@e0vlOh{qjNq&^%-V4#QX$@SgY^Jy^ZOUc7V2#MRW$GZB%$UG>=uozosX{D60@ zR>jU-Av)QmaZvwB2CfJ_+CZ}QO^Pz3HhzR!yBfI}AaZjdgXw6uX4Er`d-ERM`REG{ z$sFJMqhaaZ9T}-#QnU`bZ!Wk#eOuO;c#vDI?Wy*mbFp>oc-Pw>O*okzk)cnd+6#&` zY8B7SM&GcFIRUU-c*&_hS8sAT$|lTh(L=^bF@3%w*rB`Y>$tUr+}F0s=JJU%h&TQf?UBWgR4D znPuPY*DrIBHQOIwyFGe$;)wUu*4oqHDYl@ehUl+;Q$)?SRRz}V(UMEKHNGD8^lT=D zVw$PA@lv__q-uYC`+2+%bD$o2=?&@a{3G(39Dq2VN&4ZEhA*st#x@LKgf2k|3H)mRdMcrQ+X_ z?t{y(%lr=;Vjp)e+`fm5y*p#-8p0j4%1*&oZqpt`l)J6#c(KJZi)sxuF^O$&Cq1ex zgP+6bD!+IixA)1e&nlgsR%~v_eC)&Ki}M_c)bSD#{u%d`SY6*2ga^T z*$AI2ep)(w+Gl8ZnD*q_p*#3YHz&FWJ40$)=i?i*v0GZJ;^^z7RXNn+?Xaqfif*8P zU_gdUCX2J=nBcP{*Ebq=#fplSNzRwCSkGBw)mv1{r>8R6%P}c^dFnaGfRpL6+U)p` zg(Dr~d19%MFW6dDy|mHH{N5(j{WT+>uOy<3&W(v?y881lhes0>Eshc0N_AtG1YKVs zQ>Ifs0XqJ6NL*IcxRD%pxSm6yQVX(&&g>A67OE7t@0*hfwDUp&i7s7(*bm!6lJ2#q zZ9Q97X7Z|SxPjNo(Fd~(^(e;A-OXiUJG0g|6uLRo)zx`FOJvFRG30a7aqli(f!#>Y z!u|B%hZi=H`|KK}l*ZZmm}vHnm?j zND5Z$ZVk^2tbR7~WOab~Dy8LmLf}n86I7)BR!{1gxz+Uz*dL{;QLOUi3SEWz>Ca0Kw^0w^mxlQ| z(-vxSH%jCTC!W5uUflRu7S?it`#^Y5fAJ#gfxZeI7jv`-y#Ki5VW;T1ZG2+y$f1rs zW-bKdx4MT~rg$3m9{b-l-je!tpbv|qYMJcdC**bgHviH0L-w@%`o6Ao$U*ZoMximL z8F!$pZeiRPN8cx|7stPuT{P+3Ev0NIGXBAC%>0+7`=MFd6D`ITvybmzwk#*K>Z%oK eHw-Nl0W!epj<)T>G{e%Bx00)~2eHy=U;LkHkNFz_ From a2b04241250f675d622f8328dd64d5c8618f2e7f Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Thu, 23 Jun 2016 15:48:45 +0200 Subject: [PATCH 011/107] update win frame decoration icons --- platform/icons/src/windows/close.png | Bin 257 -> 0 bytes platform/icons/src/windows/closeActive.png | Bin 0 -> 132 bytes platform/icons/src/windows/closeActive@2x.png | Bin 0 -> 202 bytes .../icons/src/windows/closeActive@2x_dark.png | Bin 0 -> 245 bytes platform/icons/src/windows/closeActive_dark.png | Bin 0 -> 154 bytes platform/icons/src/windows/closeHover.png | Bin 0 -> 154 bytes platform/icons/src/windows/closeHover@2x.png | Bin 0 -> 239 bytes platform/icons/src/windows/closeInactive.png | Bin 0 -> 148 bytes platform/icons/src/windows/closeInactive@2x.png | Bin 0 -> 216 bytes .../icons/src/windows/closeInactive@2x_dark.png | Bin 0 -> 245 bytes .../icons/src/windows/closeInactive_dark.png | Bin 0 -> 154 bytes platform/icons/src/windows/iconify.png | Bin 96 -> 0 bytes platform/icons/src/windows/maximize.png | Bin 161 -> 0 bytes platform/icons/src/windows/maximize@2x.png | Bin 0 -> 109 bytes platform/icons/src/windows/maximize@2x_dark.png | Bin 0 -> 111 bytes platform/icons/src/windows/maximizeInactive.png | Bin 0 -> 91 bytes .../icons/src/windows/maximizeInactive@2x.png | Bin 0 -> 111 bytes .../src/windows/maximizeInactive@2x_dark.png | Bin 0 -> 110 bytes .../icons/src/windows/maximizeInactive_dark.png | Bin 0 -> 90 bytes platform/icons/src/windows/maximize_dark.png | Bin 0 -> 91 bytes platform/icons/src/windows/minimize.png | Bin 196 -> 78 bytes platform/icons/src/windows/minimize@2x.png | Bin 0 -> 94 bytes platform/icons/src/windows/minimize@2x_dark.png | Bin 0 -> 97 bytes platform/icons/src/windows/minimizeInactive.png | Bin 0 -> 83 bytes .../icons/src/windows/minimizeInactive@2x.png | Bin 0 -> 97 bytes .../src/windows/minimizeInactive@2x_dark.png | Bin 0 -> 96 bytes .../icons/src/windows/minimizeInactive_dark.png | Bin 0 -> 82 bytes platform/icons/src/windows/minimize_dark.png | Bin 0 -> 83 bytes platform/icons/src/windows/restore.png | Bin 0 -> 109 bytes platform/icons/src/windows/restore@2x.png | Bin 0 -> 129 bytes platform/icons/src/windows/restore@2x_dark.png | Bin 0 -> 129 bytes platform/icons/src/windows/restoreInactive.png | Bin 0 -> 108 bytes .../icons/src/windows/restoreInactive@2x.png | Bin 0 -> 133 bytes .../src/windows/restoreInactive@2x_dark.png | Bin 0 -> 128 bytes .../icons/src/windows/restoreInactive_dark.png | Bin 0 -> 107 bytes platform/icons/src/windows/restore_dark.png | Bin 0 -> 108 bytes .../util/src/com/intellij/icons/AllIcons.java | 10 +++++++--- 37 files changed, 7 insertions(+), 3 deletions(-) delete mode 100644 platform/icons/src/windows/close.png create mode 100644 platform/icons/src/windows/closeActive.png create mode 100644 platform/icons/src/windows/closeActive@2x.png create mode 100644 platform/icons/src/windows/closeActive@2x_dark.png create mode 100644 platform/icons/src/windows/closeActive_dark.png create mode 100644 platform/icons/src/windows/closeHover.png create mode 100644 platform/icons/src/windows/closeHover@2x.png create mode 100644 platform/icons/src/windows/closeInactive.png create mode 100644 platform/icons/src/windows/closeInactive@2x.png create mode 100644 platform/icons/src/windows/closeInactive@2x_dark.png create mode 100644 platform/icons/src/windows/closeInactive_dark.png delete mode 100644 platform/icons/src/windows/iconify.png delete mode 100644 platform/icons/src/windows/maximize.png create mode 100644 platform/icons/src/windows/maximize@2x.png create mode 100644 platform/icons/src/windows/maximize@2x_dark.png create mode 100644 platform/icons/src/windows/maximizeInactive.png create mode 100644 platform/icons/src/windows/maximizeInactive@2x.png create mode 100644 platform/icons/src/windows/maximizeInactive@2x_dark.png create mode 100644 platform/icons/src/windows/maximizeInactive_dark.png create mode 100644 platform/icons/src/windows/maximize_dark.png create mode 100644 platform/icons/src/windows/minimize@2x.png create mode 100644 platform/icons/src/windows/minimize@2x_dark.png create mode 100644 platform/icons/src/windows/minimizeInactive.png create mode 100644 platform/icons/src/windows/minimizeInactive@2x.png create mode 100644 platform/icons/src/windows/minimizeInactive@2x_dark.png create mode 100644 platform/icons/src/windows/minimizeInactive_dark.png create mode 100644 platform/icons/src/windows/minimize_dark.png create mode 100644 platform/icons/src/windows/restore.png create mode 100644 platform/icons/src/windows/restore@2x.png create mode 100644 platform/icons/src/windows/restore@2x_dark.png create mode 100644 platform/icons/src/windows/restoreInactive.png create mode 100644 platform/icons/src/windows/restoreInactive@2x.png create mode 100644 platform/icons/src/windows/restoreInactive@2x_dark.png create mode 100644 platform/icons/src/windows/restoreInactive_dark.png create mode 100644 platform/icons/src/windows/restore_dark.png diff --git a/platform/icons/src/windows/close.png b/platform/icons/src/windows/close.png deleted file mode 100644 index 4c593adde24b493b73faa14f690568acc6c835f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 257 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Cp=voLn>}1|M>sko>^7G$EN1T z1l|tgMhlJ($&Le49oF>ZFnD~fSE%DV(!^pS?tFEfqZvcW=j0VfOl{gk9IiGLaBpJd z3GluCQKD&$&?J(v2W;bfqXjsdJg9EB<&A&|oOmYH;@0kt)`k0+UP^-|$+qd1W5Mrp>(`rbjsZ6{IF68Lw+F gU6$!2)x^NC=(}|3*|fC_fyOd;y85}Sb4q9e0CuP?#{d8T literal 0 HcmV?d00001 diff --git a/platform/icons/src/windows/closeActive@2x.png b/platform/icons/src/windows/closeActive@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0d27cde74cd9d05ef7484f7e10f73cb4cc688491 GIT binary patch literal 202 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJiJmTwAr-gYPP@o;K!L-xTJrYy zivRy_n~AX|pV_cfbhda+i2rmi=YpLvd%lTGSrlfee?61w07pYaLgelkj?OJ)5YiUjawRD`fF(B z7%_kN@Hvv#@M@ut)Z>U`)UKyL=XHvzO~Mo+y0h;Nq_GqMtDCAqf_QI&880MP(F%W5@xOQC+f-lVM(wXW{+sfA@iwF?hQAxvX|m{BvG^?p?WbNsy-N)@zmgQOwy>x)1(d_Ev_UL5AVT^9TkDW-)n- zSv&8rYcohPT)36aXc2Yt(z+$DXRtHqdRv$4IXW|#WGg!TEmUbpGwihxVO(H&@$8?; z3}4b1?r<)!HLiLk>QH07cE-f10oo_mmUgUaQD*31%ZTjb&b@KBXU$!MHL|B0TV#YU nzM0vfcHD#Qy2})=zi!;`xm9n4`yQ$T`hdaH)z4*}Q$iB}u^d}^ literal 0 HcmV?d00001 diff --git a/platform/icons/src/windows/closeInactive.png b/platform/icons/src/windows/closeInactive.png new file mode 100644 index 0000000000000000000000000000000000000000..a24938407f8341377c5f30f96dd75a2af64945ab GIT binary patch literal 148 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`(Vi}jAr-fh6C~mio}HQbzwrh~ zhh#y*ggf;$Y!YYZ8M9AUEU>I$YuI2Y=A1CA*RjTlZGm*tqL~rQ54I(J7K-I@C^K_A vAY^oa!(Ty4(1=0#zy_8zhHr%~U0`9@$8?S{Ih}I}&>99$S3j3^P6=2 literal 0 HcmV?d00001 diff --git a/platform/icons/src/windows/closeInactive@2x.png b/platform/icons/src/windows/closeInactive@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..4d232434c41b7b275fc3d547cdf8d089f9055bbc GIT binary patch literal 216 zcmV;}04M*6P)gC0dUb`=gWjN0JtPXv!Ve|OhP)Op8}w_ z0-!elH*ECzS0Me8yZ(d{0B8f`kwdtaNoyIktYgwx#~K$AMqWf{x`<4s-)I4(jyNZ< S$G9v20000)UKyL=XHvzO~Mo+y0h;Nq_GqMtDCAqf_QI&880MP(F%WYgr+Ar-fhfBgS%l@k&D= tvm392#D@m;fkHB*#l{TXeVDaw&p8!&gBP-SA=&QJRcZiuwbVk!zSS$z4s&BFVdQ&MBb@0O{=+j{pDw literal 0 HcmV?d00001 diff --git a/platform/icons/src/windows/maximizeInactive@2x.png b/platform/icons/src/windows/maximizeInactive@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..1b8ba51e0556b6a4944bb5669517d4e46a8eca88 GIT binary patch literal 111 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdzGfx-CkcwMxuNm?(81OJ3{E(io zg}2G?tcxAr-fh6C~mmEMNZI-f+eQ oMjnpJW)78&qol`;+0QHI*QUCw| literal 0 HcmV?d00001 diff --git a/platform/icons/src/windows/minimize.png b/platform/icons/src/windows/minimize.png index dc6b39109161e89489e7ab0f1493084f5d20cd04..f21aafd5314b95ee7cc11fda2e60c300de7339b4 100644 GIT binary patch delta 48 zcmX@Y=r=({OVrcFF{I*Fa)JcwVg}(q>O%cZ4_O)BDRF*3@@(^C1|aZs^>bP0l+XkK DpIH%q delta 167 zcmV;Y09gM{!~u{be~U>(K~#9!WBC97KLaJ0fhq<(eE1NA*8%Y^BJo8aev52CEf609 z;uAz*kVOSR`~ca2|3JJ7h-VXlUjp$?Al`&*z!Ru9h{0Vzd;#PYWCNZ7u`H1W%!Ybp z)BrRCo&qr+kp@f!;002ovPDHLkV1fYiK#>3d diff --git a/platform/icons/src/windows/minimize@2x.png b/platform/icons/src/windows/minimize@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..fa32e78f8176f3261167b875d671dd81e37a6e91 GIT binary patch literal 94 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdzRZkbkkcwMx&u!#oVBk2s;opCg sm;=X}HY|PP$-t1d_0C>Kh93(V`IoETRQ)dM0o1_Y>FVdQ&MBb@0Hy#PqW}N^ literal 0 HcmV?d00001 diff --git a/platform/icons/src/windows/minimize@2x_dark.png b/platform/icons/src/windows/minimize@2x_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..f463d2d83d417be80c5baf650a285ac77bc2939a GIT binary patch literal 97 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz4Nn)xkcwMx&u!#oFyLS@{C5Az vauwkviyd!V`Wnv4@L}Q-_1oqQ4CyvXOUeajW^3^R^)Pt4`njxgN@xNA!*(2> literal 0 HcmV?d00001 diff --git a/platform/icons/src/windows/minimizeInactive.png b/platform/icons/src/windows/minimizeInactive.png new file mode 100644 index 0000000000000000000000000000000000000000..49be621e23a8b3ef0a29ebac589c57b6c34e8ff9 GIT binary patch literal 83 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Ql2i3Ar-fh6C_v{Gw`07WBJ+M gu)<_Xn=Au^?0xB{4G(vy16472y85}Sb4q9e0PdF+!2kdN literal 0 HcmV?d00001 diff --git a/platform/icons/src/windows/minimizeInactive@2x.png b/platform/icons/src/windows/minimizeInactive@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..afe98f8b3a4012eb1fa88bdaa2b99e5974a650a9 GIT binary patch literal 97 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz4Nn)xkcwMx&u!#oFyLS@{C5Ar va#i6aiyd!V`Wnv4@L}Q-_1oqQ4Cyx6y!jKEw(m{{>S6G7^>bP0l+XkK%;p_t literal 0 HcmV?d00001 diff --git a/platform/icons/src/windows/minimizeInactive@2x_dark.png b/platform/icons/src/windows/minimizeInactive@2x_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..a4fd6cebfdd00b266da169ffa9ef4a0d307ed65c GIT binary patch literal 96 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdzbx#+^kcwMx&u!#oFyLS@{C54l tkD7;j^M<9b*K;vEQ1bP0l+XkK0z($m literal 0 HcmV?d00001 diff --git a/platform/icons/src/windows/minimize_dark.png b/platform/icons/src/windows/minimize_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..01275e1af39b0eb30b234be617672bcc30707938 GIT binary patch literal 83 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Ql2i3Ar-fh6C_v{Gw`m7+4;%d gu)<_Xn=AvvMjqLt+dcgYfT|cgUHx3vIVCg!0OUgz0ssI2 literal 0 HcmV?d00001 diff --git a/platform/icons/src/windows/restore.png b/platform/icons/src/windows/restore.png new file mode 100644 index 0000000000000000000000000000000000000000..9dcafef6a1a7ee0e4e15ae7a7c7b5fea9baa2c37 GIT binary patch literal 109 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`CY~;iAr-fh6C~mu{Qv(yfhS4m zKnrif#*2n=%p5m;rZE1FVdQ&MBb@0C(#uqyPW_ literal 0 HcmV?d00001 diff --git a/platform/icons/src/windows/restore@2x_dark.png b/platform/icons/src/windows/restore@2x_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..0fa65cd5b7c178247cefa45d43181f93cf8a53ff GIT binary patch literal 129 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz4^J1zkcwMxuWsaJP~c&9e81mw z8IP%lh=5dk{Yl=dooYgYxm_Klk&)UBe9yU0Jo?43Zl4TLA48msa`k~PdAuv+l!F;A Zn)A*OKfTH>>YfWo&ePS;Wt~$(69B-0CjS5c literal 0 HcmV?d00001 diff --git a/platform/icons/src/windows/restoreInactive.png b/platform/icons/src/windows/restoreInactive.png new file mode 100644 index 0000000000000000000000000000000000000000..6e25f284583d5847c4f4f75aba8f5cfcd391ffbc GIT binary patch literal 108 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`#-1*YAr-fh6C~mio}HO#@JC)= z?HU7{jKq4z|C|Yncn)NKUcq?8RoPH4VS$NMd*nBurtGs16lOm^vIMA|!PC{xWt~$( F69Ds2Ay@za literal 0 HcmV?d00001 diff --git a/platform/icons/src/windows/restoreInactive@2x.png b/platform/icons/src/windows/restoreInactive@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..2faaa2b60268a8b40a309884547414550da4af8c GIT binary patch literal 133 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdzA5Ry@kcwMxry6oG7;qeU_uu}* zRxvKUR;TXREu1O*R&!Vwq|fABHQvT`q4S-cuIvP>%GC_9UJQ&Z0v~dEve=JsAG*Z2 g(r}eD!v|jG2@5t<)t%B42Aa#@>FVdQ&MBb@0JB;tod5s; literal 0 HcmV?d00001 diff --git a/platform/icons/src/windows/restoreInactive@2x_dark.png b/platform/icons/src/windows/restoreInactive@2x_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..056a3a5aebc811baacc46248193b33b4701df717 GIT binary patch literal 128 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdzcTX3`kcwMxuPX8}DDbcx{9XU+ z`65L}2gC5P$;K-zopr0QYt%NB{r; literal 0 HcmV?d00001 diff --git a/platform/icons/src/windows/restoreInactive_dark.png b/platform/icons/src/windows/restoreInactive_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..718897b7bdea50382d49c57780a986117909c312 GIT binary patch literal 107 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`MxHK?Ar-fh6C~mmEMLyv_W$wW zBT@$%m>-)yuxIp{!f25zXWFnML**DN&lI=E2B+ Date: Thu, 23 Jun 2016 15:49:35 +0200 Subject: [PATCH 012/107] new icons for close, maximize, minimize --- .../ide/ui/laf/darcula/darcula_windows.properties | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula_windows.properties b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula_windows.properties index e633a34e62ee..e28788497193 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula_windows.properties +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/darcula_windows.properties @@ -9,7 +9,7 @@ InternalFrameUI=com.intellij.ide.ui.laf.darcula.ui.DarculaInternalFrameUI InternalFrame.border=com.intellij.ide.ui.laf.darcula.ui.DarculaInternalBorder RootPaneUI=com.intellij.ide.ui.laf.darcula.ui.DarculaRootPaneUI -InternalFrame.closeIcon=AllIcons.Windows.Close -InternalFrame.iconifyIcon=AllIcons.Windows.Iconify -InternalFrame.maximizeIcon=AllIcons.Windows.Maximize -InternalFrame.minimizeIcon=AllIcons.Windows.Minimize +InternalFrame.closeIcon=AllIcons.Windows.CloseInactive +InternalFrame.iconifyIcon=AllIcons.Windows.MinimizeInactive +InternalFrame.maximizeIcon=AllIcons.Windows.MaximizeInactive +InternalFrame.minimizeIcon=AllIcons.Windows.RestoreInactive From 5039d8f0bc195800b700d4b38b3e503d10a39ac2 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Thu, 23 Jun 2016 15:51:17 +0200 Subject: [PATCH 013/107] better spacing between close, maximize, minimize buttons --- .../ide/ui/laf/darcula/ui/DarculaTitlePane.java | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaTitlePane.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaTitlePane.java index 7b86a9c29738..0f3704882e77 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaTitlePane.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaTitlePane.java @@ -293,7 +293,7 @@ public class DarculaTitlePane extends JComponent { menu.add(myCloseAction); } - private static JButton createButton(String accessibleName, Icon icon, Action action) { + private static JButton createButton(String accessibleName, Icon icon, Action action, boolean isCloseAction) { JButton button = new JButton() { boolean mouseOverButton = false; { @@ -316,6 +316,10 @@ public class DarculaTitlePane extends JComponent { protected void paintComponent(Graphics g) { final Window window = SwingUtilities.windowForComponent(this); float alpha = window.isActive() && mouseOverButton ? 1f : 0.5f; + if (isCloseAction && mouseOverButton) { + g.setColor(Color.red); + g.fillRect(0, 0, getWidth(), getHeight()); + } final GraphicsConfig config = GraphicsUtil.paintWithAlpha(g, alpha); getIcon().paintIcon(this, g, 0, 0); config.restore(); @@ -334,14 +338,14 @@ public class DarculaTitlePane extends JComponent { } private void createButtons() { - myCloseButton = createButton("Close", UIManager.getIcon("InternalFrame.closeIcon"), myCloseAction); + myCloseButton = createButton("Close", UIManager.getIcon("InternalFrame.closeIcon"), myCloseAction, true); if (getWindowDecorationStyle() == JRootPane.FRAME) { myMaximizeIcon = UIManager.getIcon("InternalFrame.maximizeIcon"); myMinimizeIcon = UIManager.getIcon("InternalFrame.minimizeIcon"); - myIconifyButton = createButton("Iconify", UIManager.getIcon("InternalFrame.iconifyIcon"), myIconifyAction); - myToggleButton = createButton("Maximize", myMaximizeIcon, myRestoreAction); + myIconifyButton = createButton("Iconify", UIManager.getIcon("InternalFrame.iconifyIcon"), myIconifyAction, false); + myToggleButton = createButton("Maximize", myMaximizeIcon, myRestoreAction, false); } } @@ -688,12 +692,12 @@ public class DarculaTitlePane extends JComponent { } x = w; - spacing = 8; + spacing = 14; x += -spacing - buttonWidth; if (myCloseButton != null) { myCloseButton.setBounds(x, (h - buttonHeight) / 2, buttonWidth, buttonHeight); } - + spacing = 30; if (getWindowDecorationStyle() == JRootPane.FRAME) { if (Toolkit.getDefaultToolkit().isFrameStateSupported( Frame.MAXIMIZED_BOTH)) { From 2401d62f80861f0b915a0316a754e6e5fcefa59e Mon Sep 17 00:00:00 2001 From: Andrey Vlasovskikh Date: Fri, 20 May 2016 22:51:40 +0300 Subject: [PATCH 014/107] Initial implementation of background caching of packages (PY-18039) --- .../actions/ProjectSpecificSettingsStep.java | 15 +- .../configuration/IpnbConnectionManager.java | 16 +- .../plugins/ipnb/format/IpnbParser.java | 15 +- .../python/packaging/PyPackageManager.java | 27 +-- .../python/packaging/PyPackageManagers.java | 2 +- .../templateLanguages/PyTemplatesUtil.java | 101 ----------- .../PythonTemplateIndentOptionsProvider.java | 50 ------ .../templateLanguages/TemplatesService.java | 4 +- .../com/jetbrains/rest/RestPythonUtil.java | 16 +- .../run/sphinx/SphinxRunConfiguration.java | 10 +- .../com/jetbrains/python/PyBundle.properties | 4 +- .../PyPackageRequirementsInspection.java | 30 +--- .../packaging/PyCondaPackageManagerImpl.java | 7 +- .../packaging/PyPackageManagerImpl.java | 157 +++++++----------- .../packaging/PyPackageManagersImpl.java | 29 ++-- .../python/packaging/PyPackageUtil.java | 36 ++++ .../packaging/PyRemotePackageManagerImpl.java | 1 - .../ui/PyInstalledPackagesPanel.java | 8 +- .../ui/PyPackageManagementService.java | 13 +- .../src/com/jetbrains/python/psi/PyUtil.java | 32 +++- .../python/sdk/PythonSdkUpdater.java | 15 +- .../sdk/skeletons/PySkeletonRefresher.java | 10 -- .../testing/VFSTestFrameworkListener.java | 16 +- .../pytest/PyTestConfigurationProducer.java | 17 +- .../com/jetbrains/env/PyEnvTestCase.java | 3 +- .../jetbrains/env/python/PyPackagingTest.java | 10 +- 26 files changed, 232 insertions(+), 412 deletions(-) delete mode 100644 python/openapi/src/com/jetbrains/python/templateLanguages/PyTemplatesUtil.java delete mode 100644 python/openapi/src/com/jetbrains/python/templateLanguages/PythonTemplateIndentOptionsProvider.java diff --git a/python/ide/src/com/jetbrains/python/newProject/actions/ProjectSpecificSettingsStep.java b/python/ide/src/com/jetbrains/python/newProject/actions/ProjectSpecificSettingsStep.java index 5a34a82f377b..93ee06c1a796 100644 --- a/python/ide/src/com/jetbrains/python/newProject/actions/ProjectSpecificSettingsStep.java +++ b/python/ide/src/com/jetbrains/python/newProject/actions/ProjectSpecificSettingsStep.java @@ -15,7 +15,6 @@ */ package com.jetbrains.python.newProject.actions; -import com.intellij.execution.ExecutionException; import com.intellij.facet.ui.ValidationResult; import com.intellij.ide.util.projectWizard.ProjectSettingsStepBase; import com.intellij.ide.util.projectWizard.WebProjectTemplate; @@ -35,9 +34,8 @@ import com.jetbrains.python.configuration.PyConfigurableInterpreterList; import com.jetbrains.python.configuration.VirtualEnvProjectFilter; import com.jetbrains.python.newProject.PyFrameworkProjectGenerator; import com.jetbrains.python.newProject.PythonProjectGenerator; -import com.jetbrains.python.packaging.PyPackageManager; +import com.jetbrains.python.packaging.PyPackage; import com.jetbrains.python.packaging.PyPackageUtil; -import com.jetbrains.python.sdk.PySdkUtil; import com.jetbrains.python.sdk.PythonSdkType; import icons.PythonIcons; import org.jetbrains.annotations.NotNull; @@ -169,14 +167,11 @@ public class ProjectSpecificSettingsStep extends ProjectSettingsStepBase impleme if (PyPackageUtil.packageManagementEnabled(sdk)) { warningList.add(frameworkName + " will be installed on the selected interpreter"); myInstallFramework = true; - final PyPackageManager packageManager = PyPackageManager.getInstance(sdk); - boolean hasManagement = false; - try { - hasManagement = packageManager.hasManagement(PySdkUtil.isRemote(sdk)); + final List packages = PyPackageUtil.refreshAndGetPackagesModally(sdk); + if (packages == null) { + return false; } - catch (ExecutionException ignored) { - } - if (!hasManagement) { + if (!PyPackageUtil.hasManagement(packages)) { warningList.add("Python packaging tools and " + warningList); } } else { diff --git a/python/ipnb/src/org/jetbrains/plugins/ipnb/configuration/IpnbConnectionManager.java b/python/ipnb/src/org/jetbrains/plugins/ipnb/configuration/IpnbConnectionManager.java index 27be6ff10510..7bba8e8e03a8 100644 --- a/python/ipnb/src/org/jetbrains/plugins/ipnb/configuration/IpnbConnectionManager.java +++ b/python/ipnb/src/org/jetbrains/plugins/ipnb/configuration/IpnbConnectionManager.java @@ -33,6 +33,7 @@ import com.intellij.util.ui.UIUtil; import com.jetbrains.python.PythonHelper; import com.jetbrains.python.packaging.PyPackage; import com.jetbrains.python.packaging.PyPackageManager; +import com.jetbrains.python.packaging.PyPackageUtil; import com.jetbrains.python.sdk.PythonSdkType; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -269,15 +270,12 @@ public final class IpnbConnectionManager implements ProjectComponent { showWarning(fileEditor, "Please check Python Interpreter in Settings->Python Interpreter", null); return false; } - try { - final PyPackage ipythonPackage = PyPackageManager.getInstance(sdk).findPackage("ipython", false); - final PyPackage jupyterPackage = PyPackageManager.getInstance(sdk).findPackage("jupyter", false); - if (ipythonPackage == null && jupyterPackage == null) { - showWarning(fileEditor, "Add Jupyter to the interpreter of the current project.", null); - return false; - } - } - catch (ExecutionException ignored) { + final List packages = PyPackageManager.getInstance(sdk).getPackages(); + final PyPackage ipythonPackage = packages != null ? PyPackageUtil.findPackage(packages, "ipython") : null; + final PyPackage jupyterPackage = packages != null ? PyPackageUtil.findPackage(packages, "jupyter") : null; + if (ipythonPackage == null && jupyterPackage == null) { + showWarning(fileEditor, "Add Jupyter to the interpreter of the current project.", null); + return false; } String url = showDialogUrl(initUrl); diff --git a/python/ipnb/src/org/jetbrains/plugins/ipnb/format/IpnbParser.java b/python/ipnb/src/org/jetbrains/plugins/ipnb/format/IpnbParser.java index e9bc33718e75..1076c0753244 100644 --- a/python/ipnb/src/org/jetbrains/plugins/ipnb/format/IpnbParser.java +++ b/python/ipnb/src/org/jetbrains/plugins/ipnb/format/IpnbParser.java @@ -4,7 +4,6 @@ import com.google.common.collect.Lists; import com.google.gson.*; import com.google.gson.annotations.SerializedName; import com.google.gson.stream.JsonWriter; -import com.intellij.execution.ExecutionException; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.module.Module; @@ -17,6 +16,7 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.text.VersionComparatorUtil; import com.jetbrains.python.packaging.PyPackage; import com.jetbrains.python.packaging.PyPackageManager; +import com.jetbrains.python.packaging.PyPackageUtil; import com.jetbrains.python.sdk.PythonSdkType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -79,14 +79,11 @@ public class IpnbParser { if (module != null) { final Sdk sdk = PythonSdkType.findPythonSdk(module); if (sdk != null) { - try { - final PyPackage ipython = PyPackageManager.getInstance(sdk).findPackage("ipython", true); - final PyPackage jupyter = PyPackageManager.getInstance(sdk).findPackage("jupyter", true); - if (jupyter == null && ipython != null && VersionComparatorUtil.compare(ipython.getVersion(), "3.0") <= 0) { - return false; - } - } - catch (ExecutionException ignored) { + final List packages = PyPackageManager.getInstance(sdk).getPackages(); + final PyPackage ipython = packages != null ? PyPackageUtil.findPackage(packages, "ipython") : null; + final PyPackage jupyter = packages != null ? PyPackageUtil.findPackage(packages, "jupyter") : null; + if (jupyter == null && ipython != null && VersionComparatorUtil.compare(ipython.getVersion(), "3.0") <= 0) { + return false; } } } diff --git a/python/openapi/src/com/jetbrains/python/packaging/PyPackageManager.java b/python/openapi/src/com/jetbrains/python/packaging/PyPackageManager.java index c8b8dd4ab633..a94da215513b 100644 --- a/python/openapi/src/com/jetbrains/python/packaging/PyPackageManager.java +++ b/python/openapi/src/com/jetbrains/python/packaging/PyPackageManager.java @@ -31,19 +31,16 @@ import java.util.Set; public abstract class PyPackageManager { public static final Key RUNNING_PACKAGING_TASKS = Key.create("PyPackageRequirementsInspection.RunningPackagingTasks"); - public static final String SETUPTOOLS = "setuptools"; - public static final String PIP = "pip"; - public static final String DISTRIBUTE = "distribute"; - public static final String USE_USER_SITE = "--user"; - public static PyPackageManager getInstance(Sdk sdk) { + @NotNull + public static PyPackageManager getInstance(@NotNull Sdk sdk) { return PyPackageManagers.getInstance().forSdk(sdk); } public abstract void installManagement() throws ExecutionException; - public abstract boolean hasManagement(boolean cachedOnly) throws ExecutionException; + public abstract boolean hasManagement() throws ExecutionException; public abstract void install(@NotNull String requirementString) throws ExecutionException; @@ -57,22 +54,10 @@ public abstract class PyPackageManager { public abstract String createVirtualEnv(@NotNull String destinationDir, boolean useGlobalSite) throws ExecutionException; @Nullable - public abstract List getPackages(boolean cachedOnly) throws ExecutionException; + public abstract List getPackages(); - /** - * @param cachedOnly only search through cached packages. Cache may be empty just after project opened. - * warning: non-cache access may be slow on remote interpreters. - * Use {@link #findPackage(String)}: this method uses cache on remote interpreters and skips - * in local - */ - @Nullable - public abstract PyPackage findPackage(@NotNull String name, boolean cachedOnly) throws ExecutionException; - - /** - * Like {@link #findPackage(String, boolean)} but controls cache access based on intepreter remote/local type - */ - @Nullable - public abstract PyPackage findPackage(@NotNull String name) throws ExecutionException; + @NotNull + public abstract List refreshAndGetPackages(boolean alwaysRefresh) throws ExecutionException; @Nullable public abstract List getRequirements(@NotNull Module module); diff --git a/python/openapi/src/com/jetbrains/python/packaging/PyPackageManagers.java b/python/openapi/src/com/jetbrains/python/packaging/PyPackageManagers.java index 83fccdcea6cf..6729ff51ffd4 100644 --- a/python/openapi/src/com/jetbrains/python/packaging/PyPackageManagers.java +++ b/python/openapi/src/com/jetbrains/python/packaging/PyPackageManagers.java @@ -32,7 +32,7 @@ public abstract class PyPackageManagers { } @NotNull - public abstract PyPackageManager forSdk(Sdk sdk); + public abstract PyPackageManager forSdk(@NotNull Sdk sdk); public abstract PackageManagementService getManagementService(Project project, Sdk sdk); diff --git a/python/openapi/src/com/jetbrains/python/templateLanguages/PyTemplatesUtil.java b/python/openapi/src/com/jetbrains/python/templateLanguages/PyTemplatesUtil.java deleted file mode 100644 index ce08ddfd80dc..000000000000 --- a/python/openapi/src/com/jetbrains/python/templateLanguages/PyTemplatesUtil.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2000-2014 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.jetbrains.python.templateLanguages; - -import com.intellij.execution.ExecutionException; -import com.intellij.facet.ui.ValidationResult; -import com.intellij.lang.Language; -import com.intellij.openapi.projectRoots.Sdk; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.psi.FileViewProvider; -import com.intellij.psi.PsiElement; -import com.intellij.psi.templateLanguages.TemplateLanguageFileViewProvider; -import com.jetbrains.python.packaging.PyPackage; -import com.jetbrains.python.packaging.PyPackageManager; -import org.jetbrains.annotations.NonNls; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public class PyTemplatesUtil { - private PyTemplatesUtil() { - } - - public static ValidationResult checkInstalled(@Nullable final Sdk sdk, @NotNull final TemplateLanguagePanel templatesPanel, - @NotNull final String prefix) { - if (sdk == null) return ValidationResult.OK; - String templateBinding = null; - @NonNls String language = templatesPanel.getTemplateLanguage(); - if (language != null) { - String framework = StringUtil.trimEnd(prefix, '_'); - framework = StringUtil.trimEnd(framework, '-'); - String postfix = language.toLowerCase(); - if (framework.equals(postfix)) return ValidationResult.OK; - if (language.equals(TemplatesService.JINJA2)) { - postfix = "jinja"; - } - templateBinding = prefix + postfix; - } - final PyPackageManager packageManager = PyPackageManager.getInstance(sdk); - if (templateBinding != null) { - if (TemplatesService.ALL_TEMPLATE_BINDINGS.contains(templateBinding)) { - try { - final PyPackage installedPackage = packageManager.findPackage(templateBinding, false); - if (installedPackage == null) { - return new ValidationResult(templateBinding + " will be installed on the selected interpreter"); - } - } - catch (ExecutionException ignored) { - } - } - } - if (language != null) { - try { - final PyPackage installedPackage = packageManager.findPackage(language, false); - if (installedPackage == null) { - return new ValidationResult(language + " will be installed on the selected interpreter"); - } - } - catch (ExecutionException ignored) { - } - } - return null; - } - - /** - * Fetches template data language if file has {@link TemplateLanguageFileViewProvider} - * - * @param psiElement element to get lang for - * @param expectedProvider only fetch language if provider has certain type. Pass null for any type. - * @return template data language - */ - @Nullable - public static Language getTemplateDataLanguage(@Nullable final PsiElement psiElement, - @Nullable final Class expectedProvider) { - if (psiElement == null) { - return null; - } - - final FileViewProvider provider = psiElement.getContainingFile().getViewProvider(); - if (provider instanceof TemplateLanguageFileViewProvider) { - if (expectedProvider == null || expectedProvider.isInstance(provider)) { - return (((TemplateLanguageFileViewProvider)provider).getTemplateDataLanguage()); - } - } - - return psiElement.getLanguage(); - } -} - diff --git a/python/openapi/src/com/jetbrains/python/templateLanguages/PythonTemplateIndentOptionsProvider.java b/python/openapi/src/com/jetbrains/python/templateLanguages/PythonTemplateIndentOptionsProvider.java deleted file mode 100644 index cb8663544b77..000000000000 --- a/python/openapi/src/com/jetbrains/python/templateLanguages/PythonTemplateIndentOptionsProvider.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2000-2015 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.jetbrains.python.templateLanguages; - -import com.intellij.lang.Language; -import com.intellij.psi.PsiFile; -import com.intellij.psi.codeStyle.CodeStyleSettings; -import com.intellij.psi.codeStyle.CommonCodeStyleSettings.IndentOptions; -import com.intellij.psi.codeStyle.FileIndentOptionsProvider; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -/** - * Injects indents for Python templates. - * In Python we have template langs, but we should use indent from underlying language (like html) - * because templ. language never works standalone: it is always emebedded in some language - * - * @author Ilya.Kazakevich - */ -public class PythonTemplateIndentOptionsProvider extends FileIndentOptionsProvider { - @Nullable - @Override - public final IndentOptions getIndentOptions(@NotNull final CodeStyleSettings settings, - @NotNull final PsiFile file) { - final Language language = file.getLanguage(); - if (!(language instanceof PythonTemplateLanguage)) { - return null; // We only care about python template files - } - - // This template language has no settings, lets use parent language then - final Language templateDataLanguage = PyTemplatesUtil.getTemplateDataLanguage(file, null); - if (templateDataLanguage == null) { - return null; // No template data language - } - return settings.getIndentOptions(templateDataLanguage.getAssociatedFileType()); - } -} diff --git a/python/openapi/src/com/jetbrains/python/templateLanguages/TemplatesService.java b/python/openapi/src/com/jetbrains/python/templateLanguages/TemplatesService.java index b8eb026b8674..a0be24a26434 100644 --- a/python/openapi/src/com/jetbrains/python/templateLanguages/TemplatesService.java +++ b/python/openapi/src/com/jetbrains/python/templateLanguages/TemplatesService.java @@ -19,9 +19,9 @@ import com.intellij.lang.Language; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleServiceManager; import com.intellij.openapi.project.Project; +import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.containers.ContainerUtil; -import com.jetbrains.python.packaging.PyPackageManager; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -111,7 +111,7 @@ public abstract class TemplatesService { public abstract void setTemplateFileTypes(List fileTypes); public abstract void generateTemplates(@NotNull final TemplateSettingsHolder settings, VirtualFile baseDir); - public abstract void installTemplateEngine(@NotNull final TemplateSettingsHolder settings, @NotNull final PyPackageManager packageManager, + public abstract void installTemplateEngine(@NotNull final TemplateSettingsHolder settings, @NotNull final Sdk sdk, @NotNull final Project project, @NotNull final String prefix); public abstract void addLanguageSelectedListener(Runnable listener); diff --git a/python/python-rest/src/com/jetbrains/rest/RestPythonUtil.java b/python/python-rest/src/com/jetbrains/rest/RestPythonUtil.java index e7e2eae2b928..b3353c6ab7e2 100644 --- a/python/python-rest/src/com/jetbrains/rest/RestPythonUtil.java +++ b/python/python-rest/src/com/jetbrains/rest/RestPythonUtil.java @@ -15,7 +15,6 @@ */ package com.jetbrains.rest; -import com.intellij.execution.ExecutionException; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.actionSystem.LangDataKeys; @@ -26,8 +25,11 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.projectRoots.Sdk; import com.jetbrains.python.packaging.PyPackage; import com.jetbrains.python.packaging.PyPackageManager; +import com.jetbrains.python.packaging.PyPackageUtil; import com.jetbrains.python.sdk.PythonSdkType; +import java.util.List; + /** * User : catherine */ @@ -45,15 +47,11 @@ public class RestPythonUtil { module = modules.length == 0 ? null : modules [0]; } if (module != null) { - Sdk sdk = PythonSdkType.findPythonSdk(module); + final Sdk sdk = PythonSdkType.findPythonSdk(module); if (sdk != null) { - PyPackageManager manager = PyPackageManager.getInstance(sdk); - try { - final PyPackage sphinx = manager.findPackage("Sphinx", false); - presentation.setEnabled(sphinx != null); - } - catch (ExecutionException ignored) { - } + final List packages = PyPackageManager.getInstance(sdk).getPackages(); + final PyPackage sphinx = packages != null ? PyPackageUtil.findPackage(packages, "Sphinx") : null; + presentation.setEnabled(sphinx != null); } } } diff --git a/python/python-rest/src/com/jetbrains/rest/run/sphinx/SphinxRunConfiguration.java b/python/python-rest/src/com/jetbrains/rest/run/sphinx/SphinxRunConfiguration.java index f2e90d02079e..26311708c5ce 100644 --- a/python/python-rest/src/com/jetbrains/rest/run/sphinx/SphinxRunConfiguration.java +++ b/python/python-rest/src/com/jetbrains/rest/run/sphinx/SphinxRunConfiguration.java @@ -25,10 +25,13 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; import com.jetbrains.python.packaging.PyPackage; import com.jetbrains.python.packaging.PyPackageManager; +import com.jetbrains.python.packaging.PyPackageUtil; import com.jetbrains.rest.run.RestConfigurationEditor; import com.jetbrains.rest.run.RestRunConfiguration; import org.jetbrains.annotations.NotNull; +import java.util.List; + /** * User : catherine */ @@ -42,14 +45,13 @@ public class SphinxRunConfiguration extends RestRunConfiguration { protected SettingsEditor createConfigurationEditor() { final SphinxTasksModel model = new SphinxTasksModel(); if (!model.contains("pdf") && getSdk() != null) { - try { - final PyPackage rst2pdf = PyPackageManager.getInstance(getSdk()).findPackage("rst2pdf"); + final List packages = PyPackageManager.getInstance(getSdk()).getPackages(); + if (packages != null) { + final PyPackage rst2pdf = PyPackageUtil.findPackage(packages,"rst2pdf"); if (rst2pdf != null) { model.add(13, "pdf"); } } - catch (ExecutionException ignored) { - } } RestConfigurationEditor editor = new RestConfigurationEditor(getProject(), this, model); diff --git a/python/src/com/jetbrains/python/PyBundle.properties b/python/src/com/jetbrains/python/PyBundle.properties index ee67f7d0e69a..62055e41c78f 100644 --- a/python/src/com/jetbrains/python/PyBundle.properties +++ b/python/src/com/jetbrains/python/PyBundle.properties @@ -889,7 +889,7 @@ sdk.gen.reloading=Reloading generated skeletons... sdk.gen.reading.versions.file=Reading versions file... sdk.gen.notify.converting.old.skels=Converting old skeletons sdk.gen.notify.converting.text=Skeletons of binary modules seem to be from an older version.
These will be fully re-generated, which will take some time, but will happen only once.
Next time you open the project, only skeletons of new or updated binary modules will be re-generated. -sdk.gen.updating.skeletons=Updating Skeletons +sdk.gen.updating.interpreter=Updating Python Interpreter sdk.gen.stubs.for.binary.modules=Generate stubs for binary module {0} # Active SDK configurable and related dialogs @@ -1009,4 +1009,4 @@ formatter.dictionary.literals=Dictionary literals smartKeys.insert.backslash.in.statement.on.enter=Insert backslash when pressing Enter inside a statement smartKeys.insert.self.in.method=Insert 'self' when defining a method -smartKeys.insert.type.placeholder.in.docstring.stub=Insert type placeholders in the documentation comment stub \ No newline at end of file +smartKeys.insert.type.placeholder.in.docstring.stub=Insert type placeholders in the documentation comment stub diff --git a/python/src/com/jetbrains/python/inspections/PyPackageRequirementsInspection.java b/python/src/com/jetbrains/python/inspections/PyPackageRequirementsInspection.java index 31bd6d7cbf50..2ae69d0dd897 100644 --- a/python/src/com/jetbrains/python/inspections/PyPackageRequirementsInspection.java +++ b/python/src/com/jetbrains/python/inspections/PyPackageRequirementsInspection.java @@ -39,7 +39,6 @@ import com.jetbrains.python.packaging.*; import com.jetbrains.python.packaging.ui.PyChooseRequirementsDialog; import com.jetbrains.python.psi.*; import com.jetbrains.python.psi.impl.PyPsiUtils; -import com.jetbrains.python.sdk.PySdkUtil; import com.jetbrains.python.sdk.PythonSdkType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -158,7 +157,7 @@ public class PyPackageRequirementsInspection extends PyInspection { return; } } - if (PyPackageManager.SETUPTOOLS.equals(packageName)) { + if (PyPackageUtil.SETUPTOOLS.equals(packageName)) { return; } final Module module = ModuleUtilCore.findModuleForPsiElement(packageReferenceExpression); @@ -211,13 +210,7 @@ public class PyPackageRequirementsInspection extends PyInspection { return Collections.emptySet(); } final Set results = new HashSet(requirements); - final List packages; - try { - packages = PyPackageManager.getInstance(sdk).getPackages(PySdkUtil.isRemote(sdk)); - } - catch (ExecutionException e) { - return null; - } + final List packages = PyPackageManager.getInstance(sdk).getPackages(); if (packages == null) return null; for (PyRequirement req : requirements) { final PyPackage pkg = req.match(packages); @@ -237,15 +230,10 @@ public class PyPackageRequirementsInspection extends PyInspection { final PyPackageManager manager = PyPackageManager.getInstance(sdk); List requirements = manager.getRequirements(module); if (requirements != null) { - final List packages; - try { - packages = manager.getPackages(PySdkUtil.isRemote(sdk)); - } - catch (ExecutionException e) { - LOG.warn(e); + final List packages = manager.getPackages(); + if (packages == null) { return null; } - if (packages == null) return null; final List unsatisfied = new ArrayList(); for (PyRequirement req : requirements) { if (!ignoredPackages.contains(req.getName()) && req.match(packages) == null) { @@ -297,13 +285,11 @@ public class PyPackageRequirementsInspection extends PyInspection { public void applyFix(@NotNull final Project project, @NotNull ProblemDescriptor descriptor) { boolean installManagement = false; final PyPackageManager manager = PyPackageManager.getInstance(mySdk); - boolean hasManagement = false; - try { - hasManagement = manager.hasManagement(false); + final List packages = manager.getPackages(); + if (packages == null) { + return; } - catch (ExecutionException ignored) { - } - if (!hasManagement) { + if (PyPackageUtil.hasManagement(packages)) { final int result = Messages.showYesNoDialog(project, "Python packaging tools are required for installing packages. Do you want to " + "install 'pip' and 'setuptools' for your interpreter?", diff --git a/python/src/com/jetbrains/python/packaging/PyCondaPackageManagerImpl.java b/python/src/com/jetbrains/python/packaging/PyCondaPackageManagerImpl.java index ac6135ac7135..12b0f622468b 100644 --- a/python/src/com/jetbrains/python/packaging/PyCondaPackageManagerImpl.java +++ b/python/src/com/jetbrains/python/packaging/PyCondaPackageManagerImpl.java @@ -49,9 +49,8 @@ public class PyCondaPackageManagerImpl extends PyPackageManagerImpl { public void installManagement() throws ExecutionException { } - @Override - public boolean hasManagement(boolean cachedOnly) throws ExecutionException { + public boolean hasManagement() throws ExecutionException { final Sdk sdk = getSdk(); return isCondaVEnv(sdk); } @@ -126,10 +125,10 @@ public class PyCondaPackageManagerImpl extends PyPackageManagerImpl { @NotNull @Override - protected List getPackages() throws ExecutionException { + protected List collectPackages() throws ExecutionException { final ProcessOutput output = getCondaOutput("list", Lists.newArrayList("-e")); final Set packages = Sets.newConcurrentHashSet(parseCondaToolOutput(output.getStdout())); - packages.addAll(super.getPackages()); + packages.addAll(super.collectPackages()); return Lists.newArrayList(packages); } diff --git a/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java b/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java index f504c905450e..16130c28a1a4 100644 --- a/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java +++ b/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java @@ -41,7 +41,6 @@ import com.intellij.util.messages.MessageBusConnection; import com.intellij.util.net.HttpConfigurable; import com.jetbrains.python.PythonHelpersLocator; import com.jetbrains.python.psi.LanguageLevel; -import com.jetbrains.python.sdk.PySdkUtil; import com.jetbrains.python.sdk.PythonEnvUtil; import com.jetbrains.python.sdk.PythonSdkType; import org.jetbrains.annotations.NotNull; @@ -78,9 +77,8 @@ public class PyPackageManagerImpl extends PyPackageManager { public static final String UNINSTALL = "uninstall"; public static final String UNTAR = "untar"; - private final Object myCacheLock = new Object(); - private List myPackagesCache = null; - private ExecutionException myExceptionCache = null; + @Nullable private volatile List myPackagesCache = null; + private volatile boolean myUpdatingCache = false; @NotNull final private Sdk mySdk; @@ -95,7 +93,6 @@ public class PyPackageManagerImpl extends PyPackageManager { VfsUtil.markDirtyAndRefresh(true, true, true, files); }); PythonSdkType.getInstance().setupSdkPaths(sdk); - clearCaches(); }); } @@ -103,24 +100,25 @@ public class PyPackageManagerImpl extends PyPackageManager { public void installManagement() throws ExecutionException { final Sdk sdk = getSdk(); final boolean pre26 = PythonSdkType.getLanguageLevelForSdk(sdk).isOlderThan(LanguageLevel.PYTHON26); - if (!hasSetuptools(false)) { - final String name = SETUPTOOLS + "-" + (pre26 ? SETUPTOOLS_PRE_26_VERSION : SETUPTOOLS_VERSION); + if (!refreshAndCheckForSetuptools()) { + final String name = PyPackageUtil.SETUPTOOLS + "-" + (pre26 ? SETUPTOOLS_PRE_26_VERSION : SETUPTOOLS_VERSION); installManagement(name); } - if (!hasPackage(PIP, false)) { - final String name = PIP + "-" + (pre26 ? PIP_PRE_26_VERSION : PIP_VERSION); + if (PyPackageUtil.findPackage(refreshAndGetPackages(false), PyPackageUtil.PIP) == null) { + final String name = PyPackageUtil.PIP + "-" + (pre26 ? PIP_PRE_26_VERSION : PIP_VERSION); installManagement(name); } } @Override - public boolean hasManagement(boolean cachedOnly) throws ExecutionException { - return hasSetuptools(cachedOnly) && hasPackage(PIP, cachedOnly); + public boolean hasManagement() throws ExecutionException { + return refreshAndCheckForSetuptools() && PyPackageUtil.findPackage(refreshAndGetPackages(false), PyPackageUtil.PIP) != null; } - private boolean hasSetuptools(boolean cachedOnly) throws ExecutionException { + private boolean refreshAndCheckForSetuptools() throws ExecutionException { try { - return hasPackage(SETUPTOOLS, cachedOnly) || hasPackage(DISTRIBUTE, cachedOnly); + final List packages = refreshAndGetPackages(false); + return PyPackageUtil.findPackage(packages, PyPackageUtil.SETUPTOOLS) != null || PyPackageUtil.findPackage(packages, PyPackageUtil.DISTRIBUTE) != null; } catch (PyExecutionException e) { if (e.getExitCode() == ERROR_NO_SETUPTOOLS) { @@ -137,7 +135,6 @@ public class PyPackageManagerImpl extends PyPackageManager { getPythonProcessResult(fileName, Collections.singletonList(INSTALL), true, true, dirName + name); } finally { - clearCaches(); FileUtil.delete(new File(dirName)); } } @@ -154,10 +151,6 @@ public class PyPackageManagerImpl extends PyPackageManager { return dirName; } - private boolean hasPackage(@NotNull String name, boolean cachedOnly) throws ExecutionException { - return findPackage(name, cachedOnly) != null; - } - PyPackageManagerImpl(@NotNull final Sdk sdk) { mySdk = sdk; subscribeToLocalChanges(); @@ -224,7 +217,7 @@ public class PyPackageManagerImpl extends PyPackageManager { } finally { LOG.debug("Packages cache is about to be cleared because these requirements were installed: " + requirements); - clearCaches(); + refreshPackagesSynchronously(); FileUtil.delete(buildDir); } } @@ -250,50 +243,20 @@ public class PyPackageManagerImpl extends PyPackageManager { } finally { LOG.debug("Packages cache is about to be cleared because these packages were uninstalled: " + packages); - clearCaches(); + refreshPackagesSynchronously(); } } + @Nullable - public List getPackages(boolean cachedOnly) throws ExecutionException { - synchronized (myCacheLock) { - if (myPackagesCache != null) { - return new ArrayList(myPackagesCache); - } - if (myExceptionCache != null) { - throw myExceptionCache; - } - if (cachedOnly) { - return null; - } - } - try { - final List packages = getPackages(); - if (LOG.isDebugEnabled()) { - LOG.debug("Packages installed in " + mySdk.getName() + ": " + packages); - } - synchronized (myCacheLock) { - myPackagesCache = packages; - return new ArrayList(myPackagesCache); - } - } - catch (ExecutionException e) { - synchronized (myCacheLock) { - myExceptionCache = e; - } - throw e; - } + @Override + public List getPackages() { + final List packages = myPackagesCache; + return packages != null ? Collections.unmodifiableList(packages) : null; } - //@NotNull - //public String fetchLatestVersion(InstalledPackage pkg) throws ExecutionException { - // final ArrayList arguments = Lists.newArrayList("latestVersion", pkg.getName()); - // arguments.addAll(PyPackageService.getInstance().additionalRepositories); - // return getHelperResult(PACKAGING_TOOL, arguments, false, false, null); - //} - @NotNull - protected List getPackages() throws ExecutionException { + protected List collectPackages() throws ExecutionException { final String output; try { output = getHelperResult(PACKAGING_TOOL, Collections.singletonList("list"), false, false, null); @@ -301,8 +264,8 @@ public class PyPackageManagerImpl extends PyPackageManager { catch (final ProcessNotCreatedException ex) { if (ApplicationManager.getApplication().isUnitTestMode()) { LOG.info("Not-env unit test mode, will return mock packages"); - return Lists.newArrayList(new PyPackage(PIP, PIP_VERSION, null, Collections.emptyList()), - new PyPackage(SETUPTOOLS, SETUPTOOLS_VERSION, null, Collections.emptyList())); + return Lists.newArrayList(new PyPackage(PyPackageUtil.PIP, PIP_VERSION, null, Collections.emptyList()), + new PyPackage(PyPackageUtil.SETUPTOOLS, SETUPTOOLS_VERSION, null, Collections.emptyList())); } else { throw ex; @@ -314,40 +277,17 @@ public class PyPackageManagerImpl extends PyPackageManager { @Nullable public Set getDependents(@NotNull PyPackage pkg) throws ExecutionException { - final List packages = getPackages(false); - if (packages != null) { - final Set dependents = new HashSet(); - for (PyPackage p : packages) { - final List requirements = p.getRequirements(); - for (PyRequirement requirement : requirements) { - if (requirement.getName().equals(pkg.getName())) { - dependents.add(p); - } - } - } - return dependents; - } - return null; - } - - @Override - @Nullable - public PyPackage findPackage(@NotNull String name, boolean cachedOnly) throws ExecutionException { - final List packages = getPackages(cachedOnly); - if (packages != null) { - for (PyPackage pkg : packages) { - if (name.equalsIgnoreCase(pkg.getName())) { - return pkg; + final List packages = refreshAndGetPackages(false); + final Set dependents = new HashSet(); + for (PyPackage p : packages) { + final List requirements = p.getRequirements(); + for (PyRequirement requirement : requirements) { + if (requirement.getName().equals(pkg.getName())) { + dependents.add(p); } } } - return null; - } - - @Nullable - @Override - public final PyPackage findPackage(@NotNull final String name) throws ExecutionException { - return findPackage(name, PySdkUtil.isRemote(mySdk)); + return dependents; } @NotNull @@ -405,11 +345,38 @@ public class PyPackageManagerImpl extends PyPackageManager { .orElseGet(() -> PyPackageUtil.findSetupPyRequires(module)); } - protected void clearCaches() { - synchronized (myCacheLock) { - myPackagesCache = null; - myExceptionCache = null; - LOG.debug("Packages cache is cleared"); + +// public List refreshAndGetPackagesIfNotInProgress(boolean alwaysRefresh) throws ExecutionException + + @Override + @NotNull + public List refreshAndGetPackages(boolean alwaysRefresh) throws ExecutionException { + final List currentPackages = myPackagesCache; + if (alwaysRefresh || currentPackages == null) { + myUpdatingCache = true; + try { + final List packages = collectPackages(); + myPackagesCache = packages; + return packages; + } + finally { + myUpdatingCache = false; + } + } + return Collections.unmodifiableList(currentPackages); + } + + private void refreshPackagesSynchronously() { + assert !ApplicationManager.getApplication().isDispatchThread(); + if (myUpdatingCache) { + return; + } + try { + LOG.info("Refreshing installed packages for SDK " + mySdk.getHomePath()); + refreshAndGetPackages(true); + } + catch (ExecutionException e) { + LOG.error(e); } } @@ -568,7 +535,7 @@ public class PyPackageManagerImpl extends PyPackageManager { for (VirtualFile root : roots) { if (VfsUtilCore.isAncestor(root, file, false)) { LOG.debug("Clearing packages cache on SDK change"); - clearCaches(); + ApplicationManager.getApplication().executeOnPooledThread(PyPackageManagerImpl.this::refreshPackagesSynchronously); return; } } diff --git a/python/src/com/jetbrains/python/packaging/PyPackageManagersImpl.java b/python/src/com/jetbrains/python/packaging/PyPackageManagersImpl.java index 11d61778f85a..163b75476a31 100644 --- a/python/src/com/jetbrains/python/packaging/PyPackageManagersImpl.java +++ b/python/src/com/jetbrains/python/packaging/PyPackageManagersImpl.java @@ -29,10 +29,7 @@ import com.jetbrains.python.sdk.flavors.PythonSdkFlavor; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; /** * @author yole @@ -98,16 +95,16 @@ public class PyPackageManagersImpl extends PyPackageManagers { throw new ExecutionException(getErrorMessage()); } + @Override + public boolean hasManagement() throws ExecutionException { + return false; + } + @NotNull private String getErrorMessage() { return "Invalid interpreter \"" + myName + "\" version: " + myLanguageLevel.toString() + " type: " + myFlavor.getName(); } - @Override - public boolean hasManagement(boolean cachedOnly) throws ExecutionException { - throw new ExecutionException(getErrorMessage()); - } - @Override public void install(@NotNull String requirementString) throws ExecutionException { throw new ExecutionException(getErrorMessage()); @@ -135,19 +132,13 @@ public class PyPackageManagersImpl extends PyPackageManagers { @Nullable @Override - public List getPackages(boolean cachedOnly) throws ExecutionException { - throw new ExecutionException(getErrorMessage()); + public List getPackages() { + return null; } - @Nullable + @NotNull @Override - public PyPackage findPackage(@NotNull String name, boolean cachedOnly) throws ExecutionException { - throw new ExecutionException(getErrorMessage()); - } - - @Nullable - @Override - public PyPackage findPackage(@NotNull String name) throws ExecutionException { + public List refreshAndGetPackages(boolean alwaysRefresh) throws ExecutionException { throw new ExecutionException(getErrorMessage()); } diff --git a/python/src/com/jetbrains/python/packaging/PyPackageUtil.java b/python/src/com/jetbrains/python/packaging/PyPackageUtil.java index 6ce2c625d814..ec0aae2e56c6 100644 --- a/python/src/com/jetbrains/python/packaging/PyPackageUtil.java +++ b/python/src/com/jetbrains/python/packaging/PyPackageUtil.java @@ -17,6 +17,8 @@ package com.jetbrains.python.packaging; import com.intellij.openapi.editor.Document; import com.intellij.openapi.fileEditor.FileDocumentManager; +import com.intellij.execution.ExecutionException; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; import com.intellij.openapi.projectRoots.Sdk; @@ -53,6 +55,10 @@ import java.util.stream.Stream; * @author vlan */ public class PyPackageUtil { + public static final String SETUPTOOLS = "setuptools"; + public static final String PIP = "pip"; + public static final String DISTRIBUTE = "distribute"; + private static final Logger LOG = Logger.getInstance(PyPackageUtil.class); @NotNull private static final String REQUIRES = "requires"; @@ -270,6 +276,36 @@ public class PyPackageUtil { }.withSshContribution(true).withVagrantContribution(true).withWebDeploymentContribution(true).check(sdk); } + @Nullable + public static List refreshAndGetPackagesModally(@NotNull Sdk sdk) { + final Ref> packagesRef = Ref.create(); + PyUtil.runWithProgress(null, "Scanning Installed Packages", true, false, indicator -> { + indicator.setIndeterminate(true); + try { + packagesRef.set(PyPackageManager.getInstance(sdk).refreshAndGetPackages(false)); + } + catch (ExecutionException e) { + LOG.error(e); + } + }); + return packagesRef.get(); + } + + @Nullable + public static PyPackage findPackage(@NotNull List packages, @NotNull String name) { + for (PyPackage pkg : packages) { + if (name.equalsIgnoreCase(pkg.getName())) { + return pkg; + } + } + return null; + } + + public static boolean hasManagement(@NotNull List packages) { + return (findPackage(packages, SETUPTOOLS) != null || findPackage(packages, DISTRIBUTE) != null) || + findPackage(packages, PIP) != null; + } + @Nullable public static List getRequirementsFromTxt(@NotNull Module module) { final VirtualFile requirementsTxt = findRequirementsTxt(module); diff --git a/python/src/com/jetbrains/python/packaging/PyRemotePackageManagerImpl.java b/python/src/com/jetbrains/python/packaging/PyRemotePackageManagerImpl.java index 2fe8f70bfead..158dcfceed99 100644 --- a/python/src/com/jetbrains/python/packaging/PyRemotePackageManagerImpl.java +++ b/python/src/com/jetbrains/python/packaging/PyRemotePackageManagerImpl.java @@ -214,7 +214,6 @@ public class PyRemotePackageManagerImpl extends PyPackageManagerImpl { try { manager.runVagrant(myVagrantFolder, myMachineName); PythonSdkType.getInstance().setupSdkPaths(sdk); - clearCaches(); } catch (ExecutionException e) { throw new RuntimeException(e); diff --git a/python/src/com/jetbrains/python/packaging/ui/PyInstalledPackagesPanel.java b/python/src/com/jetbrains/python/packaging/ui/PyInstalledPackagesPanel.java index f0a5a850751a..f84a7eb24b51 100644 --- a/python/src/com/jetbrains/python/packaging/ui/PyInstalledPackagesPanel.java +++ b/python/src/com/jetbrains/python/packaging/ui/PyInstalledPackagesPanel.java @@ -93,7 +93,7 @@ public class PyInstalledPackagesPanel extends InstalledPackagesPanel { application.executeOnPooledThread(() -> { PyExecutionException exception = null; try { - myHasManagement = PyPackageManager.getInstance(selectedSdk).hasManagement(false); + myHasManagement = PyPackageManager.getInstance(selectedSdk).hasManagement(); if (!myHasManagement) { throw new PyExecutionException("Python packaging tools not found", "pip", Collections.emptyList(), "", "", 0, ImmutableList.of(new PyInstallPackageManagementFix())); @@ -156,9 +156,9 @@ public class PyInstalledPackagesPanel extends InstalledPackagesPanel { } } final String name = pkg.getName(); - if (PyPackageManager.PIP.equals(name) || - PyPackageManager.SETUPTOOLS.equals(name) || - PyPackageManager.DISTRIBUTE.equals(name) || + if (PyPackageUtil.PIP.equals(name) || + PyPackageUtil.SETUPTOOLS.equals(name) || + PyPackageUtil.DISTRIBUTE.equals(name) || PyCondaPackageManagerImpl.PYTHON.equals(name)) { return false; } diff --git a/python/src/com/jetbrains/python/packaging/ui/PyPackageManagementService.java b/python/src/com/jetbrains/python/packaging/ui/PyPackageManagementService.java index 4096539aef49..2ffc54f888fa 100644 --- a/python/src/com/jetbrains/python/packaging/ui/PyPackageManagementService.java +++ b/python/src/com/jetbrains/python/packaging/ui/PyPackageManagementService.java @@ -15,6 +15,7 @@ */ package com.jetbrains.python.packaging.ui; +import com.google.common.collect.Lists; import com.intellij.execution.ExecutionException; import com.intellij.execution.RunCanceledByUserException; import com.intellij.openapi.project.Project; @@ -139,17 +140,17 @@ public class PyPackageManagementService extends PackageManagementServiceEx { @Override public Collection getInstalledPackages() throws IOException { - List packages; + + final PyPackageManager manager = PyPackageManager.getInstance(mySdk); + final List packages; try { - packages = PyPackageManager.getInstance(mySdk).getPackages(false); - if (packages != null) { - Collections.sort(packages, (pkg1, pkg2) -> pkg1.getName().compareTo(pkg2.getName())); - } + packages = Lists.newArrayList(manager.refreshAndGetPackages(false)); } catch (ExecutionException e) { throw new IOException(e); } - return packages != null ? new ArrayList(packages) : new ArrayList(); + Collections.sort(packages, (pkg1, pkg2) -> pkg1.getName().compareTo(pkg2.getName())); + return new ArrayList(packages); } @Override diff --git a/python/src/com/jetbrains/python/psi/PyUtil.java b/python/src/com/jetbrains/python/psi/PyUtil.java index 9fdc17b2ebb1..bdf133eed108 100644 --- a/python/src/com/jetbrains/python/psi/PyUtil.java +++ b/python/src/com/jetbrains/python/psi/PyUtil.java @@ -28,6 +28,7 @@ import com.intellij.injected.editor.VirtualFileWindow; import com.intellij.lang.ASTFactory; import com.intellij.lang.ASTNode; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.EditorFactory; @@ -38,6 +39,9 @@ import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.module.ModuleUtilCore; +import com.intellij.openapi.progress.ProgressIndicator; +import com.intellij.openapi.progress.ProgressManager; +import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.Project; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.roots.ModuleRootManager; @@ -81,15 +85,11 @@ import com.jetbrains.python.refactoring.classes.PyDependenciesComparator; import com.jetbrains.python.refactoring.classes.extractSuperclass.PyExtractSuperclassHelper; import com.jetbrains.python.refactoring.classes.membersManager.PyMemberInfo; import com.jetbrains.python.sdk.PythonSdkType; -import org.jetbrains.annotations.Contract; -import org.jetbrains.annotations.NonNls; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.*; import javax.swing.*; import java.awt.*; import java.io.File; -import java.io.FileFilter; import java.io.IOException; import java.util.*; import java.util.List; @@ -858,6 +858,28 @@ public class PyUtil { return result; } + public static void runWithProgress(@Nullable Project project, @Nls(capitalization = Nls.Capitalization.Title) @NotNull String title, + boolean modal, boolean canBeCancelled, @NotNull final Consumer function) { + ApplicationManager.getApplication().invokeAndWait(() -> { + if (modal) { + ProgressManager.getInstance().run(new Task.Modal(project, title, canBeCancelled) { + @Override + public void run(@NotNull ProgressIndicator indicator) { + function.consume(indicator); + } + }); + } + else { + ProgressManager.getInstance().run(new Task.Backgroundable(project, title, canBeCancelled) { + @Override + public void run(@NotNull ProgressIndicator indicator) { + function.consume(indicator); + } + }); + } + }, ModalityState.current()); + } + /** * Executes code only if
_PYCHARM_VERBOSE_MODE
is set in env (which should be done for debug purposes only) * @param runnable code to call diff --git a/python/src/com/jetbrains/python/sdk/PythonSdkUpdater.java b/python/src/com/jetbrains/python/sdk/PythonSdkUpdater.java index 7baf341b46de..7e38682fcf4f 100644 --- a/python/src/com/jetbrains/python/sdk/PythonSdkUpdater.java +++ b/python/src/com/jetbrains/python/sdk/PythonSdkUpdater.java @@ -18,6 +18,7 @@ package com.jetbrains.python.sdk; import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; import com.google.common.collect.Sets; +import com.intellij.execution.ExecutionException; import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; @@ -44,6 +45,7 @@ import com.intellij.util.concurrency.BlockingSet; import com.intellij.util.concurrency.EdtExecutorService; import com.jetbrains.python.PyBundle; import com.jetbrains.python.codeInsight.userSkeletons.PyUserSkeletonsUtil; +import com.jetbrains.python.packaging.PyPackageManager; import com.jetbrains.python.psi.PyUtil; import com.jetbrains.python.remote.PyCredentialsContribution; import com.jetbrains.python.remote.PyRemoteSdkAdditionalDataBase; @@ -138,7 +140,7 @@ public class PythonSdkUpdater implements StartupActivity { } ourScheduledToRefresh.remove(homePath); } - ProgressManager.getInstance().run(new Task.Backgroundable(project, PyBundle.message("sdk.gen.updating.skeletons"), false) { + ProgressManager.getInstance().run(new Task.Backgroundable(project, PyBundle.message("sdk.gen.updating.interpreter"), false) { @Override public void run(@NotNull ProgressIndicator indicator) { final Project project1 = getProject(); @@ -152,8 +154,19 @@ public class PythonSdkUpdater implements StartupActivity { LOG.error("For refreshing skeletons of remote SDK, either project or owner component must be specified"); } LOG.info("Performing background update of skeletons for SDK " + sdk12.getHomePath()); + indicator.setText("Updating skeletons..."); PySkeletonRefresher.refreshSkeletonsOfSdk(project1, ownerComponent, skeletonsPath, sdk12); updateRemoteSdkPaths(sdk12); + indicator.setIndeterminate(true); + indicator.setText("Scanning installed packages..."); + indicator.setText2(""); + LOG.info("Performing background scan of packages for SDK " + sdk12.getHomePath()); + try { + PyPackageManager.getInstance(sdk12).refreshAndGetPackages(true); + } + catch (ExecutionException e) { + LOG.error(e); + } } catch (InvalidSdkException e) { if (PythonSdkType.isVagrant(sdk12) diff --git a/python/src/com/jetbrains/python/sdk/skeletons/PySkeletonRefresher.java b/python/src/com/jetbrains/python/sdk/skeletons/PySkeletonRefresher.java index a3600e260b3b..bc5cd1f8f936 100644 --- a/python/src/com/jetbrains/python/sdk/skeletons/PySkeletonRefresher.java +++ b/python/src/com/jetbrains/python/sdk/skeletons/PySkeletonRefresher.java @@ -43,7 +43,6 @@ import com.jetbrains.python.PyBundle; import com.jetbrains.python.PyNames; import com.jetbrains.python.buildout.BuildoutFacet; import com.jetbrains.python.codeInsight.userSkeletons.PyUserSkeletonsUtil; -import com.jetbrains.python.packaging.PyPackageManager; import com.jetbrains.python.psi.resolve.PythonSdkPathCache; import com.jetbrains.python.remote.PythonRemoteInterpreterManager; import com.jetbrains.python.sdk.InvalidSdkException; @@ -345,15 +344,6 @@ public class PySkeletonRefresher { indicate(PyBundle.message("sdk.gen.cleaning.$0", readablePath)); cleanUpSkeletons(skeletonsDir); } - if (PySdkUtil.isRemote(mySdk)) { - try { - // Force loading packages - PyPackageManager.getInstance(mySdk).getPackages(false); - } - catch (ExecutionException e) { - // ignore - already logged - } - } if ((builtinsUpdated || PySdkUtil.isRemote(mySdk)) && myProject != null) { ApplicationManager.getApplication().invokeLater(() -> DaemonCodeAnalyzer.getInstance(myProject).restart(), myProject.getDisposed()); diff --git a/python/src/com/jetbrains/python/testing/VFSTestFrameworkListener.java b/python/src/com/jetbrains/python/testing/VFSTestFrameworkListener.java index 6dd8eb7b839a..50c3aac817d8 100644 --- a/python/src/com/jetbrains/python/testing/VFSTestFrameworkListener.java +++ b/python/src/com/jetbrains/python/testing/VFSTestFrameworkListener.java @@ -15,7 +15,6 @@ */ package com.jetbrains.python.testing; -import com.intellij.execution.ExecutionException; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.projectRoots.Sdk; @@ -30,11 +29,11 @@ import com.intellij.openapi.vfs.newvfs.events.VFileContentChangeEvent; import com.intellij.openapi.vfs.newvfs.events.VFileEvent; import com.intellij.util.Alarm; import com.intellij.util.messages.MessageBus; -import com.intellij.util.ui.UIUtil; import com.intellij.util.ui.update.MergingUpdateQueue; import com.intellij.util.ui.update.Update; import com.jetbrains.python.PyNames; -import com.jetbrains.python.packaging.PyPackageManager; +import com.jetbrains.python.packaging.PyPackage; +import com.jetbrains.python.packaging.PyPackageUtil; import com.jetbrains.python.sdk.PySdkUtil; import com.jetbrains.python.sdk.PythonSdkType; import org.jetbrains.annotations.NotNull; @@ -117,14 +116,11 @@ public class VFSTestFrameworkListener { LOG.info("Searching test runner in empty sdk"); return null; } - final PyPackageManager packageManager = PyPackageManager.getInstance(sdk); - try { - return packageManager.findPackage(testPackageName, false) != null; + final List packages = PyPackageUtil.refreshAndGetPackagesModally(sdk); + if (packages == null) { + return null; } - catch (ExecutionException e) { - LOG.info("Can't load package list " + e.getMessage()); - } - return null; + return PyPackageUtil.findPackage(packages, testPackageName) != null; } public static VFSTestFrameworkListener getInstance() { diff --git a/python/src/com/jetbrains/python/testing/pytest/PyTestConfigurationProducer.java b/python/src/com/jetbrains/python/testing/pytest/PyTestConfigurationProducer.java index 2249516da492..69fa292538c8 100644 --- a/python/src/com/jetbrains/python/testing/pytest/PyTestConfigurationProducer.java +++ b/python/src/com/jetbrains/python/testing/pytest/PyTestConfigurationProducer.java @@ -15,7 +15,6 @@ */ package com.jetbrains.python.testing.pytest; -import com.intellij.execution.ExecutionException; import com.intellij.execution.Location; import com.intellij.execution.actions.ConfigurationContext; import com.intellij.openapi.module.Module; @@ -31,6 +30,7 @@ import com.intellij.psi.util.PsiTreeUtil; import com.intellij.webcore.packaging.PackageVersionComparator; import com.jetbrains.python.packaging.PyPackage; import com.jetbrains.python.packaging.PyPackageManager; +import com.jetbrains.python.packaging.PyPackageUtil; import com.jetbrains.python.psi.PyClass; import com.jetbrains.python.psi.PyFile; import com.jetbrains.python.psi.PyFunction; @@ -115,17 +115,12 @@ public class PyTestConfigurationProducer extends PythonTestConfigurationProducer if (pyFunction != null) { keywords = pyFunction.getName(); if (pyClass != null) { - final PyPackageManager packageManager = PyPackageManager.getInstance(sdk); - try { - final PyPackage pytestPackage = packageManager.findPackage("pytest", false); - if (pytestPackage != null && PackageVersionComparator.VERSION_COMPARATOR.compare(pytestPackage.getVersion(), "2.3.3") >= 0) { - keywords = pyClass.getName() + " and " + keywords; - } - else { - keywords = pyClass.getName() + "." + keywords; - } + final List packages = PyPackageManager.getInstance(sdk).getPackages(); + final PyPackage pytestPackage = packages != null ? PyPackageUtil.findPackage(packages, "pytest") : null; + if (pytestPackage != null && PackageVersionComparator.VERSION_COMPARATOR.compare(pytestPackage.getVersion(), "2.3.3") >= 0) { + keywords = pyClass.getName() + " and " + keywords; } - catch (ExecutionException e) { + else { keywords = pyClass.getName() + "." + keywords; } } diff --git a/python/testSrc/com/jetbrains/env/PyEnvTestCase.java b/python/testSrc/com/jetbrains/env/PyEnvTestCase.java index 3e0d55d15fb4..01587acba9c2 100644 --- a/python/testSrc/com/jetbrains/env/PyEnvTestCase.java +++ b/python/testSrc/com/jetbrains/env/PyEnvTestCase.java @@ -19,6 +19,7 @@ import com.intellij.util.ui.UIUtil; import com.jetbrains.TestEnv; import com.jetbrains.python.packaging.PyPackage; import com.jetbrains.python.packaging.PyPackageManager; +import com.jetbrains.python.packaging.PyPackageUtil; import org.hamcrest.Matchers; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -113,7 +114,7 @@ public abstract class PyEnvTestCase { @Nullable public static PyPackage getInstalledDjango(@NotNull final Sdk sdk) throws ExecutionException { - return PyPackageManager.getInstance(sdk).findPackage("django", false); + return PyPackageUtil.findPackage(PyPackageManager.getInstance(sdk).refreshAndGetPackages(false), "django"); } public static String norm(String testDataPath) { diff --git a/python/testSrc/com/jetbrains/env/python/PyPackagingTest.java b/python/testSrc/com/jetbrains/env/python/PyPackagingTest.java index e89d9033bf8e..a7d127c5a325 100644 --- a/python/testSrc/com/jetbrains/env/python/PyPackagingTest.java +++ b/python/testSrc/com/jetbrains/env/python/PyPackagingTest.java @@ -52,7 +52,7 @@ public class PyPackagingTest extends PyEnvTestCase { final Sdk sdk = createTempSdk(sdkHome, SdkCreationType.EMPTY_SDK); List packages = null; try { - packages = PyPackageManager.getInstance(sdk).getPackages(false); + packages = PyPackageManager.getInstance(sdk).refreshAndGetPackages(false); } catch (ExecutionException ignored) { } @@ -82,7 +82,7 @@ public class PyPackagingTest extends PyEnvTestCase { assertNotNull(venvSdk); assertTrue(PythonSdkType.isVirtualEnv(venvSdk)); assertInstanceOf(PythonSdkFlavor.getPlatformIndependentFlavor(venvSdk.getHomePath()), VirtualEnvSdkFlavor.class); - final List packages = PyPackageManager.getInstance(venvSdk).getPackages(false); + final List packages = PyPackageManager.getInstance(venvSdk).refreshAndGetPackages(false); final PyPackage setuptools = findPackage("setuptools", packages); assertNotNull(setuptools); assertEquals("setuptools", setuptools.getName()); @@ -114,11 +114,11 @@ public class PyPackagingTest extends PyEnvTestCase { final Sdk venvSdk = createTempSdk(venvSdkHome, SdkCreationType.EMPTY_SDK); assertNotNull(venvSdk); final PyPackageManager manager = PyPackageManager.getInstance(venvSdk); - final List packages1 = manager.getPackages(false); + final List packages1 = manager.refreshAndGetPackages(false); // TODO: Install Markdown from a local file manager.install(list(PyRequirement.fromLine("Markdown<2.2"), new PyRequirement("httplib2")), Collections.emptyList()); - final List packages2 = manager.getPackages(false); + final List packages2 = manager.refreshAndGetPackages(false); final PyPackage markdown2 = findPackage("Markdown", packages2); assertNotNull(markdown2); assertTrue(markdown2.isInstalled()); @@ -126,7 +126,7 @@ public class PyPackagingTest extends PyEnvTestCase { assertNotNull(pip1); assertEquals("pip", pip1.getName()); manager.uninstall(list(pip1)); - final List packages3 = manager.getPackages(false); + final List packages3 = manager.refreshAndGetPackages(false); final PyPackage pip2 = findPackage("pip", packages3); assertNull(pip2); } From c65091347357141de2d7222f8f7dd23006893234 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Mon, 6 Jun 2016 15:01:41 +0300 Subject: [PATCH 015/107] PY-18039 Update level and content logging messages in package management In particular, ExecutionExceptions caused by running packaging_tool.py shouldn't be logged with the level ERROR because we don't want them in Exception Analyzer. --- .../jetbrains/python/packaging/PyPackageManagerImpl.java | 9 +++++---- .../com/jetbrains/python/packaging/PyPackageUtil.java | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java b/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java index 16130c28a1a4..e47dda08f666 100644 --- a/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java +++ b/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java @@ -216,7 +216,7 @@ public class PyPackageManagerImpl extends PyPackageManager { throw new PyExecutionException(e.getMessage(), "pip", simplifiedArgs, e.getStdout(), e.getStderr(), e.getExitCode(), e.getFixes()); } finally { - LOG.debug("Packages cache is about to be cleared because these requirements were installed: " + requirements); + LOG.debug("Packages cache is about to be refreshed because these requirements were installed: " + requirements); refreshPackagesSynchronously(); FileUtil.delete(buildDir); } @@ -242,7 +242,7 @@ public class PyPackageManagerImpl extends PyPackageManager { throw new PyExecutionException(e.getMessage(), "pip", args, e.getStdout(), e.getStderr(), e.getExitCode(), e.getFixes()); } finally { - LOG.debug("Packages cache is about to be cleared because these packages were uninstalled: " + packages); + LOG.debug("Packages cache is about to be refreshed because these packages were uninstalled: " + packages); refreshPackagesSynchronously(); } } @@ -356,6 +356,7 @@ public class PyPackageManagerImpl extends PyPackageManager { myUpdatingCache = true; try { final List packages = collectPackages(); + LOG.debug("Packages installed in " + mySdk.getName() + ": " + packages); myPackagesCache = packages; return packages; } @@ -376,7 +377,7 @@ public class PyPackageManagerImpl extends PyPackageManager { refreshAndGetPackages(true); } catch (ExecutionException e) { - LOG.error(e); + LOG.warn(e); } } @@ -534,7 +535,7 @@ public class PyPackageManagerImpl extends PyPackageManager { if (file != null) { for (VirtualFile root : roots) { if (VfsUtilCore.isAncestor(root, file, false)) { - LOG.debug("Clearing packages cache on SDK change"); + LOG.debug("Refreshing packages cache on SDK change"); ApplicationManager.getApplication().executeOnPooledThread(PyPackageManagerImpl.this::refreshPackagesSynchronously); return; } diff --git a/python/src/com/jetbrains/python/packaging/PyPackageUtil.java b/python/src/com/jetbrains/python/packaging/PyPackageUtil.java index ec0aae2e56c6..fb88e90cd2ca 100644 --- a/python/src/com/jetbrains/python/packaging/PyPackageUtil.java +++ b/python/src/com/jetbrains/python/packaging/PyPackageUtil.java @@ -285,7 +285,7 @@ public class PyPackageUtil { packagesRef.set(PyPackageManager.getInstance(sdk).refreshAndGetPackages(false)); } catch (ExecutionException e) { - LOG.error(e); + LOG.warn(e); } }); return packagesRef.get(); From d7fe9d709566a6328fd943c985148f5a127133c2 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Mon, 6 Jun 2016 15:23:11 +0300 Subject: [PATCH 016/107] PY-18039 Cleanup in PackageManagerImpl --- .../packaging/PyPackageManagerImpl.java | 64 ++++++++++--------- 1 file changed, 34 insertions(+), 30 deletions(-) diff --git a/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java b/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java index e47dda08f666..941dd15e7b78 100644 --- a/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java +++ b/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java @@ -55,16 +55,15 @@ import java.util.*; */ public class PyPackageManagerImpl extends PyPackageManager { // Python 2.4-2.5 compatible versions - public static final String SETUPTOOLS_PRE_26_VERSION = "1.4.2"; - public static final String PIP_PRE_26_VERSION = "1.1"; - public static final String VIRTUALENV_PRE_26_VERSION = "1.7.2"; + private static final String SETUPTOOLS_PRE_26_VERSION = "1.4.2"; + private static final String PIP_PRE_26_VERSION = "1.1"; + private static final String VIRTUALENV_PRE_26_VERSION = "1.7.2"; - public static final String SETUPTOOLS_VERSION = "18.1"; - public static final String PIP_VERSION = "7.1.0"; - public static final String VIRTUALENV_VERSION = "13.1.0"; + private static final String SETUPTOOLS_VERSION = "18.1"; + private static final String PIP_VERSION = "7.1.0"; + private static final String VIRTUALENV_VERSION = "13.1.0"; - public static final int OK = 0; - public static final int ERROR_NO_SETUPTOOLS = 3; + private static final int ERROR_NO_SETUPTOOLS = 3; private static final Logger LOG = Logger.getInstance(PyPackageManagerImpl.class); @@ -73,9 +72,9 @@ public class PyPackageManagerImpl extends PyPackageManager { private static final String BUILD_DIR_OPTION = "--build-dir"; - public static final String INSTALL = "install"; - public static final String UNINSTALL = "uninstall"; - public static final String UNTAR = "untar"; + private static final String INSTALL = "install"; + private static final String UNINSTALL = "uninstall"; + private static final String UNTAR = "untar"; @Nullable private volatile List myPackagesCache = null; private volatile boolean myUpdatingCache = false; @@ -118,7 +117,8 @@ public class PyPackageManagerImpl extends PyPackageManager { private boolean refreshAndCheckForSetuptools() throws ExecutionException { try { final List packages = refreshAndGetPackages(false); - return PyPackageUtil.findPackage(packages, PyPackageUtil.SETUPTOOLS) != null || PyPackageUtil.findPackage(packages, PyPackageUtil.DISTRIBUTE) != null; + return PyPackageUtil.findPackage(packages, PyPackageUtil.SETUPTOOLS) != null || + PyPackageUtil.findPackage(packages, PyPackageUtil.DISTRIBUTE) != null; } catch (PyExecutionException e) { if (e.getExitCode() == ERROR_NO_SETUPTOOLS) { @@ -170,12 +170,12 @@ public class PyPackageManagerImpl extends PyPackageManager { @Override public void install(@NotNull String requirementString) throws ExecutionException { installManagement(); - install(Collections.singletonList(PyRequirement.fromLine(requirementString)), Collections.emptyList()); + install(Collections.singletonList(PyRequirement.fromLine(requirementString)), Collections.emptyList()); } @Override public void install(@NotNull List requirements, @NotNull List extraArgs) throws ExecutionException { - final List args = new ArrayList(); + final List args = new ArrayList<>(); args.add(INSTALL); final File buildDir; try { @@ -188,7 +188,7 @@ public class PyPackageManagerImpl extends PyPackageManager { args.addAll(Arrays.asList(BUILD_DIR_OPTION, buildDir.getAbsolutePath())); } - boolean useUserSite = extraArgs.contains(USE_USER_SITE); + final boolean useUserSite = extraArgs.contains(USE_USER_SITE); final String proxyString = getProxyString(); if (proxyString != null) { @@ -203,7 +203,7 @@ public class PyPackageManagerImpl extends PyPackageManager { getHelperResult(PACKAGING_TOOL, args, !useUserSite, true, null); } catch (PyExecutionException e) { - final List simplifiedArgs = new ArrayList(); + final List simplifiedArgs = new ArrayList<>(); simplifiedArgs.add("install"); if (proxyString != null) { simplifiedArgs.add("--proxy"); @@ -222,8 +222,9 @@ public class PyPackageManagerImpl extends PyPackageManager { } } + @Override public void uninstall(@NotNull List packages) throws ExecutionException { - final List args = new ArrayList(); + final List args = new ArrayList<>(); try { args.add(UNINSTALL); boolean canModify = true; @@ -264,8 +265,8 @@ public class PyPackageManagerImpl extends PyPackageManager { catch (final ProcessNotCreatedException ex) { if (ApplicationManager.getApplication().isUnitTestMode()) { LOG.info("Not-env unit test mode, will return mock packages"); - return Lists.newArrayList(new PyPackage(PyPackageUtil.PIP, PIP_VERSION, null, Collections.emptyList()), - new PyPackage(PyPackageUtil.SETUPTOOLS, SETUPTOOLS_VERSION, null, Collections.emptyList())); + return Lists.newArrayList(new PyPackage(PyPackageUtil.PIP, PIP_VERSION, null, Collections.emptyList()), + new PyPackage(PyPackageUtil.SETUPTOOLS, SETUPTOOLS_VERSION, null, Collections.emptyList())); } else { throw ex; @@ -275,10 +276,11 @@ public class PyPackageManagerImpl extends PyPackageManager { return parsePackagingToolOutput(output); } + @Override @Nullable public Set getDependents(@NotNull PyPackage pkg) throws ExecutionException { final List packages = refreshAndGetPackages(false); - final Set dependents = new HashSet(); + final Set dependents = new HashSet<>(); for (PyPackage p : packages) { final List requirements = p.getRequirements(); for (PyRequirement requirement : requirements) { @@ -290,9 +292,10 @@ public class PyPackageManagerImpl extends PyPackageManager { return dependents; } + @Override @NotNull public String createVirtualEnv(@NotNull String destinationDir, boolean useGlobalSite) throws ExecutionException { - final List args = new ArrayList(); + final List args = new ArrayList<>(); final Sdk sdk = getSdk(); final LanguageLevel languageLevel = PythonSdkType.getLanguageLevelForSdk(sdk); final boolean usePyVenv = languageLevel.isAtLeast(LanguageLevel.PYTHON33); @@ -338,6 +341,7 @@ public class PyPackageManagerImpl extends PyPackageManager { return path; } + @Override @Nullable public List getRequirements(@NotNull Module module) { return Optional @@ -346,7 +350,7 @@ public class PyPackageManagerImpl extends PyPackageManager { } -// public List refreshAndGetPackagesIfNotInProgress(boolean alwaysRefresh) throws ExecutionException + // public List refreshAndGetPackagesIfNotInProgress(boolean alwaysRefresh) throws ExecutionException @Override @NotNull @@ -356,7 +360,7 @@ public class PyPackageManagerImpl extends PyPackageManager { myUpdatingCache = true; try { final List packages = collectPackages(); - LOG.debug("Packages installed in " + mySdk.getName() + ": " + packages); + LOG.debug("Packages installed in " + mySdk.getName() + ": " + packages); myPackagesCache = packages; return packages; } @@ -436,7 +440,7 @@ public class PyPackageManagerImpl extends PyPackageManager { if (workingDir == null) { workingDir = new File(homePath).getParent(); } - final List cmdline = new ArrayList(); + final List cmdline = new ArrayList<>(); cmdline.add(homePath); cmdline.add(helperPath); cmdline.addAll(args); @@ -446,11 +450,11 @@ public class PyPackageManagerImpl extends PyPackageManager { final boolean useSudo = !canCreate && !SystemInfo.isWindows && askForSudo; try { - final Map environment = new HashMap(System.getenv()); + final Map environment = new HashMap<>(System.getenv()); PythonEnvUtil.setPythonUnbuffered(environment); PythonEnvUtil.setPythonDontWriteBytecode(environment); - GeneralCommandLine commandLine = new GeneralCommandLine(cmdline).withWorkDirectory(workingDir).withEnvironment(environment); - Process process; + final GeneralCommandLine commandLine = new GeneralCommandLine(cmdline).withWorkDirectory(workingDir).withEnvironment(environment); + final Process process; if (useSudo) { process = ExecUtil.sudo(commandLine, "Please enter your password to make changes in system packages: "); } @@ -503,16 +507,16 @@ public class PyPackageManagerImpl extends PyPackageManager { @NotNull private static List parsePackagingToolOutput(@NotNull String s) throws ExecutionException { final String[] lines = StringUtil.splitByLines(s); - final List packages = new ArrayList(); + final List packages = new ArrayList<>(); for (String line : lines) { final List fields = StringUtil.split(line, "\t"); if (fields.size() < 3) { - throw new PyExecutionException("Invalid output format", PACKAGING_TOOL, Collections.emptyList()); + throw new PyExecutionException("Invalid output format", PACKAGING_TOOL, Collections.emptyList()); } final String name = fields.get(0); final String version = fields.get(1); final String location = fields.get(2); - final List requirements = new ArrayList(); + final List requirements = new ArrayList<>(); if (fields.size() >= 4) { final String requiresLine = fields.get(3); final String requiresSpec = StringUtil.join(StringUtil.split(requiresLine, ":"), "\n"); From 0a037df9beed61ed88a5c4453d9f7ca93f470909 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Mon, 6 Jun 2016 22:08:36 +0300 Subject: [PATCH 017/107] PY-18039 Throughout debug logging for PyPackageManager and helper methods When we either launch packaging_tool.py or attempt to show modal dialog the stacktrace of the call site is added to debug messages. --- python/src/com/jetbrains/python/PyBundle.properties | 1 + .../com/jetbrains/python/packaging/PyPackageManagerImpl.java | 1 + python/src/com/jetbrains/python/packaging/PyPackageUtil.java | 4 +++- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/python/src/com/jetbrains/python/PyBundle.properties b/python/src/com/jetbrains/python/PyBundle.properties index 62055e41c78f..d1e327049b9a 100644 --- a/python/src/com/jetbrains/python/PyBundle.properties +++ b/python/src/com/jetbrains/python/PyBundle.properties @@ -890,6 +890,7 @@ sdk.gen.reading.versions.file=Reading versions file... sdk.gen.notify.converting.old.skels=Converting old skeletons sdk.gen.notify.converting.text=Skeletons of binary modules seem to be from an older version.
These will be fully re-generated, which will take some time, but will happen only once.
Next time you open the project, only skeletons of new or updated binary modules will be re-generated. sdk.gen.updating.interpreter=Updating Python Interpreter +sdk.scanning.installed.packages=Scanning Installed Packages sdk.gen.stubs.for.binary.modules=Generate stubs for binary module {0} # Active SDK configurable and related dialogs diff --git a/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java b/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java index 941dd15e7b78..a82dfb40e0c9 100644 --- a/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java +++ b/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java @@ -260,6 +260,7 @@ public class PyPackageManagerImpl extends PyPackageManager { protected List collectPackages() throws ExecutionException { final String output; try { + LOG.debug("Collecting installed packages for the SDK " + mySdk.getName(), new Throwable()); output = getHelperResult(PACKAGING_TOOL, Collections.singletonList("list"), false, false, null); } catch (final ProcessNotCreatedException ex) { diff --git a/python/src/com/jetbrains/python/packaging/PyPackageUtil.java b/python/src/com/jetbrains/python/packaging/PyPackageUtil.java index fb88e90cd2ca..214b5694719b 100644 --- a/python/src/com/jetbrains/python/packaging/PyPackageUtil.java +++ b/python/src/com/jetbrains/python/packaging/PyPackageUtil.java @@ -34,6 +34,7 @@ import com.intellij.openapi.vfs.VirtualFileVisitor; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiManager; +import com.jetbrains.python.PyBundle; import com.jetbrains.python.PyNames; import com.jetbrains.python.codeInsight.controlflow.ScopeOwner; import com.jetbrains.python.packaging.setupPy.SetupTaskIntrospector; @@ -279,7 +280,8 @@ public class PyPackageUtil { @Nullable public static List refreshAndGetPackagesModally(@NotNull Sdk sdk) { final Ref> packagesRef = Ref.create(); - PyUtil.runWithProgress(null, "Scanning Installed Packages", true, false, indicator -> { + LOG.debug("Showing modal progress for collecting installed packages", new Throwable()); + PyUtil.runWithProgress(null, PyBundle.message("sdk.scanning.installed.packages"), true, false, indicator -> { indicator.setIndeterminate(true); try { packagesRef.set(PyPackageManager.getInstance(sdk).refreshAndGetPackages(false)); From 1e2d9ca81d3fb69b20406a394ddd4bb78e2fb27a Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Mon, 6 Jun 2016 22:12:20 +0300 Subject: [PATCH 018/107] PY-18039 Run packaging_tool.py once to detect IPython version if necessary In theory IPython cell can be run before PythonSdkUpdater startup activity finishes updating packaging cache when a project is opened. --- .../src/org/jetbrains/plugins/ipnb/format/IpnbParser.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/ipnb/src/org/jetbrains/plugins/ipnb/format/IpnbParser.java b/python/ipnb/src/org/jetbrains/plugins/ipnb/format/IpnbParser.java index 1076c0753244..4d19bea816a4 100644 --- a/python/ipnb/src/org/jetbrains/plugins/ipnb/format/IpnbParser.java +++ b/python/ipnb/src/org/jetbrains/plugins/ipnb/format/IpnbParser.java @@ -15,7 +15,6 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.text.VersionComparatorUtil; import com.jetbrains.python.packaging.PyPackage; -import com.jetbrains.python.packaging.PyPackageManager; import com.jetbrains.python.packaging.PyPackageUtil; import com.jetbrains.python.sdk.PythonSdkType; import org.jetbrains.annotations.NotNull; @@ -79,7 +78,8 @@ public class IpnbParser { if (module != null) { final Sdk sdk = PythonSdkType.findPythonSdk(module); if (sdk != null) { - final List packages = PyPackageManager.getInstance(sdk).getPackages(); + // It should be called first before IpnbConnectionManager#startIpythonServer() + final List packages = PyPackageUtil.refreshAndGetPackagesModally(sdk); final PyPackage ipython = packages != null ? PyPackageUtil.findPackage(packages, "ipython") : null; final PyPackage jupyter = packages != null ? PyPackageUtil.findPackage(packages, "jupyter") : null; if (jupyter == null && ipython != null && VersionComparatorUtil.compare(ipython.getVersion(), "3.0") <= 0) { From 38731649c68beb17d0ea74f599ff2ef7bad0e954 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Wed, 8 Jun 2016 21:42:18 +0300 Subject: [PATCH 019/107] PY-18039 PyPackageManager#getDependents() returns @NotNull value --- .../src/com/jetbrains/python/packaging/PyPackageManager.java | 2 +- .../com/jetbrains/python/packaging/PyPackageManagerImpl.java | 2 +- .../com/jetbrains/python/packaging/PyPackageManagersImpl.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/python/openapi/src/com/jetbrains/python/packaging/PyPackageManager.java b/python/openapi/src/com/jetbrains/python/packaging/PyPackageManager.java index a94da215513b..a500532496eb 100644 --- a/python/openapi/src/com/jetbrains/python/packaging/PyPackageManager.java +++ b/python/openapi/src/com/jetbrains/python/packaging/PyPackageManager.java @@ -62,6 +62,6 @@ public abstract class PyPackageManager { @Nullable public abstract List getRequirements(@NotNull Module module); - @Nullable + @NotNull public abstract Set getDependents(@NotNull PyPackage pkg) throws ExecutionException; } diff --git a/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java b/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java index a82dfb40e0c9..da4e302f641f 100644 --- a/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java +++ b/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java @@ -278,7 +278,7 @@ public class PyPackageManagerImpl extends PyPackageManager { } @Override - @Nullable + @NotNull public Set getDependents(@NotNull PyPackage pkg) throws ExecutionException { final List packages = refreshAndGetPackages(false); final Set dependents = new HashSet<>(); diff --git a/python/src/com/jetbrains/python/packaging/PyPackageManagersImpl.java b/python/src/com/jetbrains/python/packaging/PyPackageManagersImpl.java index 163b75476a31..6f0a8cee52c2 100644 --- a/python/src/com/jetbrains/python/packaging/PyPackageManagersImpl.java +++ b/python/src/com/jetbrains/python/packaging/PyPackageManagersImpl.java @@ -148,7 +148,7 @@ public class PyPackageManagersImpl extends PyPackageManagers { return null; } - @Nullable + @NotNull @Override public Set getDependents(@NotNull PyPackage pkg) throws ExecutionException { throw new ExecutionException(getErrorMessage()); From fe70160b18dc3ffe5d3208c0e0ba73b1b16cb36b Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Thu, 16 Jun 2016 12:49:24 +0300 Subject: [PATCH 020/107] IDEA-CR-10973 Fix excess calls to checkValid() in Python new project wizard --- .../python/PythonSdkChooserCombo.java | 14 ++--- .../actions/ProjectSpecificSettingsStep.java | 63 +++++++------------ 2 files changed, 25 insertions(+), 52 deletions(-) diff --git a/python/ide/src/com/jetbrains/python/PythonSdkChooserCombo.java b/python/ide/src/com/jetbrains/python/PythonSdkChooserCombo.java index 7c9335ba62bd..bd132745ff05 100644 --- a/python/ide/src/com/jetbrains/python/PythonSdkChooserCombo.java +++ b/python/ide/src/com/jetbrains/python/PythonSdkChooserCombo.java @@ -20,16 +20,15 @@ import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.project.Project; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.roots.ui.configuration.projectRoot.ProjectSdksModel; +import com.intellij.openapi.ui.ComboBox; import com.intellij.openapi.util.Condition; import com.intellij.ui.CollectionComboBoxModel; import com.intellij.ui.ComboboxWithBrowseButton; -import com.intellij.util.NullableConsumer; import com.intellij.util.containers.ContainerUtil; import com.jetbrains.python.configuration.PyConfigurableInterpreterList; import com.jetbrains.python.sdk.PySdkListCellRenderer; import com.jetbrains.python.sdk.PySdkService; import com.jetbrains.python.sdk.PythonSdkDetailsStep; -import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.event.ActionEvent; @@ -41,17 +40,12 @@ import java.util.List; */ public class PythonSdkChooserCombo extends ComboboxWithBrowseButton { private final List myChangedListeners = ContainerUtil.createLockFreeCopyOnWriteList(); - private static final Logger LOG = Logger.getInstance("#com.jetbrains.python.PythonSdkChooserCombo"); + private static final Logger LOG = Logger.getInstance(PythonSdkChooserCombo.class); @SuppressWarnings("unchecked") public PythonSdkChooserCombo(final Project project, List sdks, final Condition acceptableSdkCondition) { - Sdk initialSelection = null; - for (Sdk sdk : sdks) { - if (acceptableSdkCondition.value(sdk)) { - initialSelection = sdk; - break; - } - } + super(new ComboBox<>()); + final Sdk initialSelection = ContainerUtil.find(sdks, acceptableSdkCondition); final JComboBox comboBox = getComboBox(); comboBox.setModel(new CollectionComboBoxModel(sdks, initialSelection)); comboBox.setRenderer(new PySdkListCellRenderer(true)); diff --git a/python/ide/src/com/jetbrains/python/newProject/actions/ProjectSpecificSettingsStep.java b/python/ide/src/com/jetbrains/python/newProject/actions/ProjectSpecificSettingsStep.java index 93ee06c1a796..1bdc5359402e 100644 --- a/python/ide/src/com/jetbrains/python/newProject/actions/ProjectSpecificSettingsStep.java +++ b/python/ide/src/com/jetbrains/python/newProject/actions/ProjectSpecificSettingsStep.java @@ -28,7 +28,9 @@ import com.intellij.platform.DirectoryProjectGenerator; import com.intellij.ui.DocumentAdapter; import com.intellij.ui.HideableDecorator; import com.intellij.util.NullableConsumer; +import com.intellij.util.PathUtil; import com.intellij.util.ui.UIUtil; +import com.intellij.util.ui.update.UiNotifyConnector; import com.jetbrains.python.PythonSdkChooserCombo; import com.jetbrains.python.configuration.PyConfigurableInterpreterList; import com.jetbrains.python.configuration.VirtualEnvProjectFilter; @@ -46,9 +48,7 @@ import javax.swing.event.DocumentEvent; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.io.File; +import java.awt.event.ItemEvent; import java.util.ArrayList; import java.util.List; @@ -117,20 +117,28 @@ public class ProjectSpecificSettingsStep extends ProjectSettingsStepBase impleme protected void registerValidators() { super.registerValidators(); if (myProjectGenerator instanceof PythonProjectGenerator && !((PythonProjectGenerator)myProjectGenerator).hideInterpreter()) { - mySdkCombo.getComboBox().addPropertyChangeListener(new PropertyChangeListener() { + myLocationField.getTextField().getDocument().addDocumentListener(new DocumentAdapter() { @Override - public void propertyChange(PropertyChangeEvent event) { + protected void textChanged(DocumentEvent e) { + final String path = myLocationField.getText().trim(); + ((PythonProjectGenerator)myProjectGenerator).locationChanged(PathUtil.getFileName(path)); + } + }); + + mySdkCombo.getComboBox().addItemListener(e -> { + if (e.getStateChange() == ItemEvent.SELECTED) { checkValid(); } }); - final ActionListener listener = new ActionListener() { - @Override - public void actionPerformed(ActionEvent event) { - checkValid(); - } - }; - mySdkCombo.getComboBox().addActionListener(listener); - mySdkCombo.addActionListener(listener); + UiNotifyConnector.doWhenFirstShown(mySdkCombo, this::checkValid); + } + } + + @Override + protected void initGeneratorListeners() { + super.initGeneratorListeners(); + if (myProjectGenerator instanceof PythonProjectGenerator) { + ((PythonProjectGenerator)myProjectGenerator).addSettingsStateListener(this::checkValid); } } @@ -277,33 +285,4 @@ public class ProjectSpecificSettingsStep extends ProjectSettingsStepBase impleme return LabeledComponent.create(mySdkCombo, "Interpreter", BorderLayout.WEST); } - - @Override - protected void initGeneratorListeners() { - super.initGeneratorListeners(); - if (myProjectGenerator instanceof PythonProjectGenerator) { - ((PythonProjectGenerator)myProjectGenerator).addSettingsStateListener(new PythonProjectGenerator.SettingsListener() { - @Override - public void stateChanged() { - checkValid(); - } - }); - - myErrorLabel.addMouseListener(((PythonProjectGenerator)myProjectGenerator).getErrorLabelMouseListener()); - } - myLocationField.getTextField().getDocument().addDocumentListener(new DocumentAdapter() { - @Override - protected void textChanged(DocumentEvent e) { - if (myProjectGenerator instanceof PythonProjectGenerator) { - String path = myLocationField.getText().trim(); - path = StringUtil.trimEnd(path, File.separator); - int ind = path.lastIndexOf(File.separator); - if (ind != -1) { - String projectName = path.substring(ind + 1, path.length()); - ((PythonProjectGenerator)myProjectGenerator).locationChanged(projectName); - } - } - } - }); - } } From ee7a87e1df1eb06e305601f8e7c27eb5731d8c95 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Fri, 17 Jun 2016 15:19:13 +0300 Subject: [PATCH 021/107] IDEA-CR-10973 Don't lose ItemEvent for SDK created in PythonSdkChooserCombo It might happen because ProjectSdkModel copies added SDK internally and that original SDK is no longer in the list returned by PyConfigurableInterpreterList which is then used to initialize the model of the combo box in the project wizard. As a result passing that SDK to setSelectedItem() has no effect, SDK doesn't appear in the combo box and checkValid() isn't invoked either. --- .../src/com/jetbrains/python/PythonSdkChooserCombo.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/python/ide/src/com/jetbrains/python/PythonSdkChooserCombo.java b/python/ide/src/com/jetbrains/python/PythonSdkChooserCombo.java index bd132745ff05..032bda6b3741 100644 --- a/python/ide/src/com/jetbrains/python/PythonSdkChooserCombo.java +++ b/python/ide/src/com/jetbrains/python/PythonSdkChooserCombo.java @@ -72,6 +72,9 @@ public class PythonSdkChooserCombo extends ComboboxWithBrowseButton { private void showOptions(final Project project) { final PyConfigurableInterpreterList interpreterList = PyConfigurableInterpreterList.getInstance(project); final Sdk[] sdks = interpreterList.getModel().getSdks(); + //noinspection unchecked + final JComboBox comboBox = getComboBox(); + final Sdk oldSelectedSdk = (Sdk)comboBox.getSelectedItem(); PythonSdkDetailsStep.show(project, sdks, null, this, getButton().getLocationOnScreen(), sdk -> { if (sdk == null) return; final PySdkService sdkService = PySdkService.getInstance(); @@ -87,8 +90,10 @@ public class PythonSdkChooserCombo extends ComboboxWithBrowseButton { LOG.error("Error adding new python interpreter " + e.getMessage()); } } - //noinspection unchecked - getComboBox().setModel(new CollectionComboBoxModel(interpreterList.getAllPythonSdks(), sdk)); + final List committedSdks = interpreterList.getAllPythonSdks(); + final Sdk copiedSdk = interpreterList.getModel().findSdk(sdk.getName()); + comboBox.setModel(new CollectionComboBoxModel<>(committedSdks, oldSelectedSdk)); + comboBox.setSelectedItem(copiedSdk); }, true); } From 9df946a675f9a907bc7e86c0484e029c06b5ffe0 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Thu, 16 Jun 2016 20:25:53 +0300 Subject: [PATCH 022/107] IDEA-CR-10973 If packaging_tool.py fails, initialize cache with empty list This way we won't keep calling the script over and over again via PyPackageUtil#refreshAndGetPackagesModally() (e.g. in various project wizards) if for some reason it doesn't succeed first time. --- .../jetbrains/python/packaging/PyPackageManagerImpl.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java b/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java index da4e302f641f..2a4333cc84f8 100644 --- a/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java +++ b/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java @@ -363,7 +363,11 @@ public class PyPackageManagerImpl extends PyPackageManager { final List packages = collectPackages(); LOG.debug("Packages installed in " + mySdk.getName() + ": " + packages); myPackagesCache = packages; - return packages; + return Collections.unmodifiableList(packages); + } + catch (ExecutionException e) { + myPackagesCache = Collections.emptyList(); + throw e; } finally { myUpdatingCache = false; From 282f7f1641ea5aa938fa45c6fcb4c1de279b3596 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Fri, 17 Jun 2016 14:42:52 +0300 Subject: [PATCH 023/107] IDEA-CR-10973 Packages are always updated in "Project interpreter" configurable I've also removed excess calls to refreshAndGetPackages() in PyActiveSdkConfigurable. It's not necessary to call it in #setSelectedSdk() since item listener on the combo box updates list of installed packages and notifications at the bottom anyway after selected value has been changed. --- .../PyActiveSdkConfigurable.java | 23 +++++-------------- .../ui/PyPackageManagementService.java | 2 +- 2 files changed, 7 insertions(+), 18 deletions(-) diff --git a/python/python-community-configure/src/com/jetbrains/python/configuration/PyActiveSdkConfigurable.java b/python/python-community-configure/src/com/jetbrains/python/configuration/PyActiveSdkConfigurable.java index d15ae055eaec..41be0e419608 100644 --- a/python/python-community-configure/src/com/jetbrains/python/configuration/PyActiveSdkConfigurable.java +++ b/python/python-community-configure/src/com/jetbrains/python/configuration/PyActiveSdkConfigurable.java @@ -51,8 +51,7 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; import java.util.ArrayList; import java.util.List; import java.util.Set; @@ -195,24 +194,16 @@ public class PyActiveSdkConfigurable implements UnnamedConfigurable { myInitialSdkSet = myProjectSdksModel.getProjectSdks().keySet(); myProjectSdksModel.addListener(mySdkModelListener); - mySdkCombo.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { + mySdkCombo.addItemListener(e -> { + if (e.getStateChange() == ItemEvent.SELECTED) { final Sdk selectedSdk = (Sdk)mySdkCombo.getSelectedItem(); - myPackagesPanel.updatePackages(selectedSdk != null ? - PyPackageManagers.getInstance().getManagementService(myProject, selectedSdk) : null); + final PyPackageManagers packageManagers = PyPackageManagers.getInstance(); + myPackagesPanel.updatePackages(selectedSdk != null ? packageManagers.getManagementService(myProject, selectedSdk) : null); myPackagesPanel.updateNotifications(selectedSdk); } }); myAddSdkCallback = new SdkAddedCallback(); - myDetailsButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - showDetails(); - } - } - ); - + myDetailsButton.addActionListener(e -> showDetails()); } private void showDetails() { @@ -295,8 +286,6 @@ public class PyActiveSdkConfigurable implements UnnamedConfigurable { else { mySdkCombo.getModel().setSelectedItem(selectedSdk == null ? null : myProjectSdksModel.findSdk(selectedSdk.getName())); } - myPackagesPanel.updatePackages(selectedSdk != null ? PyPackageManagers.getInstance().getManagementService(myProject, selectedSdk) : null); - myPackagesPanel.updateNotifications(selectedSdk); } private void rehighlightVersionSpecific(@Nullable final Sdk newSdk, @Nullable final Sdk prevSdk) { diff --git a/python/src/com/jetbrains/python/packaging/ui/PyPackageManagementService.java b/python/src/com/jetbrains/python/packaging/ui/PyPackageManagementService.java index 2ffc54f888fa..78332f1fdba4 100644 --- a/python/src/com/jetbrains/python/packaging/ui/PyPackageManagementService.java +++ b/python/src/com/jetbrains/python/packaging/ui/PyPackageManagementService.java @@ -144,7 +144,7 @@ public class PyPackageManagementService extends PackageManagementServiceEx { final PyPackageManager manager = PyPackageManager.getInstance(mySdk); final List packages; try { - packages = Lists.newArrayList(manager.refreshAndGetPackages(false)); + packages = Lists.newArrayList(manager.refreshAndGetPackages(true)); } catch (ExecutionException e) { throw new IOException(e); From af8c00c744814fd8ad6bf1b0829fb267336e3630 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Wed, 22 Jun 2016 17:19:45 +0300 Subject: [PATCH 024/107] IDEA-CR-10973 VFSTestListener updates packages synchronously, one refresh at time --- .../packaging/PyPackageManagerImpl.java | 19 ++---------- .../python/packaging/PyPackageUtil.java | 31 +++++++++++++++++++ .../PyIntegratedToolsProjectConfigurator.java | 26 +++++++++------- .../testing/VFSTestFrameworkListener.java | 17 +++++++--- 4 files changed, 61 insertions(+), 32 deletions(-) diff --git a/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java b/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java index 2a4333cc84f8..fce9cffa7961 100644 --- a/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java +++ b/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java @@ -49,6 +49,7 @@ import org.jetbrains.annotations.Nullable; import java.io.File; import java.io.IOException; import java.util.*; +import java.util.concurrent.atomic.AtomicBoolean; /** * @author vlan @@ -77,7 +78,7 @@ public class PyPackageManagerImpl extends PyPackageManager { private static final String UNTAR = "untar"; @Nullable private volatile List myPackagesCache = null; - private volatile boolean myUpdatingCache = false; + private final AtomicBoolean myUpdatingCache = new AtomicBoolean(false); @NotNull final private Sdk mySdk; @@ -358,7 +359,6 @@ public class PyPackageManagerImpl extends PyPackageManager { public List refreshAndGetPackages(boolean alwaysRefresh) throws ExecutionException { final List currentPackages = myPackagesCache; if (alwaysRefresh || currentPackages == null) { - myUpdatingCache = true; try { final List packages = collectPackages(); LOG.debug("Packages installed in " + mySdk.getName() + ": " + packages); @@ -369,25 +369,12 @@ public class PyPackageManagerImpl extends PyPackageManager { myPackagesCache = Collections.emptyList(); throw e; } - finally { - myUpdatingCache = false; - } } return Collections.unmodifiableList(currentPackages); } private void refreshPackagesSynchronously() { - assert !ApplicationManager.getApplication().isDispatchThread(); - if (myUpdatingCache) { - return; - } - try { - LOG.info("Refreshing installed packages for SDK " + mySdk.getHomePath()); - refreshAndGetPackages(true); - } - catch (ExecutionException e) { - LOG.warn(e); - } + PyPackageUtil.updatePackagesSynchronouslyWithGuard(this, myUpdatingCache); } @Nullable diff --git a/python/src/com/jetbrains/python/packaging/PyPackageUtil.java b/python/src/com/jetbrains/python/packaging/PyPackageUtil.java index 214b5694719b..b1e2ffe071d5 100644 --- a/python/src/com/jetbrains/python/packaging/PyPackageUtil.java +++ b/python/src/com/jetbrains/python/packaging/PyPackageUtil.java @@ -18,6 +18,7 @@ package com.jetbrains.python.packaging; import com.intellij.openapi.editor.Document; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.execution.ExecutionException; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; @@ -51,6 +52,7 @@ import org.jetbrains.annotations.Nullable; import java.util.*; import java.util.stream.Collectors; import java.util.stream.Stream; +import java.util.concurrent.atomic.AtomicBoolean; /** * @author vlan @@ -293,6 +295,35 @@ public class PyPackageUtil { return packagesRef.get(); } + /** + * Run unconditional update of the list of packages installed in SDK. Normally only one such of updates should run at time. + * This behavior in enforced by the parameter isUpdating. + * + * @param manager package manager for SDK + * @param isUpdating flag indicating whether another refresh is already running + * @return whether packages were refreshed successfully, e.g. this update wasn't cancelled because of another refresh in progress + */ + public static boolean updatePackagesSynchronouslyWithGuard(@NotNull PyPackageManager manager, @NotNull AtomicBoolean isUpdating) { + assert !ApplicationManager.getApplication().isDispatchThread(); + if (!isUpdating.compareAndSet(false, true)) { + return false; + } + try { + if (manager instanceof PyPackageManagerImpl) { + LOG.info("Refreshing installed packages for SDK " + ((PyPackageManagerImpl)manager).getSdk().getHomePath()); + } + manager.refreshAndGetPackages(true); + } + catch (ExecutionException e) { + LOG.warn(e); + } + finally { + isUpdating.set(false); + } + return true; + } + + @Nullable public static PyPackage findPackage(@NotNull List packages, @NotNull String name) { for (PyPackage pkg : packages) { diff --git a/python/src/com/jetbrains/python/testing/PyIntegratedToolsProjectConfigurator.java b/python/src/com/jetbrains/python/testing/PyIntegratedToolsProjectConfigurator.java index 3ad43f6d6c86..8cf525865f0f 100644 --- a/python/src/com/jetbrains/python/testing/PyIntegratedToolsProjectConfigurator.java +++ b/python/src/com/jetbrains/python/testing/PyIntegratedToolsProjectConfigurator.java @@ -38,6 +38,7 @@ import com.jetbrains.python.PythonModuleTypeBase; import com.jetbrains.python.documentation.PyDocumentationSettings; import com.jetbrains.python.documentation.docstrings.DocStringFormat; import com.jetbrains.python.documentation.docstrings.DocStringUtil; +import com.jetbrains.python.packaging.PyPackage; import com.jetbrains.python.packaging.PyPackageUtil; import com.jetbrains.python.psi.*; import com.jetbrains.python.sdk.PythonSdkType; @@ -114,17 +115,20 @@ public class PyIntegratedToolsProjectConfigurator implements DirectoryProjectCon //check if installed in sdk final Sdk sdk = PythonSdkType.findPythonSdk(module); if (sdk != null && sdk.getSdkType() instanceof PythonSdkType) { - final Boolean nose = VFSTestFrameworkListener.isTestFrameworkInstalled(sdk, PyNames.NOSE_TEST); - final Boolean pytest = VFSTestFrameworkListener.isTestFrameworkInstalled(sdk, PyNames.PY_TEST); - final Boolean attest = VFSTestFrameworkListener.isTestFrameworkInstalled(sdk, PyNames.AT_TEST); - if (nose != null && nose) - testRunner = PythonTestConfigurationsModel.PYTHONS_NOSETEST_NAME; - else if (pytest != null && pytest) - testRunner = PythonTestConfigurationsModel.PY_TEST_NAME; - else if (attest != null && attest) - testRunner = PythonTestConfigurationsModel.PYTHONS_ATTEST_NAME; - if (!testRunner.isEmpty()) { - LOG.debug("Test runner '" + testRunner + "' was detected from SDK " + sdk); + final List packages = PyPackageUtil.refreshAndGetPackagesModally(sdk); + if (packages != null) { + final boolean nose = PyPackageUtil.findPackage(packages, PyNames.NOSE_TEST) != null; + final boolean pytest = PyPackageUtil.findPackage(packages, PyNames.PY_TEST) != null; + final boolean attest = PyPackageUtil.findPackage(packages, PyNames.AT_TEST) != null; + if (nose) + testRunner = PythonTestConfigurationsModel.PYTHONS_NOSETEST_NAME; + else if (pytest) + testRunner = PythonTestConfigurationsModel.PY_TEST_NAME; + else if (attest) + testRunner = PythonTestConfigurationsModel.PYTHONS_ATTEST_NAME; + if (!testRunner.isEmpty()) { + LOG.debug("Test runner '" + testRunner + "' was detected from SDK " + sdk); + } } } } diff --git a/python/src/com/jetbrains/python/testing/VFSTestFrameworkListener.java b/python/src/com/jetbrains/python/testing/VFSTestFrameworkListener.java index 50c3aac817d8..d193dc2aabc9 100644 --- a/python/src/com/jetbrains/python/testing/VFSTestFrameworkListener.java +++ b/python/src/com/jetbrains/python/testing/VFSTestFrameworkListener.java @@ -33,18 +33,21 @@ import com.intellij.util.ui.update.MergingUpdateQueue; import com.intellij.util.ui.update.Update; import com.jetbrains.python.PyNames; import com.jetbrains.python.packaging.PyPackage; +import com.jetbrains.python.packaging.PyPackageManager; import com.jetbrains.python.packaging.PyPackageUtil; import com.jetbrains.python.sdk.PySdkUtil; import com.jetbrains.python.sdk.PythonSdkType; import org.jetbrains.annotations.NotNull; import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; /** * User: catherine */ public class VFSTestFrameworkListener { private static final Logger LOG = Logger.getInstance("#com.jetbrains.python.testing.VFSTestFrameworkListener"); + private final AtomicBoolean myIsUpdating = new AtomicBoolean(false); private final MergingUpdateQueue myQueue; private final PyTestFrameworkService myService; @@ -111,16 +114,20 @@ public class VFSTestFrameworkListener { /** * @return null if we can't be sure */ - public static Boolean isTestFrameworkInstalled(Sdk sdk, String testPackageName) { + public Boolean isTestFrameworkInstalled(Sdk sdk, String testPackageName) { if (sdk == null || StringUtil.isEmptyOrSpaces(sdk.getHomePath())) { LOG.info("Searching test runner in empty sdk"); return null; } - final List packages = PyPackageUtil.refreshAndGetPackagesModally(sdk); - if (packages == null) { - return null; + final PyPackageManager manager = PyPackageManager.getInstance(sdk); + final boolean refreshed = PyPackageUtil.updatePackagesSynchronouslyWithGuard(manager, myIsUpdating); + if (refreshed) { + final List packages = manager.getPackages(); + if (packages != null) { + return PyPackageUtil.findPackage(packages, testPackageName) != null; + } } - return PyPackageUtil.findPackage(packages, testPackageName) != null; + return null; } public static VFSTestFrameworkListener getInstance() { From 3dfac0df47cef0ec010fcd8e3f6978521bd099f2 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Thu, 23 Jun 2016 17:21:10 +0300 Subject: [PATCH 025/107] PY-18039 Fix PyPackageRequirementsInspectionTest It failed because packages cache wasn't initialized before the tests and "Package requirements" inspection doesn't warn about anything in this case. --- .../PyPackageRequirementsInspectionTest.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/python/testSrc/com/jetbrains/python/inspections/PyPackageRequirementsInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyPackageRequirementsInspectionTest.java index 00d5eee2330e..554c34a904cf 100644 --- a/python/testSrc/com/jetbrains/python/inspections/PyPackageRequirementsInspectionTest.java +++ b/python/testSrc/com/jetbrains/python/inspections/PyPackageRequirementsInspectionTest.java @@ -15,14 +15,25 @@ */ package com.jetbrains.python.inspections; +import com.intellij.openapi.projectRoots.Sdk; import com.jetbrains.python.fixtures.PyTestCase; +import com.jetbrains.python.packaging.PyPackageManager; import com.jetbrains.python.psi.LanguageLevel; +import com.jetbrains.python.sdk.PythonSdkType; import org.jetbrains.annotations.NotNull; /** * @author vlan */ public class PyPackageRequirementsInspectionTest extends PyTestCase { + @Override + public void setUp() throws Exception { + super.setUp(); + final Sdk sdk = PythonSdkType.findPythonSdk(myFixture.getModule()); + assertNotNull(sdk); + PyPackageManager.getInstance(sdk).refreshAndGetPackages(true); + } + public void testPartiallySatisfiedRequirementsTxt() { doTest("test1.py"); } From 9a5e20cca0f79ef2e5fbe4c3132bf9cbb04736de Mon Sep 17 00:00:00 2001 From: "Ilya.Kazakevich" Date: Thu, 23 Jun 2016 17:51:52 +0300 Subject: [PATCH 026/107] PY-19907: check ``startTime`` property type. If it has wrong type, that means user has custom property. Fail and report this fact. --- python/helpers/pycharm/tcunittest.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/python/helpers/pycharm/tcunittest.py b/python/helpers/pycharm/tcunittest.py index 185c12898a1e..1418bfa487ed 100644 --- a/python/helpers/pycharm/tcunittest.py +++ b/python/helpers/pycharm/tcunittest.py @@ -211,6 +211,8 @@ class TeamcityTestResult(TestResult): def __getDuration(self, test): start = getattr(test, "startTime", datetime.datetime.now()) + assert isinstance(start, datetime.datetime), \ + "You testcase has property named 'startTime' (value {0}). Please, rename it".format(start) d = datetime.datetime.now() - start duration = d.microseconds / 1000 + d.seconds * 1000 + d.days * 86400000 return duration From 3c3e9a324e9df2dad7ee422103ef91c25586e129 Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Thu, 23 Jun 2016 18:01:55 +0300 Subject: [PATCH 027/107] EA-84725 - assert: FrameWrapper.getFrame --- .../openapi/vcs/history/impl/VcsSelectionHistoryDialog.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/history/impl/VcsSelectionHistoryDialog.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/history/impl/VcsSelectionHistoryDialog.java index 6f9cb5d3c0f8..891108da0b8e 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/history/impl/VcsSelectionHistoryDialog.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/history/impl/VcsSelectionHistoryDialog.java @@ -228,7 +228,8 @@ public class VcsSelectionHistoryDialog extends FrameWrapper implements DataProvi @Override protected void notifyError(@NotNull VcsException e) { SwingUtilities.invokeLater(() -> { - if (!VcsSelectionHistoryDialog.this.getFrame().isShowing()) return; + VcsSelectionHistoryDialog dialog = VcsSelectionHistoryDialog.this; + if (dialog.isDisposed() || !dialog.getFrame().isShowing()) return; PopupUtil.showBalloonForComponent(mySplitter, canNoLoadMessage(e), MessageType.ERROR, true, myProject); }); } From 0acd1f437f08b6647d28c74203ddbca8ae389e46 Mon Sep 17 00:00:00 2001 From: Daniil Ovchinnikov Date: Thu, 23 Jun 2016 17:55:47 +0300 Subject: [PATCH 028/107] [groovy] set navigation element for GrTraitMethods properly --- .../lang/psi/impl/synthetic/GrTraitMethod.java | 1 + .../lang/highlighting/Gr23HighlightingTest.groovy | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrTraitMethod.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrTraitMethod.java index 19f30aab7a27..af4225639c66 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrTraitMethod.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrTraitMethod.java @@ -25,6 +25,7 @@ public class GrTraitMethod extends LightMethod implements PsiMirrorElement { @NotNull PsiMethod method, @NotNull PsiSubstitutor substitutor) { super(containingClass, method, substitutor); + setNavigationElement(method); } @Override diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/Gr23HighlightingTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/Gr23HighlightingTest.groovy index c0e2bc27e838..64d5b720afac 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/Gr23HighlightingTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/Gr23HighlightingTest.groovy @@ -19,6 +19,7 @@ import com.intellij.codeInspection.InspectionProfileEntry import com.intellij.ide.highlighter.JavaFileType import com.intellij.testFramework.LightProjectDescriptor import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor +import org.jetbrains.plugins.groovy.codeInspection.GroovyUnusedDeclarationInspection import org.jetbrains.plugins.groovy.codeInspection.assignment.GroovyAssignabilityCheckInspection import org.jetbrains.plugins.groovy.codeInspection.untypedUnresolvedAccess.GrUnresolvedAccessInspection @@ -460,4 +461,16 @@ class C implements T { ''' myFixture.testHighlighting false, false, false } + + void 'test trait method usages'() { + testHighlighting '''\ +trait T { + def getFoo() {} +} + +class A implements T {} + +new A().foo +''', GroovyUnusedDeclarationInspection + } } From ad396e7657451740435f1b39eb6a0fa0587820aa Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Thu, 12 May 2016 17:09:46 +0300 Subject: [PATCH 029/107] diff: move [*]Fragment conversions into ComparisonManager * make ByLine accept lines instead of texts * simplify ByLine.Line creation * remove diffSomehow methods --- .../diff/comparison/ComparisonManager.java | 11 + .../diff/fragments/MergeLineFragment.java | 0 .../diff/fragments/MergeWordFragment.java | 0 .../com/intellij/diff/comparison/ByLine.java | 310 ++++++------------ .../com/intellij/diff/comparison/ByWord.java | 43 ++- .../comparison/ComparisonManagerImpl.java | 139 +++++++- .../intellij/diff/comparison/TextChunk.java | 59 ---- .../iterables/DiffIterableUtil.java | 24 -- .../diff/fragments/MergeLineFragmentImpl.java | 9 - .../diff/fragments/MergeWordFragmentImpl.java | 4 - .../intellij/diff/merge/TextMergeViewer.java | 7 +- .../simple/SimpleThreesideDiffViewer.java | 8 +- .../diff/comparison/ComparisonUtilAutoTest.kt | 2 +- .../util/src/com/intellij/util/diff/Diff.java | 16 - .../vcs-impl/src/com/intellij/diff/Block.java | 66 ++-- 15 files changed, 302 insertions(+), 396 deletions(-) rename platform/{diff-impl => diff-api}/src/com/intellij/diff/fragments/MergeLineFragment.java (100%) rename platform/{diff-impl => diff-api}/src/com/intellij/diff/fragments/MergeWordFragment.java (100%) delete mode 100644 platform/diff-impl/src/com/intellij/diff/comparison/TextChunk.java diff --git a/platform/diff-api/src/com/intellij/diff/comparison/ComparisonManager.java b/platform/diff-api/src/com/intellij/diff/comparison/ComparisonManager.java index cd0915a0d435..30f8a8f7d35e 100644 --- a/platform/diff-api/src/com/intellij/diff/comparison/ComparisonManager.java +++ b/platform/diff-api/src/com/intellij/diff/comparison/ComparisonManager.java @@ -17,6 +17,7 @@ package com.intellij.diff.comparison; import com.intellij.diff.fragments.DiffFragment; import com.intellij.diff.fragments.LineFragment; +import com.intellij.diff.fragments.MergeLineFragment; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.progress.ProgressIndicator; import org.jetbrains.annotations.NotNull; @@ -61,6 +62,16 @@ public abstract class ComparisonManager { @NotNull ComparisonPolicy policy, @NotNull ProgressIndicator indicator) throws DiffTooBigException; + /** + * Compare three texts by-line (LEFT - BASE - RIGHT) + */ + @NotNull + public abstract List compareLines(@NotNull CharSequence text1, + @NotNull CharSequence text2, + @NotNull CharSequence text3, + @NotNull ComparisonPolicy policy, + @NotNull ProgressIndicator indicator) throws DiffTooBigException; + /** * Compare two texts by-word */ diff --git a/platform/diff-impl/src/com/intellij/diff/fragments/MergeLineFragment.java b/platform/diff-api/src/com/intellij/diff/fragments/MergeLineFragment.java similarity index 100% rename from platform/diff-impl/src/com/intellij/diff/fragments/MergeLineFragment.java rename to platform/diff-api/src/com/intellij/diff/fragments/MergeLineFragment.java diff --git a/platform/diff-impl/src/com/intellij/diff/fragments/MergeWordFragment.java b/platform/diff-api/src/com/intellij/diff/fragments/MergeWordFragment.java similarity index 100% rename from platform/diff-impl/src/com/intellij/diff/fragments/MergeWordFragment.java rename to platform/diff-api/src/com/intellij/diff/fragments/MergeWordFragment.java diff --git a/platform/diff-impl/src/com/intellij/diff/comparison/ByLine.java b/platform/diff-impl/src/com/intellij/diff/comparison/ByLine.java index f204eafde823..6abdc3781529 100644 --- a/platform/diff-impl/src/com/intellij/diff/comparison/ByLine.java +++ b/platform/diff-impl/src/com/intellij/diff/comparison/ByLine.java @@ -17,11 +17,6 @@ package com.intellij.diff.comparison; import com.intellij.diff.comparison.iterables.DiffIterableUtil.*; import com.intellij.diff.comparison.iterables.FairDiffIterable; -import com.intellij.diff.fragments.LineFragment; -import com.intellij.diff.fragments.LineFragmentImpl; -import com.intellij.diff.fragments.MergeLineFragment; -import com.intellij.diff.fragments.MergeLineFragmentImpl; -import com.intellij.diff.util.IntPair; import com.intellij.diff.util.MergeRange; import com.intellij.diff.util.Range; import com.intellij.openapi.progress.ProgressIndicator; @@ -35,6 +30,7 @@ import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; +import static com.intellij.diff.comparison.ComparisonPolicy.IGNORE_WHITESPACES; import static com.intellij.diff.comparison.TrimUtil.trimEnd; import static com.intellij.diff.comparison.TrimUtil.trimStart; import static com.intellij.diff.comparison.iterables.DiffIterableUtil.*; @@ -42,55 +38,61 @@ import static com.intellij.openapi.util.text.StringUtil.isWhiteSpace; public class ByLine { @NotNull - public static List compare(@NotNull CharSequence text1, - @NotNull CharSequence text2, - @NotNull ComparisonPolicy policy, - @NotNull ProgressIndicator indicator) { + public static FairDiffIterable compare(@NotNull List lines1, + @NotNull List lines2, + @NotNull ComparisonPolicy policy, + @NotNull ProgressIndicator indicator) { indicator.checkCanceled(); - - List lines1 = getLines(text1, policy); - List lines2 = getLines(text2, policy); - - FairDiffIterable changes = compareSmart(lines1, lines2, indicator); - changes = optimizeLineChunks(lines1, lines2, changes, indicator); - changes = expandRanges(lines1, lines2, changes, indicator); - return convertIntoFragments(lines1, lines2, changes); + return doCompare(getLines(lines1, policy), getLines(lines2, policy), policy, indicator); } @NotNull - public static List compareTwoStep(@NotNull CharSequence text1, - @NotNull CharSequence text2, - @NotNull ComparisonPolicy policy, - @NotNull ProgressIndicator indicator) { + public static List compare(@NotNull List lines1, + @NotNull List lines2, + @NotNull List lines3, + @NotNull ComparisonPolicy policy, + @NotNull ProgressIndicator indicator) { + indicator.checkCanceled(); + return doCompare(getLines(lines1, policy), getLines(lines2, policy), getLines(lines3, policy), policy, indicator); + } + + // + // Impl + // + + @NotNull + static FairDiffIterable doCompare(@NotNull List lines1, + @NotNull List lines2, + @NotNull ComparisonPolicy policy, + @NotNull ProgressIndicator indicator) { indicator.checkCanceled(); - List lines1 = getLines(text1, policy); - List lines2 = getLines(text2, policy); + if (policy == IGNORE_WHITESPACES) { + FairDiffIterable changes = compareSmart(lines1, lines2, indicator); + changes = optimizeLineChunks(lines1, lines2, changes, indicator); + return expandRanges(lines1, lines2, changes, indicator); + } + else { + List iwLines1 = convertMode(lines1, IGNORE_WHITESPACES); + List iwLines2 = convertMode(lines2, IGNORE_WHITESPACES); - List iwLines1 = convertToIgnoreWhitespace(lines1); - List iwLines2 = convertToIgnoreWhitespace(lines2); - - FairDiffIterable iwChanges = compareSmart(iwLines1, iwLines2, indicator); - iwChanges = optimizeLineChunks(lines1, lines2, iwChanges, indicator); - FairDiffIterable changes = correctChangesSecondStep(lines1, lines2, iwChanges); - return convertIntoFragments(lines1, lines2, changes); + FairDiffIterable iwChanges = compareSmart(iwLines1, iwLines2, indicator); + iwChanges = optimizeLineChunks(lines1, lines2, iwChanges, indicator); + return correctChangesSecondStep(lines1, lines2, iwChanges); + } } @NotNull - public static List compareTwoStep(@NotNull CharSequence text1, - @NotNull CharSequence text2, - @NotNull CharSequence text3, - @NotNull ComparisonPolicy policy, - @NotNull ProgressIndicator indicator) { + static List doCompare(@NotNull List lines1, + @NotNull List lines2, + @NotNull List lines3, + @NotNull ComparisonPolicy policy, + @NotNull ProgressIndicator indicator) { indicator.checkCanceled(); - List lines1 = getLines(text1, policy); - List lines2 = getLines(text2, policy); - List lines3 = getLines(text3, policy); - - List iwLines1 = convertToIgnoreWhitespace(lines1); - List iwLines2 = convertToIgnoreWhitespace(lines2); - List iwLines3 = convertToIgnoreWhitespace(lines3); + List iwLines1 = convertMode(lines1, IGNORE_WHITESPACES); + List iwLines2 = convertMode(lines2, IGNORE_WHITESPACES); + List iwLines3 = convertMode(lines3, IGNORE_WHITESPACES); FairDiffIterable iwChanges1 = compareSmart(iwLines2, iwLines1, indicator); iwChanges1 = optimizeLineChunks(lines2, lines1, iwChanges1, indicator); @@ -100,14 +102,9 @@ public class ByLine { iwChanges2 = optimizeLineChunks(lines2, lines3, iwChanges2, indicator); FairDiffIterable iterable2 = correctChangesSecondStep(lines2, lines3, iwChanges2); - List conflicts = ComparisonMergeUtil.buildFair(iterable1, iterable2, indicator); - return convertIntoFragments(conflicts); + return ComparisonMergeUtil.buildFair(iterable1, iterable2, indicator); } - // - // Impl - // - @NotNull private static FairDiffIterable correctChangesSecondStep(@NotNull final List lines1, @NotNull final List lines2, @@ -288,45 +285,6 @@ public class ByLine { return new ChunkOptimizer.LineChunkOptimizer(lines1, lines2, iterable, indicator).build(); } - @NotNull - private static List convertIntoFragments(@NotNull List lines1, - @NotNull List lines2, - @NotNull FairDiffIterable changes) { - List fragments = new ArrayList<>(); - for (Range ch : changes.iterateChanges()) { - IntPair offsets1 = getOffsets(lines1, ch.start1, ch.end1); - IntPair offsets2 = getOffsets(lines2, ch.start2, ch.end2); - - fragments.add(new LineFragmentImpl(ch.start1, ch.end1, ch.start2, ch.end2, - offsets1.val1, offsets1.val2, offsets2.val1, offsets2.val2)); - } - return fragments; - } - - @NotNull - private static List convertIntoFragments(@NotNull List conflicts) { - return ContainerUtil.map(conflicts, ch -> new MergeLineFragmentImpl(ch)); - } - - @NotNull - private static IntPair getOffsets(@NotNull List lines, int startIndex, int endIndex) { - if (startIndex == endIndex) { - int offset; - if (startIndex < lines.size()) { - offset = lines.get(startIndex).getOffset1(); - } - else { - offset = lines.get(lines.size() - 1).getOffset2(); - } - return new IntPair(offset, offset); - } - else { - int offset1 = lines.get(startIndex).getOffset1(); - int offset2 = lines.get(endIndex - 1).getOffset2(); - return new IntPair(offset1, offset2); - } - } - /* * Compare lines in two steps: * - compare ignoring "unimportant" lines @@ -381,70 +339,39 @@ public class ByLine { // @NotNull - private static List getLines(@NotNull CharSequence text, @NotNull ComparisonPolicy policy) { - List lines = new ArrayList<>(); - - int offset = 0; - while (true) { - Line line = createLine(text, offset, policy); - lines.add(line); - offset = line.getOffset2(); - if (!line.hasNewline()) break; - } - - return lines; + private static List getLines(@NotNull List text, @NotNull ComparisonPolicy policy) { + return ContainerUtil.map(text, (line) -> new Line(line, policy)); } @NotNull - private static Line createLine(@NotNull CharSequence text, int offset, @NotNull ComparisonPolicy policy) { - switch (policy) { - case DEFAULT: - return Line.createDefault(text, offset); - case IGNORE_WHITESPACES: - return Line.createIgnore(text, offset); - case TRIM_WHITESPACES: - return Line.createTrim(text, offset); - default: - throw new IllegalArgumentException(policy.name()); - } - } - - @NotNull - private static List convertToIgnoreWhitespace(@NotNull List original) { + private static List convertMode(@NotNull List original, @NotNull ComparisonPolicy policy) { List result = new ArrayList<>(original.size()); - for (Line line : original) { - result.add(Line.createIgnore(line.getOriginalText(), line.getOffset1())); + result.add(new Line(line.getContent(), policy)); } - return result; } - static class Line extends TextChunk { - enum Mode {DEFAULT, TRIM, IGNORE} - - @NotNull private final Mode myMode; + static class Line { + @NotNull private final CharSequence myText; + @NotNull private final ComparisonPolicy myPolicy; private final int myHash; private final int myNonSpaceChars; - private final boolean myNewline; - public Line(@NotNull CharSequence text, int offset1, int offset2, - @NotNull Mode mode, int hash, int nonSpaceChars, boolean newline) { - super(text, offset1, offset2); - myMode = mode; - myHash = hash; - myNonSpaceChars = nonSpaceChars; - myNewline = newline; - } - - public boolean hasNewline() { - return myNewline; + public Line(@NotNull CharSequence text, @NotNull ComparisonPolicy policy) { + myText = text; + myPolicy = policy; + myHash = hashCode(text, policy); + myNonSpaceChars = countNonSpaceChars(text); } @NotNull - @Override public CharSequence getContent() { - return getOriginalText().subSequence(getOffset1(), getOffset2() - (myNewline ? 1 : 0)); + return myText; + } + + public int getNonSpaceChars() { + return myNonSpaceChars; } @Override @@ -453,20 +380,11 @@ public class ByLine { if (o == null || getClass() != o.getClass()) return false; Line line = (Line)o; - assert myMode == line.myMode; + assert myPolicy == line.myPolicy; if (hashCode() != line.hashCode()) return false; - switch (myMode) { - case DEFAULT: - return StringUtil.equals(getContent(), line.getContent()); - case TRIM: - return StringUtil.equalsTrimWhitespaces(getContent(), line.getContent()); - case IGNORE: - return StringUtil.equalsIgnoreWhitespaces(getContent(), line.getContent()); - default: - throw new IllegalArgumentException(myMode.toString()); - } + return equals(getContent(), line.getContent(), myPolicy); } @Override @@ -474,87 +392,47 @@ public class ByLine { return myHash; } - public int getNonSpaceChars() { - return myNonSpaceChars; - } - - public static Line createDefault(@NotNull CharSequence text, int startOffset) { - int len = text.length(); - - int h = 0; + private static int countNonSpaceChars(@NotNull CharSequence text) { int nonSpace = 0; - boolean newline = false; - int offset = startOffset; + int len = text.length(); + int offset = 0; + while (offset < len) { char c = text.charAt(offset); - if (c == '\n') { - offset++; - newline = true; - break; - } - if (!isWhiteSpace(c)) nonSpace++; - h = 31 * h + c; - offset++; - } - - return new Line(text, startOffset, offset, Mode.DEFAULT, h, nonSpace, newline); - } - - public static Line createIgnore(@NotNull CharSequence text, int startOffset) { - int len = text.length(); - - int h = 0; - int nonSpace = 0; - boolean newline = false; - - int offset = startOffset; - while (offset < len) { - char c = text.charAt(offset); - if (c == '\n') { - offset++; - newline = true; - break; - } - if (!isWhiteSpace(c)) { - nonSpace++; - h = 31 * h + c; - } - offset++; - } - - return new Line(text, startOffset, offset, Mode.IGNORE, h, nonSpace, newline); - } - - public static Line createTrim(@NotNull CharSequence text, int startOffset) { - int len = text.length(); - - int nonSpace = 0; - boolean newline = false; - - int offset = startOffset; - while (offset < len) { - char c = text.charAt(offset); - if (c == '\n') { - offset++; - newline = true; - break; - } if (!isWhiteSpace(c)) nonSpace++; offset++; } - int h = calcTrimHash(text, startOffset, offset); - - return new Line(text, startOffset, offset, Mode.TRIM, h, nonSpace, newline); + return nonSpace; } + private static boolean equals(@NotNull CharSequence text1, @NotNull CharSequence text2, @NotNull ComparisonPolicy policy) { + switch (policy) { + case DEFAULT: + return StringUtil.equals(text1, text2); + case TRIM_WHITESPACES: + return StringUtil.equalsTrimWhitespaces(text1, text2); + case IGNORE_WHITESPACES: + return StringUtil.equalsIgnoreWhitespaces(text1, text2); + default: + throw new IllegalArgumentException(policy.toString()); + } + } - private static int calcTrimHash(@NotNull CharSequence text, int offset1, int offset2) { - offset1 = trimStart(text, offset1, offset2); - offset2 = trimEnd(text, offset1, offset2); - - return StringUtil.stringHashCode(text, offset1, offset2); + private static int hashCode(@NotNull CharSequence text, @NotNull ComparisonPolicy policy) { + switch (policy) { + case DEFAULT: + return StringUtil.stringHashCode(text); + case TRIM_WHITESPACES: + int offset1 = trimStart(text, 0, text.length()); + int offset2 = trimEnd(text, offset1, text.length()); + return StringUtil.stringHashCode(text, offset1, offset2); + case IGNORE_WHITESPACES: + return StringUtil.stringHashCodeIgnoreWhitespaces(text); + default: + throw new IllegalArgumentException(policy.name()); + } } } } diff --git a/platform/diff-impl/src/com/intellij/diff/comparison/ByWord.java b/platform/diff-impl/src/com/intellij/diff/comparison/ByWord.java index 7e97f0de823a..eec26d3f1e25 100644 --- a/platform/diff-impl/src/com/intellij/diff/comparison/ByWord.java +++ b/platform/diff-impl/src/com/intellij/diff/comparison/ByWord.java @@ -17,24 +17,23 @@ package com.intellij.diff.comparison; import com.intellij.diff.comparison.LineFragmentSplitter.WordBlock; import com.intellij.diff.comparison.iterables.DiffIterable; -import com.intellij.diff.comparison.iterables.DiffIterableUtil; import com.intellij.diff.comparison.iterables.DiffIterableUtil.*; import com.intellij.diff.comparison.iterables.FairDiffIterable; import com.intellij.diff.fragments.DiffFragment; import com.intellij.diff.fragments.MergeWordFragment; -import com.intellij.diff.fragments.MergeWordFragmentImpl; import com.intellij.diff.util.MergeRange; import com.intellij.diff.util.Range; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.util.Couple; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.util.containers.ContainerUtil; import com.intellij.util.text.MergingCharSequence; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; +import static com.intellij.diff.comparison.ComparisonManagerImpl.convertIntoDiffFragments; +import static com.intellij.diff.comparison.ComparisonManagerImpl.convertIntoMergeWordFragments; import static com.intellij.diff.comparison.TrimUtil.*; import static com.intellij.diff.comparison.TrimUtil.trim; import static com.intellij.diff.comparison.iterables.DiffIterableUtil.*; @@ -66,7 +65,7 @@ public class ByWord { FairDiffIterable delimitersIterable = matchAdjustmentDelimiters(text1, text2, words1, words2, wordChanges, indicator); DiffIterable iterable = matchAdjustmentWhitespaces(text1, text2, delimitersIterable, policy, indicator); - return convertIntoFragments(iterable); + return convertIntoDiffFragments(iterable); } @NotNull @@ -92,7 +91,7 @@ public class ByWord { List wordConflicts = ComparisonMergeUtil.buildFair(iterable1, iterable2, indicator); List result = matchAdjustmentWhitespaces(text1, text2, text3, wordConflicts, policy, indicator); - return convertIntoFragments(result); + return convertIntoMergeWordFragments(result); } @NotNull @@ -144,7 +143,7 @@ public class ByWord { offsets.start1, offsets.start2, indicator); DiffIterable iterable = matchAdjustmentWhitespaces(subtext1, subtext2, delimitersIterable, policy, indicator); - List fragments = convertIntoFragments(iterable); + List fragments = convertIntoDiffFragments(iterable); int newlines1 = countNewlines(subwords1); int newlines2 = countNewlines(subwords2); @@ -159,16 +158,6 @@ public class ByWord { // Impl // - @NotNull - private static List convertIntoFragments(@NotNull List conflicts) { - return ContainerUtil.map(conflicts, ch -> new MergeWordFragmentImpl(ch)); - } - - @NotNull - private static List convertIntoFragments(@NotNull DiffIterable iterable) { - return DiffIterableUtil.convertIntoFragments(iterable); - } - @NotNull private static FairDiffIterable optimizeWordChunks(@NotNull CharSequence text1, @NotNull CharSequence text2, @@ -863,14 +852,32 @@ public class ByWord { int getOffset2(); } - static class WordChunk extends TextChunk implements InlineChunk { + static class WordChunk implements InlineChunk { + @NotNull private final CharSequence myText; + private final int myOffset1; + private final int myOffset2; private final int myHash; public WordChunk(@NotNull CharSequence text, int offset1, int offset2, int hash) { - super(text, offset1, offset2); + myText = text; + myOffset1 = offset1; + myOffset2 = offset2; myHash = hash; } + @NotNull + public CharSequence getContent() { + return myText.subSequence(myOffset1, myOffset2); + } + + public int getOffset1() { + return myOffset1; + } + + public int getOffset2() { + return myOffset2; + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/platform/diff-impl/src/com/intellij/diff/comparison/ComparisonManagerImpl.java b/platform/diff-impl/src/com/intellij/diff/comparison/ComparisonManagerImpl.java index 26aa3fa4ed20..31f67d866a6f 100644 --- a/platform/diff-impl/src/com/intellij/diff/comparison/ComparisonManagerImpl.java +++ b/platform/diff-impl/src/com/intellij/diff/comparison/ComparisonManagerImpl.java @@ -15,10 +15,11 @@ */ package com.intellij.diff.comparison; -import com.intellij.diff.fragments.DiffFragment; -import com.intellij.diff.fragments.DiffFragmentImpl; -import com.intellij.diff.fragments.LineFragment; -import com.intellij.diff.fragments.LineFragmentImpl; +import com.intellij.diff.comparison.iterables.DiffIterable; +import com.intellij.diff.comparison.iterables.FairDiffIterable; +import com.intellij.diff.fragments.*; +import com.intellij.diff.util.IntPair; +import com.intellij.diff.util.MergeRange; import com.intellij.diff.util.Range; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProgressIndicator; @@ -33,8 +34,6 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; -import static com.intellij.diff.comparison.iterables.DiffIterableUtil.convertIntoFragments; - public class ComparisonManagerImpl extends ComparisonManager { public static final Logger LOG = Logger.getInstance(ComparisonManagerImpl.class); @@ -44,12 +43,24 @@ public class ComparisonManagerImpl extends ComparisonManager { @NotNull CharSequence text2, @NotNull ComparisonPolicy policy, @NotNull ProgressIndicator indicator) throws DiffTooBigException { - if (policy == ComparisonPolicy.IGNORE_WHITESPACES) { - return ByLine.compare(text1, text2, policy, indicator); - } - else { - return ByLine.compareTwoStep(text1, text2, policy, indicator); - } + List lines1 = getLines(text1); + List lines2 = getLines(text2); + FairDiffIterable iterable = ByLine.compare(lines1, lines2, policy, indicator); + return convertIntoLineFragments(lines1, lines2, iterable); + } + + @NotNull + @Override + public List compareLines(@NotNull CharSequence text1, + @NotNull CharSequence text2, + @NotNull CharSequence text3, + @NotNull ComparisonPolicy policy, + @NotNull ProgressIndicator indicator) throws DiffTooBigException { + List lines1 = getLines(text1); + List lines2 = getLines(text2); + List lines3 = getLines(text3); + List ranges = ByLine.compare(lines1, lines2, lines3, policy, indicator); + return convertIntoMergeLineFragments(ranges); } @NotNull @@ -145,13 +156,13 @@ public class ComparisonManagerImpl extends ComparisonManager { @NotNull ComparisonPolicy policy, @NotNull ProgressIndicator indicator) throws DiffTooBigException { if (policy == ComparisonPolicy.IGNORE_WHITESPACES) { - return convertIntoFragments(ByChar.compareIgnoreWhitespaces(text1, text2, indicator)); + return convertIntoDiffFragments(ByChar.compareIgnoreWhitespaces(text1, text2, indicator)); } if (policy == ComparisonPolicy.DEFAULT) { - return convertIntoFragments(ByChar.compareTwoStep(text1, text2, indicator)); + return convertIntoDiffFragments(ByChar.compareTwoStep(text1, text2, indicator)); } LOG.warn(policy.toString() + " is not supported by ByChar comparison"); - return convertIntoFragments(ByChar.compareTwoStep(text1, text2, indicator)); + return convertIntoDiffFragments(ByChar.compareTwoStep(text1, text2, indicator)); } @Override @@ -159,6 +170,63 @@ public class ComparisonManagerImpl extends ComparisonManager { return ComparisonUtil.isEquals(text1, text2, policy); } + // + // Fragments + // + + @NotNull + public static List convertIntoDiffFragments(@NotNull DiffIterable changes) { + final List fragments = new ArrayList<>(); + for (Range ch : changes.iterateChanges()) { + fragments.add(new DiffFragmentImpl(ch.start1, ch.end1, ch.start2, ch.end2)); + } + return fragments; + } + + @NotNull + public static List convertIntoLineFragments(@NotNull List lines1, + @NotNull List lines2, + @NotNull FairDiffIterable changes) { + List fragments = new ArrayList<>(); + for (Range ch : changes.iterateChanges()) { + IntPair offsets1 = getOffsets(lines1, ch.start1, ch.end1); + IntPair offsets2 = getOffsets(lines2, ch.start2, ch.end2); + + fragments.add(new LineFragmentImpl(ch.start1, ch.end1, ch.start2, ch.end2, + offsets1.val1, offsets1.val2, offsets2.val1, offsets2.val2)); + } + return fragments; + } + + @NotNull + private static IntPair getOffsets(@NotNull List lines, int startIndex, int endIndex) { + if (startIndex == endIndex) { + int offset; + if (startIndex < lines.size()) { + offset = lines.get(startIndex).getOffset1(); + } + else { + offset = lines.get(lines.size() - 1).getOffset2(); + } + return new IntPair(offset, offset); + } + else { + int offset1 = lines.get(startIndex).getOffset1(); + int offset2 = lines.get(endIndex - 1).getOffset2(); + return new IntPair(offset1, offset2); + } + } + + @NotNull + public static List convertIntoMergeLineFragments(@NotNull List conflicts) { + return ContainerUtil.map(conflicts, ch -> new MergeLineFragmentImpl(ch.start1, ch.end1, ch.start2, ch.end2, ch.start3, ch.end3)); + } + + @NotNull + public static List convertIntoMergeWordFragments(@NotNull List conflicts) { + return ContainerUtil.map(conflicts, ch -> new MergeWordFragmentImpl(ch.start1, ch.end1, ch.start2, ch.end2, ch.start3, ch.end3)); + } + // // Post process line fragments // @@ -304,4 +372,45 @@ public class ComparisonManagerImpl extends ComparisonManager { int length2 = lineFragment.getEndOffset2() - lineFragment.getStartOffset2(); return Collections.singletonList(new DiffFragmentImpl(0, length1, 0, length2)); } + + @NotNull + private static List getLines(@NotNull CharSequence text) { + List lines = new ArrayList<>(); + + int offset = 0; + while (true) { + int lineEnd = StringUtil.indexOf(text, '\n', offset); + if (lineEnd != -1) { + lines.add(new Line(text, offset, lineEnd, true)); + offset = lineEnd + 1; + } + else { + lines.add(new Line(text, offset, text.length(), false)); + break; + } + } + + return lines; + } + + private static class Line extends CharSequenceSubSequence { + private final int myOffset1; + private final int myOffset2; + private final boolean myNewline; + + public Line(@NotNull CharSequence chars, int offset1, int offset2, boolean newline) { + super(chars, offset1, offset2); + myOffset1 = offset1; + myOffset2 = offset2; + myNewline = newline; + } + + public int getOffset1() { + return myOffset1; + } + + public int getOffset2() { + return myOffset2 + (myNewline ? 1 : 0); + } + } } diff --git a/platform/diff-impl/src/com/intellij/diff/comparison/TextChunk.java b/platform/diff-impl/src/com/intellij/diff/comparison/TextChunk.java deleted file mode 100644 index 8a163f39b653..000000000000 --- a/platform/diff-impl/src/com/intellij/diff/comparison/TextChunk.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2000-2015 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.diff.comparison; - -import org.jetbrains.annotations.NotNull; - -abstract class TextChunk { - @NotNull private final CharSequence myText; - private final int myOffset1; - private final int myOffset2; - - public TextChunk(@NotNull CharSequence text, int offset1, int offset2) { - myText = text; - myOffset1 = offset1; - myOffset2 = offset2; - } - - @Override - public abstract int hashCode(); - - @Override - public abstract boolean equals(Object obj); - - @NotNull - public CharSequence getContent() { - return myText.subSequence(myOffset1, myOffset2); - } - - @NotNull - public CharSequence getOriginalText() { - return myText; - } - - public int getOffset1() { - return myOffset1; - } - - public int getOffset2() { - return myOffset2; - } - - @Override - public String toString() { - return getContent().toString(); - } -} diff --git a/platform/diff-impl/src/com/intellij/diff/comparison/iterables/DiffIterableUtil.java b/platform/diff-impl/src/com/intellij/diff/comparison/iterables/DiffIterableUtil.java index 10a4fc0de250..346e1402e489 100644 --- a/platform/diff-impl/src/com/intellij/diff/comparison/iterables/DiffIterableUtil.java +++ b/platform/diff-impl/src/com/intellij/diff/comparison/iterables/DiffIterableUtil.java @@ -18,7 +18,6 @@ package com.intellij.diff.comparison.iterables; import com.intellij.diff.comparison.DiffTooBigException; import com.intellij.diff.comparison.TrimUtil; import com.intellij.diff.fragments.DiffFragment; -import com.intellij.diff.fragments.DiffFragmentImpl; import com.intellij.diff.util.Range; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.util.Comparing; @@ -88,20 +87,6 @@ public class DiffIterableUtil { return diff(data1, data2, indicator); } - /* - * Compare two arrays, basing on equals() and hashCode() of it's elements - * - * If the input arrays are too big, "everything is changed" can be returned. - */ - @NotNull - public static FairDiffIterable diffSomehow(@NotNull T[] data1, @NotNull T[] data2, @NotNull ProgressIndicator indicator) { - indicator.checkCanceled(); - - // TODO: use ProgressIndicator inside - Diff.Change change = Diff.buildChangesSomehow(data1, data2); - return fair(create(change, data1.length, data2.length)); - } - // // Iterable // @@ -158,15 +143,6 @@ public class DiffIterableUtil { // Misc // - @NotNull - public static List convertIntoFragments(@NotNull DiffIterable changes) { - final List fragments = new ArrayList<>(); - for (Range ch : changes.iterateChanges()) { - fragments.add(new DiffFragmentImpl(ch.start1, ch.end1, ch.start2, ch.end2)); - } - return fragments; - } - @NotNull public static Iterable> iterateAll(@NotNull final DiffIterable iterable) { return () -> new Iterator>() { diff --git a/platform/diff-impl/src/com/intellij/diff/fragments/MergeLineFragmentImpl.java b/platform/diff-impl/src/com/intellij/diff/fragments/MergeLineFragmentImpl.java index eea8b6a2d590..a9d7b118fc3c 100644 --- a/platform/diff-impl/src/com/intellij/diff/fragments/MergeLineFragmentImpl.java +++ b/platform/diff-impl/src/com/intellij/diff/fragments/MergeLineFragmentImpl.java @@ -15,7 +15,6 @@ */ package com.intellij.diff.fragments; -import com.intellij.diff.util.MergeRange; import com.intellij.diff.util.ThreeSide; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -57,14 +56,6 @@ public class MergeLineFragmentImpl implements MergeLineFragment { myInnerFragments = innerFragments; } - public MergeLineFragmentImpl(@NotNull MergeRange range) { - this(range, null); - } - - public MergeLineFragmentImpl(@NotNull MergeRange range, @Nullable List innerFragments) { - this(range.start1, range.end1, range.start2, range.end2, range.start3, range.end3, innerFragments); - } - public MergeLineFragmentImpl(@NotNull MergeLineFragment fragment, @Nullable List fragments) { this(fragment.getStartLine(ThreeSide.LEFT), fragment.getEndLine(ThreeSide.LEFT), fragment.getStartLine(ThreeSide.BASE), fragment.getEndLine(ThreeSide.BASE), diff --git a/platform/diff-impl/src/com/intellij/diff/fragments/MergeWordFragmentImpl.java b/platform/diff-impl/src/com/intellij/diff/fragments/MergeWordFragmentImpl.java index b95a3e316493..b7abb9c333ed 100644 --- a/platform/diff-impl/src/com/intellij/diff/fragments/MergeWordFragmentImpl.java +++ b/platform/diff-impl/src/com/intellij/diff/fragments/MergeWordFragmentImpl.java @@ -41,10 +41,6 @@ public class MergeWordFragmentImpl implements MergeWordFragment { myEndOffset3 = endOffset3; } - public MergeWordFragmentImpl(@NotNull MergeRange range) { - this(range.start1, range.end1, range.start2, range.end2, range.start3, range.end3); - } - @Override public int getStartOffset(@NotNull ThreeSide side) { return side.select(myStartOffset1, myStartOffset2, myStartOffset3); diff --git a/platform/diff-impl/src/com/intellij/diff/merge/TextMergeViewer.java b/platform/diff-impl/src/com/intellij/diff/merge/TextMergeViewer.java index dd6e166e4a16..e5de1b18f040 100644 --- a/platform/diff-impl/src/com/intellij/diff/merge/TextMergeViewer.java +++ b/platform/diff-impl/src/com/intellij/diff/merge/TextMergeViewer.java @@ -18,7 +18,7 @@ package com.intellij.diff.merge; import com.intellij.diff.DiffContext; import com.intellij.diff.FrameDiffTool; import com.intellij.diff.actions.ProxyUndoRedoAction; -import com.intellij.diff.comparison.ByLine; +import com.intellij.diff.comparison.ComparisonManager; import com.intellij.diff.comparison.ComparisonMergeUtil; import com.intellij.diff.comparison.ComparisonPolicy; import com.intellij.diff.comparison.DiffTooBigException; @@ -363,8 +363,9 @@ public class TextMergeViewer implements MergeTool.MergeViewer { return ContainerUtil.map(documents, Document::getImmutableCharSequence); }); - List lineFragments = ByLine.compareTwoStep(sequences.get(0), sequences.get(1), sequences.get(2), - ComparisonPolicy.DEFAULT, indicator); + ComparisonManager manager = ComparisonManager.getInstance(); + List lineFragments = manager.compareLines(sequences.get(0), sequences.get(1), sequences.get(2), + ComparisonPolicy.DEFAULT, indicator); List conflictTypes = ReadAction.compute(() -> { indicator.checkCanceled(); diff --git a/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleThreesideDiffViewer.java b/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleThreesideDiffViewer.java index 3d2325550148..c67f66adcf11 100644 --- a/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleThreesideDiffViewer.java +++ b/platform/diff-impl/src/com/intellij/diff/tools/simple/SimpleThreesideDiffViewer.java @@ -16,7 +16,7 @@ package com.intellij.diff.tools.simple; import com.intellij.diff.DiffContext; -import com.intellij.diff.comparison.ByLine; +import com.intellij.diff.comparison.ComparisonManager; import com.intellij.diff.comparison.ComparisonPolicy; import com.intellij.diff.comparison.DiffTooBigException; import com.intellij.diff.contents.DiffContent; @@ -125,8 +125,10 @@ public class SimpleThreesideDiffViewer extends ThreesideTextDiffViewerEx { }); final ComparisonPolicy comparisonPolicy = getIgnorePolicy().getComparisonPolicy(); - List lineFragments = ByLine.compareTwoStep(sequences.get(0), sequences.get(1), sequences.get(2), - comparisonPolicy, indicator); + + ComparisonManager manager = ComparisonManager.getInstance(); + List lineFragments = manager.compareLines(sequences.get(0), sequences.get(1), sequences.get(2), + comparisonPolicy, indicator); List conflictTypes = ReadAction.compute(() -> { indicator.checkCanceled(); diff --git a/platform/diff-impl/tests/com/intellij/diff/comparison/ComparisonUtilAutoTest.kt b/platform/diff-impl/tests/com/intellij/diff/comparison/ComparisonUtilAutoTest.kt index 36431c682616..4de112cd371b 100644 --- a/platform/diff-impl/tests/com/intellij/diff/comparison/ComparisonUtilAutoTest.kt +++ b/platform/diff-impl/tests/com/intellij/diff/comparison/ComparisonUtilAutoTest.kt @@ -134,7 +134,7 @@ class ComparisonUtilAutoTest : DiffTestCase() { val sequence2 = text2.charsSequence val sequence3 = text3.charsSequence - val fragments = ByLine.compareTwoStep(sequence1, sequence2, sequence3, policy, INDICATOR) + val fragments = MANAGER.compareLines(sequence1, sequence2, sequence3, policy, INDICATOR) val fineFragments = fragments.map { f -> val chunk1 = DiffUtil.getLinesContent(text1, f.startLine1, f.endLine1) diff --git a/platform/util/src/com/intellij/util/diff/Diff.java b/platform/util/src/com/intellij/util/diff/Diff.java index 7cf36e31e5e3..627fc2db358c 100644 --- a/platform/util/src/com/intellij/util/diff/Diff.java +++ b/platform/util/src/com/intellij/util/diff/Diff.java @@ -35,22 +35,6 @@ import java.util.BitSet; public class Diff { private static final Logger LOG = Logger.getInstance("#com.intellij.util.diff.Diff"); - @Nullable - public static Change buildChangesSomehow(@NotNull T[] objects1, @NotNull T[] objects2) { - try { - return buildChanges(objects1, objects2); - } - catch (FilesTooBigForDiffException e) { - final int startShift = getStartShift(objects1, objects2); - final int endCut = getEndCut(objects1, objects2, startShift); - - int trimmedLength1 = objects1.length - startShift - endCut; - int trimmedLength2 = objects2.length - startShift - endCut; - - return new Change(startShift, startShift, trimmedLength1, trimmedLength2, null); - } - } - @Nullable public static Change buildChanges(@NotNull CharSequence before, @NotNull CharSequence after) throws FilesTooBigForDiffException { final String[] strings1 = LineTokenizer.tokenize(before, false); diff --git a/platform/vcs-impl/src/com/intellij/diff/Block.java b/platform/vcs-impl/src/com/intellij/diff/Block.java index 5bff2d3acbf0..b4cd7eea32c4 100644 --- a/platform/vcs-impl/src/com/intellij/diff/Block.java +++ b/platform/vcs-impl/src/com/intellij/diff/Block.java @@ -15,6 +15,9 @@ */ package com.intellij.diff; +import com.intellij.diff.comparison.ByLine; +import com.intellij.diff.comparison.ComparisonPolicy; +import com.intellij.diff.comparison.DiffTooBigException; import com.intellij.diff.comparison.iterables.DiffIterableUtil; import com.intellij.diff.comparison.iterables.FairDiffIterable; import com.intellij.diff.util.Range; @@ -64,39 +67,46 @@ public class Block { int end = -1; int shift = 0; - FairDiffIterable iterable = DiffIterableUtil.diffSomehow(prevContent, mySource, DumbProgressIndicator.INSTANCE); - for (Pair pair : DiffIterableUtil.iterateAll(iterable)) { - Boolean equals = pair.second; - Range range = pair.first; - if (!equals) { - if (Math.max(myStart, range.start2) < Math.min(myEnd, range.end2)) { - // ranges intersect - if (range.start2 <= myStart) start = range.start1; - if (range.end2 > myEnd) end = range.end1; - } - if (range.start2 > myStart) { - if (start == -1) start = myStart - shift; - if (end == -1 && range.start2 >= myEnd) end = myEnd - shift; - } + try { + FairDiffIterable iterable = ByLine.compare(Arrays.asList(prevContent), Arrays.asList(mySource), + ComparisonPolicy.DEFAULT, DumbProgressIndicator.INSTANCE); - shift += (range.end2 - range.start2) - (range.end1 - range.start1); - } - else { - // intern strings, reducing memory usage - int count = range.end1 - range.start1; - for (int i = 0; i < count; i++) { - prevContent[range.start1 + i] = mySource[range.start2 + i]; + for (Pair pair : DiffIterableUtil.iterateAll(iterable)) { + Boolean equals = pair.second; + Range range = pair.first; + if (!equals) { + if (Math.max(myStart, range.start2) < Math.min(myEnd, range.end2)) { + // ranges intersect + if (range.start2 <= myStart) start = range.start1; + if (range.end2 > myEnd) end = range.end1; + } + if (range.start2 > myStart) { + if (start == -1) start = myStart - shift; + if (end == -1 && range.start2 >= myEnd) end = myEnd - shift; + } + + shift += (range.end2 - range.start2) - (range.end1 - range.start1); + } + else { + // intern strings, reducing memory usage + int count = range.end1 - range.start1; + for (int i = 0; i < count; i++) { + prevContent[range.start1 + i] = mySource[range.start2 + i]; + } } } - } - if (start == -1) start = myStart - shift; - if (end == -1) end = myEnd - shift; + if (start == -1) start = myStart - shift; + if (end == -1) end = myEnd - shift; - if (start < 0 || end > prevContent.length || end < start) { - LOG.error("Invalid block range: [" + start + ", " + end + "); length - " + prevContent.length); - } + if (start < 0 || end > prevContent.length || end < start) { + LOG.error("Invalid block range: [" + start + ", " + end + "); length - " + prevContent.length); + } - return new Block(prevContent, start, end); + return new Block(prevContent, start, end); + } + catch (DiffTooBigException e) { + return new Block(prevContent, 0, 0); + } } @NotNull From 35d02bf4ff214201d4d9d3ffb0ba9927159731c3 Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Mon, 20 Jun 2016 20:15:21 +0300 Subject: [PATCH 030/107] diff: fix two-step correction * use correction with IGNORE_WHITESPACES policy * fix cases of non-abmigous matching and when we refuse to check all possible variants --- .../com/intellij/diff/comparison/ByLine.java | 68 ++++++++++++------- .../diff/comparison/LineComparisonUtilTest.kt | 57 +++++++++++++++- 2 files changed, 98 insertions(+), 27 deletions(-) diff --git a/platform/diff-impl/src/com/intellij/diff/comparison/ByLine.java b/platform/diff-impl/src/com/intellij/diff/comparison/ByLine.java index 6abdc3781529..ae75bbaf8f33 100644 --- a/platform/diff-impl/src/com/intellij/diff/comparison/ByLine.java +++ b/platform/diff-impl/src/com/intellij/diff/comparison/ByLine.java @@ -15,7 +15,7 @@ */ package com.intellij.diff.comparison; -import com.intellij.diff.comparison.iterables.DiffIterableUtil.*; +import com.intellij.diff.comparison.iterables.DiffIterableUtil.ExpandChangeBuilder; import com.intellij.diff.comparison.iterables.FairDiffIterable; import com.intellij.diff.util.MergeRange; import com.intellij.diff.util.Range; @@ -24,6 +24,7 @@ import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.containers.ContainerUtil; +import gnu.trove.Equality; import gnu.trove.TIntArrayList; import org.jetbrains.annotations.NotNull; @@ -33,7 +34,8 @@ import java.util.List; import static com.intellij.diff.comparison.ComparisonPolicy.IGNORE_WHITESPACES; import static com.intellij.diff.comparison.TrimUtil.trimEnd; import static com.intellij.diff.comparison.TrimUtil.trimStart; -import static com.intellij.diff.comparison.iterables.DiffIterableUtil.*; +import static com.intellij.diff.comparison.iterables.DiffIterableUtil.diff; +import static com.intellij.diff.comparison.iterables.DiffIterableUtil.fair; import static com.intellij.openapi.util.text.StringUtil.isWhiteSpace; public class ByLine { @@ -70,7 +72,7 @@ public class ByLine { if (policy == IGNORE_WHITESPACES) { FairDiffIterable changes = compareSmart(lines1, lines2, indicator); changes = optimizeLineChunks(lines1, lines2, changes, indicator); - return expandRanges(lines1, lines2, changes, indicator); + return correctChangesSecondStepIW(lines1, lines2, changes); } else { List iwLines1 = convertMode(lines1, IGNORE_WHITESPACES); @@ -109,6 +111,23 @@ public class ByLine { private static FairDiffIterable correctChangesSecondStep(@NotNull final List lines1, @NotNull final List lines2, @NotNull final FairDiffIterable changes) { + return doCorrectChangesSecondStep(lines1, lines2, changes, + Equality.CANONICAL); + } + + @NotNull + private static FairDiffIterable correctChangesSecondStepIW(@NotNull final List lines1, + @NotNull final List lines2, + @NotNull final FairDiffIterable changes) { + return doCorrectChangesSecondStep(lines1, lines2, changes, + (l1, l2) -> StringUtil.equals(l1.getContent(), l2.getContent())); + } + + @NotNull + private static FairDiffIterable doCorrectChangesSecondStep(@NotNull final List lines1, + @NotNull final List lines2, + @NotNull final FairDiffIterable changes, + @NotNull final Equality maximisingEquality) { /* * We want to fix invalid matching here: * @@ -153,7 +172,7 @@ public class ByLine { Line line2 = lines2.get(index2); if (!StringUtil.equalsIgnoreWhitespaces(sample, line1.getContent())) { - if (line1.equals(line2)) { + if (maximisingEquality.equals(line1, line2)) { flush(index1, index2); builder.markEqual(index1, index2); } @@ -194,13 +213,24 @@ public class ByLine { } private void alignExactMatching(TIntArrayList subLines1, TIntArrayList subLines2) { - if (subLines1.size() == subLines2.size()) return; - int n = Math.max(subLines1.size(), subLines2.size()); - if (n > 10) return; // we use brute-force algorithm (C_n_k). This will limit search space by ~250 cases. + boolean skipAligning = n > 10 || // we use brute-force algorithm (C_n_k). This will limit search space by ~250 cases. + subLines1.size() == subLines2.size(); // nothing to do + + if (skipAligning) { + int count = Math.min(subLines1.size(), subLines2.size()); + for (int i = 0; i < count; i++) { + int index1 = subLines1.get(i); + int index2 = subLines2.get(i); + if (lines1.get(index1).equals(lines2.get(index2))) { + builder.markEqual(index1, index2); + } + } + return; + } if (subLines1.size() < subLines2.size()) { - int[] matching = getBestMatchingAlignment(subLines1, subLines2, lines1, lines2); + int[] matching = getBestMatchingAlignment(subLines1, subLines2, lines1, lines2, maximisingEquality); for (int i = 0; i < subLines1.size(); i++) { int index1 = subLines1.get(i); int index2 = subLines2.get(matching[i]); @@ -210,7 +240,7 @@ public class ByLine { } } else { - int[] matching = getBestMatchingAlignment(subLines2, subLines1, lines2, lines1); + int[] matching = getBestMatchingAlignment(subLines2, subLines1, lines2, lines1, maximisingEquality); for (int i = 0; i < subLines2.size(); i++) { int index1 = subLines1.get(matching[i]); int index2 = subLines2.get(i); @@ -229,7 +259,8 @@ public class ByLine { private static int[] getBestMatchingAlignment(@NotNull final TIntArrayList subLines1, @NotNull final TIntArrayList subLines2, @NotNull final List lines1, - @NotNull final List lines2) { + @NotNull final List lines2, + @NotNull final Equality maximisingEquality) { assert subLines1.size() < subLines2.size(); final int size = subLines1.size(); @@ -264,7 +295,7 @@ public class ByLine { for (int i = 0; i < size; i++) { int index1 = subLines1.get(i); int index2 = subLines2.get(comb[i]); - if (lines1.get(index1).equals(lines2.get(index2))) weight++; + if (maximisingEquality.equals(lines1.get(index1), lines2.get(index2))) weight++; } if (weight > bestWeight) { @@ -319,21 +350,6 @@ public class ByLine { return Pair.create(bigLines, indexes); } - @NotNull - private static FairDiffIterable expandRanges(@NotNull List lines1, - @NotNull List lines2, - @NotNull FairDiffIterable iterable, - @NotNull ProgressIndicator indicator) { - List changes = new ArrayList<>(); - - for (Range ch : iterable.iterateChanges()) { - Range expanded = TrimUtil.expand(lines1, lines2, ch.start1, ch.start2, ch.end1, ch.end2); - if (!expanded.isEmpty()) changes.add(expanded); - } - - return fair(create(changes, lines1.size(), lines2.size())); - } - // // Lines // diff --git a/platform/diff-impl/tests/com/intellij/diff/comparison/LineComparisonUtilTest.kt b/platform/diff-impl/tests/com/intellij/diff/comparison/LineComparisonUtilTest.kt index 9144618851d3..2eab93eccb42 100644 --- a/platform/diff-impl/tests/com/intellij/diff/comparison/LineComparisonUtilTest.kt +++ b/platform/diff-impl/tests/com/intellij/diff/comparison/LineComparisonUtilTest.kt @@ -401,6 +401,7 @@ class LineComparisonUtilTest : ComparisonUtilTestBase() { // TODO (" _-------_ _ _ " - " _ _ _ ").trim() (" _-------_ _ _ " - " _ _ _ ").default() (" _ _--_-_------" - " _--_-_ ").trim() + (" _-------_ _ _ " - " _ _ _ ").ignore() testAll() } @@ -416,7 +417,6 @@ class LineComparisonUtilTest : ComparisonUtilTestBase() { lines() { ("====}_==== }_Y_====}" - "====}_Y_====}") (" _------_ _ " - " _ _ ").default() // result after second step correction - (" _ _-_-----" - " _-_ ").ignore() // result looks strange because of 'diff.unimportant.line.char.count' testAll() } } @@ -428,4 +428,59 @@ class LineComparisonUtilTest : ComparisonUtilTestBase() { testDefault() } } + + fun `test ignore whitespace policy applies two-step correction`() { + lines() { + ("1_ _ 1" - " 1") + ("-_-_ " - " ").default() + (" _-_---" - " ").trim() + ("-_-_ " - " ").ignore() + testAll() + } + + lines() { + (" 1_ _1" - " 1") + (" _-_-" - " ").default() + testAll() + } + + lines() { + ("X_ Y_X" - "Y ") + ("-_--_-" - "--").default() + ("-_ _-" - " ").trim() + testAll() + } + } + + fun `test regression - second step correction should be performed if there are no ambigous matchings`() { + lines { + ("}_ }" - " }_}") + ("-_--" - "--_-").default() + (" _ " - " _ ").trim() + testAll() + } + + lines { + (" }_}_ }" - "}_}_}") + ("--_ _--" - "-_ _-").default() + (" _ _ " - " _ _ ").trim() + testAll() + } + + lines() { + ("X_X __Y" - "X__Z") + (" _--__-" - " __-").default() + ("-_ __-" - " __-").trim() + testAll() + } + } + + fun `test regression - second step with too many possible matchings`() { + lines { + (" X_X_X_X_X_X_X_X_X_X_X_X_X_X_X_X_X_X_X_X_X_X_X_ X" - "X_X_X_X_X_X_X_X_X_X_X_X_X_X_X_X_X_X_X ") + ("--_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _-_-_-_-_-_--" - "-_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _--").default() + (" _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _-_-_-_-_--" - " _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ").trim() + testAll() + } + } } From 40bd15da709167161d2ce56af37c80d398465e19 Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Mon, 20 Jun 2016 14:47:57 +0300 Subject: [PATCH 031/107] vcs: Show History For Selection - ignore whitespaces --- platform/vcs-impl/src/com/intellij/diff/Block.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/platform/vcs-impl/src/com/intellij/diff/Block.java b/platform/vcs-impl/src/com/intellij/diff/Block.java index b4cd7eea32c4..1e333cf119a4 100644 --- a/platform/vcs-impl/src/com/intellij/diff/Block.java +++ b/platform/vcs-impl/src/com/intellij/diff/Block.java @@ -69,7 +69,7 @@ public class Block { try { FairDiffIterable iterable = ByLine.compare(Arrays.asList(prevContent), Arrays.asList(mySource), - ComparisonPolicy.DEFAULT, DumbProgressIndicator.INSTANCE); + ComparisonPolicy.IGNORE_WHITESPACES, DumbProgressIndicator.INSTANCE); for (Pair pair : DiffIterableUtil.iterateAll(iterable)) { Boolean equals = pair.second; @@ -91,7 +91,11 @@ public class Block { // intern strings, reducing memory usage int count = range.end1 - range.start1; for (int i = 0; i < count; i++) { - prevContent[range.start1 + i] = mySource[range.start2 + i]; + int prevIndex = range.start1 + i; + int sourceIndex = range.start2 + i; + if (prevContent[prevIndex].equals(mySource[sourceIndex])) { + prevContent[prevIndex] = mySource[sourceIndex]; + } } } } From 9b3c7c0e2c8db7a72465981fb68c3779ed01213f Mon Sep 17 00:00:00 2001 From: Aleksey Pivovarov Date: Mon, 20 Jun 2016 14:53:46 +0300 Subject: [PATCH 032/107] lst: compare lines ignoring whitespaces in smart mode --- .../openapi/vcs/ex/RangesBuilder.java | 246 ++++++++++-------- 1 file changed, 143 insertions(+), 103 deletions(-) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/RangesBuilder.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/RangesBuilder.java index 56d7ca2449ee..3f12ec58f470 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/RangesBuilder.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/RangesBuilder.java @@ -15,17 +15,22 @@ */ package com.intellij.openapi.vcs.ex; +import com.intellij.diff.comparison.ByLine; +import com.intellij.diff.comparison.ComparisonPolicy; +import com.intellij.diff.comparison.TrimUtil; +import com.intellij.diff.comparison.iterables.DiffIterableUtil; +import com.intellij.diff.comparison.iterables.FairDiffIterable; import com.intellij.diff.util.DiffUtil; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.util.ArrayUtil; -import com.intellij.util.diff.Diff; +import com.intellij.openapi.progress.DumbProgressIndicator; +import com.intellij.openapi.util.Pair; +import com.intellij.openapi.vcs.ex.Range.InnerRange; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.diff.FilesTooBigForDiffException; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; -import java.util.Collections; import java.util.List; public class RangesBuilder { @@ -45,131 +50,166 @@ public class RangesBuilder { @NotNull public static List createRanges(@NotNull List current, @NotNull List vcs, - int shift, + int currentShift, int vcsShift, boolean innerWhitespaceChanges) throws FilesTooBigForDiffException { - Diff.Change ch = Diff.buildChanges(ArrayUtil.toStringArray(vcs), ArrayUtil.toStringArray(current)); + if (innerWhitespaceChanges) { + return createRangesSmart(current, vcs, currentShift, vcsShift); + } + else { + return createRangesSimple(current, vcs, currentShift, vcsShift); + } + } + + @NotNull + private static List createRangesSimple(@NotNull List current, + @NotNull List vcs, + int currentShift, + int vcsShift) throws FilesTooBigForDiffException { + FairDiffIterable iterable = ByLine.compare(vcs, current, ComparisonPolicy.DEFAULT, DumbProgressIndicator.INSTANCE); List result = new ArrayList(); - while (ch != null) { - if (innerWhitespaceChanges) { - result.add(createOnSmart(ch, shift, vcsShift, current, vcs)); - } - else { - result.add(createOn(ch, shift, vcsShift)); - } - ch = ch.link; + for (com.intellij.diff.util.Range range : iterable.iterateChanges()) { + int vcsLine1 = vcsShift + range.start1; + int vcsLine2 = vcsShift + range.end1; + int currentLine1 = currentShift + range.start2; + int currentLine2 = currentShift + range.end2; + + result.add(new Range(currentLine1, currentLine2, vcsLine1, vcsLine2)); } return result; } - private static Range createOn(@NotNull Diff.Change change, int shift, int vcsShift) { - int offset1 = shift + change.line1; - int offset2 = offset1 + change.inserted; + @NotNull + private static List createRangesSmart(@NotNull List current, + @NotNull List vcs, + int shift, + int vcsShift) throws FilesTooBigForDiffException { + FairDiffIterable iwIterable = ByLine.compare(vcs, current, ComparisonPolicy.IGNORE_WHITESPACES, DumbProgressIndicator.INSTANCE); - int uOffset1 = vcsShift + change.line0; - int uOffset2 = uOffset1 + change.deleted; + RangeBuilder rangeBuilder = new RangeBuilder(current, vcs, shift, vcsShift); - return new Range(offset1, offset2, uOffset1, uOffset2); - } + for (Pair pair : DiffIterableUtil.iterateAll(iwIterable)) { + com.intellij.diff.util.Range range = pair.first; + Boolean equals = pair.second; - private static Range createOnSmart(@NotNull Diff.Change change, - int shift, - int vcsShift, - @NotNull List current, - @NotNull List vcs) throws FilesTooBigForDiffException { - byte type = getChangeType(change); + if (equals) { + int count = range.end1 - range.start1; + for (int i = 0; i < count; i++) { + int vcsIndex = range.start1 + i; + int currentIndex = range.start2 + i; + String vcsLine = vcs.get(vcsIndex); + String currentLine = current.get(currentIndex); - int offset1 = shift + change.line1; - int offset2 = offset1 + change.inserted; - - int uOffset1 = vcsShift + change.line0; - int uOffset2 = uOffset1 + change.deleted; - - if (type != Range.MODIFIED) { - return new Range(offset1, offset2, uOffset1, uOffset2, Collections.singletonList(new Range.InnerRange(offset1, offset2, type))); - } - - LineWrapper[] lines1 = new LineWrapper[change.deleted]; - LineWrapper[] lines2 = new LineWrapper[change.inserted]; - for (int i = 0; i < change.deleted; i++) { - lines1[i] = new LineWrapper(vcs.get(i + change.line0)); - } - for (int i = 0; i < change.inserted; i++) { - lines2[i] = new LineWrapper(current.get(i + change.line1)); - } - - Diff.Change ch = Diff.buildChanges(lines1, lines2); - - List inner = new ArrayList(); - - int last0 = 0; - int last1 = 0; - while (ch != null) { - if (ch.line0 != last0 && ch.line1 != last1) { - byte innerType = Range.EQUAL; - int innerStart = shift + change.line1 + last1; - int innerEnd = shift + change.line1 + ch.line1; - inner.add(new Range.InnerRange(innerStart, innerEnd, innerType)); + if (vcsLine.equals(currentLine)) { + rangeBuilder.flushChange(); + } + else { + rangeBuilder.markChangedWhitespaces(vcsIndex, currentIndex); + } + } + } + else { + rangeBuilder.markChanged(range.start1, range.end1, range.start2, range.end2); } - - byte innerType = getChangeType(ch); - int innerStart = shift + change.line1 + ch.line1; - int innerEnd = innerStart + ch.inserted; - inner.add(new Range.InnerRange(innerStart, innerEnd, innerType)); - - last0 = ch.line0 + ch.deleted; - last1 = ch.line1 + ch.inserted; - - ch = ch.link; - } - if (change.deleted != last0 && change.inserted != last1) { - byte innerType = Range.EQUAL; - int innerStart = shift + change.line1 + last1; - int innerEnd = shift + change.line1 + change.inserted; - inner.add(new Range.InnerRange(innerStart, innerEnd, innerType)); } - return new Range(offset1, offset2, uOffset1, uOffset2, inner); + return rangeBuilder.finish(); } - private static byte getChangeType(@NotNull Diff.Change change) { - if ((change.deleted > 0) && (change.inserted > 0)) return Range.MODIFIED; - if ((change.deleted > 0)) return Range.DELETED; - if ((change.inserted > 0)) return Range.INSERTED; - LOG.error("Unknown change type"); - return Range.EQUAL; - } + private static class RangeBuilder { + @NotNull private final List myCurrent; + @NotNull private final List myVcs; + private final int myCurrentShift; + private final int myVcsShift; - private static class LineWrapper { - @NotNull private final String myLine; - private final int myHash; + @NotNull private final List myRanges = new ArrayList<>(); - public LineWrapper(@NotNull String line) { - myLine = line; - myHash = StringUtil.stringHashCodeIgnoreWhitespaces(line); + private com.intellij.diff.util.Range change; + private ArrayList innerRanges; + + public RangeBuilder(@NotNull List current, + @NotNull List vcs, + int currentShift, + int vcsShift) { + myCurrent = current; + myVcs = vcs; + myCurrentShift = currentShift; + myVcsShift = vcsShift; + } + + public void flushChange() { + if (change == null) return; + + for (InnerRange range : innerRanges) { + range.shift(myCurrentShift); + } + innerRanges.trimToSize(); + + change = TrimUtil.expand(myVcs, myCurrent, change.start1, change.start2, change.end1, change.end2); + + int currentLine1 = myCurrentShift + change.start2; + int currentLine2 = myCurrentShift + change.end2; + int vcsLine1 = myVcsShift + change.start1; + int vcsLine2 = myVcsShift + change.end1; + myRanges.add(new Range(currentLine1, currentLine2, vcsLine1, vcsLine2, innerRanges)); + + change = null; + innerRanges = null; + } + + public void markChangedWhitespaces(int vcsIndex, int currentIndex) { + appendChangedLine(vcsIndex, vcsIndex + 1, currentIndex, currentIndex + 1); + appendInnerEquals(vcsIndex, vcsIndex + 1, currentIndex, currentIndex + 1); + } + + public void markChanged(int vcsStart, int vcsEnd, int currentStart, int currentEnd) { + appendChangedLine(vcsStart, vcsEnd, currentStart, currentEnd); + appendInnerChange(vcsStart, vcsEnd, currentStart, currentEnd); } @NotNull - public String getLine() { - return myLine; + public List finish() { + flushChange(); + return myRanges; } - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - LineWrapper wrapper = (LineWrapper)o; - - if (myHash != wrapper.myHash) return false; - - return StringUtil.equalsIgnoreWhitespaces(myLine, wrapper.myLine); + private void appendChangedLine(int vcsStart, int vcsEnd, int currentStart, int currentEnd) { + if (change == null) { + change = new com.intellij.diff.util.Range(vcsStart, vcsEnd, currentStart, currentEnd); + innerRanges = new ArrayList<>(); + } + else { + assert vcsStart == change.end1; + assert currentStart == change.end2; + change = new com.intellij.diff.util.Range(change.start1, vcsEnd, change.start2, currentEnd); + } } - @Override - public int hashCode() { - return myHash; + private void appendInnerChange(int vcsStart, int vcsEnd, int currentStart, int currentEnd) { + byte type = getChangeType(vcsStart, vcsEnd, currentStart, currentEnd); + innerRanges.add(new InnerRange(currentStart, currentEnd, type)); + } + + private void appendInnerEquals(int vcsStart, int vcsEnd, int currentStart, int currentEnd) { + InnerRange last = ContainerUtil.getLastItem(innerRanges); + if (last == null || last.getType() != Range.EQUAL) { + innerRanges.add(new InnerRange(currentStart, currentEnd, Range.EQUAL)); + } + else { + assert currentStart == last.getLine2(); + innerRanges.set(innerRanges.size() - 1, new InnerRange(last.getLine1(), currentEnd, Range.EQUAL)); + } } } + + private static byte getChangeType(int vcsStart, int vcsEnd, int currentStart, int currentEnd) { + int deleted = vcsEnd - vcsStart; + int inserted = currentEnd - currentStart; + if (deleted > 0 && inserted > 0) return Range.MODIFIED; + if (deleted > 0) return Range.DELETED; + if (inserted > 0) return Range.INSERTED; + LOG.error("Unknown change type"); + return Range.EQUAL; + } } From b10d17121b5ffe133c4c1cb029b2844162885248 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Thu, 23 Jun 2016 18:05:43 +0200 Subject: [PATCH 033/107] (when we have only large added value set) if given key has number of values more than threshold calculate / use direct mapping of fileId -> Value instead of traversing all values (thus removing O(NumberOfValues) per fileId) --- .../intellij/util/indexing/ChangeTrackingValueContainer.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/util/indexing/ChangeTrackingValueContainer.java b/platform/lang-impl/src/com/intellij/util/indexing/ChangeTrackingValueContainer.java index 096e77b84ceb..45dbb6fad664 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/ChangeTrackingValueContainer.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/ChangeTrackingValueContainer.java @@ -127,7 +127,9 @@ class ChangeTrackingValueContainer extends UpdatableValueContainer newMerged = ((ChangeTrackingValueContainer)fromDisk).getMergedData().copy(); } - if ((myAdded != null || myInvalidated != null) && newMerged.size() > ValueContainerImpl.NUMBER_OF_VALUES_THRESHOLD) { + if ((myAdded != null || myInvalidated != null) && + (newMerged.size() > ValueContainerImpl.NUMBER_OF_VALUES_THRESHOLD || + myAdded.size() > ValueContainerImpl.NUMBER_OF_VALUES_THRESHOLD)) { // Calculate file ids that have Value mapped to avoid O(NumberOfValuesInMerged) during removal fileId2ValueMapping = new FileId2ValueMapping(newMerged); } From 1cb3686356729f23e05007913a1683ecdc821b39 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Thu, 23 Jun 2016 18:36:59 +0200 Subject: [PATCH 034/107] fix of NPE --- .../intellij/util/indexing/ChangeTrackingValueContainer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/util/indexing/ChangeTrackingValueContainer.java b/platform/lang-impl/src/com/intellij/util/indexing/ChangeTrackingValueContainer.java index 45dbb6fad664..b2a358ebbcf4 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/ChangeTrackingValueContainer.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/ChangeTrackingValueContainer.java @@ -129,7 +129,7 @@ class ChangeTrackingValueContainer extends UpdatableValueContainer if ((myAdded != null || myInvalidated != null) && (newMerged.size() > ValueContainerImpl.NUMBER_OF_VALUES_THRESHOLD || - myAdded.size() > ValueContainerImpl.NUMBER_OF_VALUES_THRESHOLD)) { + (myAdded != null && myAdded.size() > ValueContainerImpl.NUMBER_OF_VALUES_THRESHOLD))) { // Calculate file ids that have Value mapped to avoid O(NumberOfValuesInMerged) during removal fileId2ValueMapping = new FileId2ValueMapping(newMerged); } From 8bef89b7850f90201fc21004311eb0da3f0fc447 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 23 Jun 2016 18:03:17 +0300 Subject: [PATCH 035/107] set error hint title (IDEA-157821) --- .../intellij/refactoring/extractclass/ExtractClassHandler.java | 2 +- .../refactoring/extractclass/ExtractClassProcessor.java | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/java/java-impl/src/com/intellij/refactoring/extractclass/ExtractClassHandler.java b/java/java-impl/src/com/intellij/refactoring/extractclass/ExtractClassHandler.java index b263d49ddfdc..6a6146434d54 100644 --- a/java/java-impl/src/com/intellij/refactoring/extractclass/ExtractClassHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/extractclass/ExtractClassHandler.java @@ -63,7 +63,7 @@ public class ExtractClassHandler implements ElementsHandler { if (cannotRefactorMessage != null) { CommonRefactoringUtil.showErrorHint(project, editor, RefactorJBundle.message("cannot.perform.the.refactoring") + cannotRefactorMessage, - null, getHelpID()); + ExtractClassProcessor.REFACTORING_NAME, getHelpID()); return; } new ExtractClassDialog(containingClass, selectedMember).show(); diff --git a/java/java-impl/src/com/intellij/refactoring/extractclass/ExtractClassProcessor.java b/java/java-impl/src/com/intellij/refactoring/extractclass/ExtractClassProcessor.java index 1e92218a183e..b0f0236075f0 100644 --- a/java/java-impl/src/com/intellij/refactoring/extractclass/ExtractClassProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/extractclass/ExtractClassProcessor.java @@ -66,6 +66,7 @@ import java.util.*; public class ExtractClassProcessor extends FixableUsagesRefactoringProcessor { private static final Logger logger = Logger.getInstance("com.siyeh.rpp.extractclass.ExtractClassProcessor"); + @NonNls public static final String REFACTORING_NAME = "Extract Delegate"; private final PsiClass sourceClass; private final List fields; From 7408f4325f71a3dd91ff403b569e04cfa44876ee Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 23 Jun 2016 21:25:02 +0300 Subject: [PATCH 036/107] offline inspections: store in descriptions which tools were enabled --- .../codeInspection/InspectionApplication.java | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInspection/InspectionApplication.java b/platform/lang-impl/src/com/intellij/codeInspection/InspectionApplication.java index 50b7d0a414e4..03a5ecc59e3b 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/InspectionApplication.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/InspectionApplication.java @@ -17,6 +17,7 @@ package com.intellij.codeInspection; import com.intellij.analysis.AnalysisScope; +import com.intellij.codeInsight.daemon.HighlightDisplayKey; import com.intellij.codeInspection.ex.*; import com.intellij.conversion.ConversionListener; import com.intellij.conversion.ConversionService; @@ -257,7 +258,8 @@ public class InspectionApplication { }); final String descriptionsFile = resultsDataPath + File.separatorChar + DESCRIPTIONS + XML_EXTENSION; describeInspections(descriptionsFile, - myRunWithEditorSettings ? null : inspectionProfile.getName()); + myRunWithEditorSettings ? null : inspectionProfile.getName(), + (InspectionProfile)inspectionProfile); inspectionsResults.add(new File(descriptionsFile)); // convert report if (reportConverter != null) { @@ -448,8 +450,8 @@ public class InspectionApplication { } } - private static void describeInspections(@NonNls String myOutputPath, final String name) throws IOException { - final InspectionToolWrapper[] toolWrappers = InspectionProfileImpl.getDefaultProfile().getInspectionTools(null); + private static void describeInspections(@NonNls String myOutputPath, final String name, final InspectionProfile profile) throws IOException { + final InspectionToolWrapper[] toolWrappers = profile.getInspectionTools(null); final Map> map = new HashMap>(); for (InspectionToolWrapper toolWrapper : toolWrappers) { final String groupName = toolWrapper.getGroupDisplayName(); @@ -474,14 +476,17 @@ public class InspectionApplication { final Set entries = map.get(groupName); for (InspectionToolWrapper toolWrapper : entries) { xmlWriter.startNode("inspection"); - xmlWriter.addAttribute("shortName", toolWrapper.getShortName()); + final String shortName = toolWrapper.getShortName(); + xmlWriter.addAttribute("shortName", shortName); xmlWriter.addAttribute("displayName", toolWrapper.getDisplayName()); + final boolean toolEnabled = profile.isToolEnabled(HighlightDisplayKey.find(shortName)); + xmlWriter.addAttribute("enabled", Boolean.toString(toolEnabled)); final String description = toolWrapper.loadDescription(); if (description != null) { xmlWriter.setValue(description); } else { - LOG.error(toolWrapper.getShortName() + " descriptionUrl==" + toolWrapper); + LOG.error(shortName + " descriptionUrl==" + toolWrapper); } xmlWriter.endNode(); } From f5733769b96e3a4847ef86334662f60fc09b54e1 Mon Sep 17 00:00:00 2001 From: Julia Beliaeva Date: Thu, 23 Jun 2016 20:08:58 +0300 Subject: [PATCH 037/107] [vcs-log] enhance roots statistic --- .../intellij/vcs/log/statistics/VcsLogRepoSizeCollector.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/statistics/VcsLogRepoSizeCollector.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/statistics/VcsLogRepoSizeCollector.java index 5fb354443773..37c41b6033d4 100644 --- a/platform/vcs-log/impl/src/com/intellij/vcs/log/statistics/VcsLogRepoSizeCollector.java +++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/statistics/VcsLogRepoSizeCollector.java @@ -59,7 +59,7 @@ public class VcsLogRepoSizeCollector extends AbstractApplicationUsagesCollector asList(0, 1, 100, 1000, 10 * 1000, 100 * 1000, 500 * 1000))); for (VcsKey vcs : groupedRoots.keySet()) { usages.add(StatisticsUtilKt.getCountingUsage("data." + vcs.getName().toLowerCase() + ".root.count", groupedRoots.get(vcs).size(), - asList(0, 1, 2, 5, 8, 15, 30, 50, 100))); + asList(0, 1, 2, 5, 8, 15, 30, 50, 100, 500, 1000))); } return usages; } From 896a59ae495be51654dbead566ab5c3c15328e3d Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Thu, 23 Jun 2016 21:56:40 +0200 Subject: [PATCH 038/107] fix frame decoration size and painting --- .../ui/laf/darcula/ui/DarculaTitlePane.java | 81 ++++++++++--------- .../intellij/openapi/wm/impl/IdeRootPane.java | 2 +- 2 files changed, 42 insertions(+), 41 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaTitlePane.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaTitlePane.java index 0f3704882e77..2c91e3b7e546 100644 --- a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaTitlePane.java +++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaTitlePane.java @@ -15,14 +15,18 @@ */ package com.intellij.ide.ui.laf.darcula.ui; +import com.intellij.icons.AllIcons; import com.intellij.ide.DataManager; import com.intellij.openapi.actionSystem.ex.ActionManagerEx; -import com.intellij.openapi.ui.GraphicsConfig; import com.intellij.openapi.wm.impl.IdeMenuBar; import com.intellij.openapi.wm.impl.IdeRootPane; import com.intellij.ui.Gray; import com.intellij.ui.JBColor; -import com.intellij.util.ui.*; +import com.intellij.util.IconUtil; +import com.intellij.util.ui.ImageUtil; +import com.intellij.util.ui.JBDimension; +import com.intellij.util.ui.JBUI; +import com.intellij.util.ui.UIUtil; import org.imgscalr.Scalr; import sun.swing.SwingUtilities2; @@ -293,7 +297,7 @@ public class DarculaTitlePane extends JComponent { menu.add(myCloseAction); } - private static JButton createButton(String accessibleName, Icon icon, Action action, boolean isCloseAction) { + private static JButton createButton(String accessibleName, Icon icon, Icon hoverIcon, Action action, Color hoverBg) { JButton button = new JButton() { boolean mouseOverButton = false; { @@ -314,15 +318,11 @@ public class DarculaTitlePane extends JComponent { } @Override protected void paintComponent(Graphics g) { - final Window window = SwingUtilities.windowForComponent(this); - float alpha = window.isActive() && mouseOverButton ? 1f : 0.5f; - if (isCloseAction && mouseOverButton) { - g.setColor(Color.red); + if (mouseOverButton) { + g.setColor(hoverBg); g.fillRect(0, 0, getWidth(), getHeight()); } - final GraphicsConfig config = GraphicsUtil.paintWithAlpha(g, alpha); - getIcon().paintIcon(this, g, 0, 0); - config.restore(); + IconUtil.paintInCenterOf(this, g, mouseOverButton ? hoverIcon : icon); } }; button.setFocusPainted(false); @@ -338,14 +338,14 @@ public class DarculaTitlePane extends JComponent { } private void createButtons() { - myCloseButton = createButton("Close", UIManager.getIcon("InternalFrame.closeIcon"), myCloseAction, true); + myCloseButton = createButton("Close", AllIcons.Windows.CloseActive, AllIcons.Windows.CloseHover, myCloseAction, Color.red); if (getWindowDecorationStyle() == JRootPane.FRAME) { myMaximizeIcon = UIManager.getIcon("InternalFrame.maximizeIcon"); myMinimizeIcon = UIManager.getIcon("InternalFrame.minimizeIcon"); - myIconifyButton = createButton("Iconify", UIManager.getIcon("InternalFrame.iconifyIcon"), myIconifyAction, false); - myToggleButton = createButton("Maximize", myMaximizeIcon, myRestoreAction, false); + myIconifyButton = createButton("Iconify", AllIcons.Windows.MinimizeInactive, AllIcons.Windows.Minimize, myIconifyAction, new Color(0x55585A)); + myToggleButton = createButton("Maximize", AllIcons.Windows.MaximizeInactive, AllIcons.Windows.MaximizeInactive, myRestoreAction, new Color(0x55585A)); } } @@ -545,14 +545,14 @@ public class DarculaTitlePane extends JComponent { } - int w = width; - int h = height; - h--; + //int w = width; + //int h = height; + //h--; g.setColor(UIManager.getColor("MenuBar.darcula.borderColor")); - g.drawLine(0, h, w, h); - h--; - g.setColor(UIManager.getColor("MenuBar.darcula.borderShadowColor")); - g.drawLine(0, h, w, h); + //g.drawLine(0, h, w, h); + //h--; + //g.setColor(UIManager.getColor("MenuBar.darcula.borderShadowColor")); + g.drawLine(0, getHeight()-1, getWidth(), getHeight()-1); } private class CloseAction extends AbstractAction { @@ -608,7 +608,8 @@ public class DarculaTitlePane extends JComponent { } if (mySystemIcon != null) { - g.drawImage(mySystemIcon, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, null); + final int offset = (getHeight() - mySystemIcon.getHeight(null)) / 2; + g.drawImage(mySystemIcon, offset, offset, null); } else { Icon icon = UIManager.getIcon("InternalFrame.icon"); @@ -657,7 +658,7 @@ public class DarculaTitlePane extends JComponent { iconHeight = IMAGE_HEIGHT; } - return Math.max(Math.max(fontHeight, iconHeight), JBUI.scale(myIdeMenu == null ? 28 : 36)); + return Math.max(Math.max(fontHeight, iconHeight), JBUI.scale(31)); } public void layoutContainer(Container c) { @@ -665,17 +666,17 @@ public class DarculaTitlePane extends JComponent { int h = getHeight(); int x; int spacing; - int buttonHeight; - int buttonWidth; + int buttonHeight = JBUI.scale(29); + int buttonWidth = JBUI.scale(45); - if (myCloseButton != null && myCloseButton.getIcon() != null) { - buttonHeight = myCloseButton.getIcon().getIconHeight(); - buttonWidth = myCloseButton.getIcon().getIconWidth(); - } - else { - buttonHeight = IMAGE_HEIGHT; - buttonWidth = IMAGE_WIDTH; - } + //if (myCloseButton != null && myCloseButton.getIcon() != null) { + // buttonHeight = myCloseButton.getIcon().getIconHeight(); + // buttonWidth = myCloseButton.getIcon().getIconWidth(); + //} + //else { + // buttonHeight = IMAGE_HEIGHT; + // buttonWidth = IMAGE_WIDTH; + //} spacing = 5; x = spacing; @@ -683,33 +684,33 @@ public class DarculaTitlePane extends JComponent { myMenuBar.setBounds(x, (h - buttonHeight) / 2, buttonWidth, buttonHeight); } + int systemIconSize = mySystemIcon == null ? JBUI.scale(16) : mySystemIcon.getWidth(null); + + x = buttonHeight - systemIconSize + systemIconSize + systemIconSize/2; // offset + width + offset, where offset is (H - iconHeight) / 2 if (myIdeMenu != null) { final Dimension size = myIdeMenu.getPreferredSize(); - x += spacing + (myMenuBar != null ? buttonWidth : 0); - myIdeMenu.setBounds(x, (h - size.height) / 2, size.width, size.height); } x = w; - spacing = 14; - x += -spacing - buttonWidth; + spacing = 0; + x -= spacing + buttonWidth; if (myCloseButton != null) { myCloseButton.setBounds(x, (h - buttonHeight) / 2, buttonWidth, buttonHeight); } - spacing = 30; if (getWindowDecorationStyle() == JRootPane.FRAME) { if (Toolkit.getDefaultToolkit().isFrameStateSupported( Frame.MAXIMIZED_BOTH)) { if (myToggleButton.getParent() != null) { //spacing = 10; - x += -spacing - buttonWidth; + x -= spacing + buttonWidth; myToggleButton.setBounds(x, (h - buttonHeight) / 2, buttonWidth, buttonHeight); } } if (myIconifyButton != null && myIconifyButton.getParent() != null) { - x += -spacing - buttonWidth; + x -= spacing + buttonWidth; myIconifyButton.setBounds(x, (h - buttonHeight) / 2, buttonWidth, buttonHeight); } } @@ -761,7 +762,7 @@ public class DarculaTitlePane extends JComponent { } else if (icons.size() == 1) { mySystemIcon = icons.get(0); } else { - final JBDimension size = JBUI.size(32); + final JBDimension size = JBUI.size(16); final Image image = icons.get(0); mySystemIcon = Scalr.resize(ImageUtil.toBufferedImage(image), Scalr.Method.ULTRA_QUALITY, size.width, size.height); } 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 574524d3f569..5037e0edc2e8 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 @@ -89,7 +89,7 @@ public class IdeRootPane extends JRootPane implements UISettingsListener { private boolean myFullScreen; public IdeRootPane(ActionManagerEx actionManager, DataManager dataManager, Application application, final IdeFrame frame) { - if (SystemInfo.isWindows && (UIUtil.isUnderDarcula() /*|| UIUtil.isUnderIntelliJLaF()*/) && frame instanceof IdeFrameImpl) { + if (SystemInfo.isWindows && (UIUtil.isUnderDarcula() || UIUtil.isUnderIntelliJLaF()) && frame instanceof IdeFrameImpl) { //setUI(DarculaRootPaneUI.createUI(this)); setWindowDecorationStyle(FRAME); } From f09c6512352ee5c1b8b5375bb2ddd1a31af5209c Mon Sep 17 00:00:00 2001 From: "Gregory.Shrago" Date: Fri, 24 Jun 2016 04:34:52 +0300 Subject: [PATCH 039/107] EA-84787 - IAE: PackageSetBase.contains --- .../com/intellij/ide/scopeView/ScopePaneSelectInTarget.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/ide/scopeView/ScopePaneSelectInTarget.java b/platform/lang-impl/src/com/intellij/ide/scopeView/ScopePaneSelectInTarget.java index 78d612f36939..99d00a895cd4 100644 --- a/platform/lang-impl/src/com/intellij/ide/scopeView/ScopePaneSelectInTarget.java +++ b/platform/lang-impl/src/com/intellij/ide/scopeView/ScopePaneSelectInTarget.java @@ -51,7 +51,8 @@ public class ScopePaneSelectInTarget extends ProjectViewSelectInTarget { } @Nullable - private NamedScope getContainingScope(PsiFile file) { + private NamedScope getContainingScope(@Nullable PsiFile file) { + if (file == null) return null; NamedScopesHolder scopesHolder = DependencyValidationManager.getInstance(myProject); for (NamedScope scope : ScopeViewPane.getShownScopes(myProject)) { PackageSet packageSet = scope.getValue(); From 0b9435c51173ce0a69097cd453994a0f455a1c11 Mon Sep 17 00:00:00 2001 From: "Gregory.Shrago" Date: Fri, 24 Jun 2016 09:50:21 +0300 Subject: [PATCH 040/107] EA-73474 - assert: DummyCachingFileSystem.onProjectOpened --- .../intellij/openapi/project/impl/ProjectManagerImpl.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java index 0cc2487e0846..1ec346b95475 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java @@ -314,6 +314,13 @@ public class ProjectManagerImpl extends ProjectManagerEx implements Disposable { } } + for (Project p : myOpenProjects) { + if (ProjectUtil.isSameProject(project.getBasePath(), p)) { + ProjectUtil.focusProjectWindow(p, false); + return false; + } + } + if (!addToOpened(project)) { return false; } From 237ed2663d90205e73009bd0a713e7a5acb06b68 Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Mon, 20 Jun 2016 19:38:35 +0300 Subject: [PATCH 041/107] cleanup, removed unneeded parameters --- .../com/jetbrains/edu/coursecreator/CCUtils.java | 15 +++++++-------- .../actions/CCAddAnswerPlaceholder.java | 2 +- .../actions/CCAnswerPlaceholderAction.java | 6 ++---- .../actions/CCCreateCourseArchive.java | 2 +- .../actions/CCEditAnswerPlaceholder.java | 2 +- .../projectView/CCTreeStructureProvider.java | 6 +++--- .../learning/actions/StudyNextWindowAction.java | 2 +- 7 files changed, 16 insertions(+), 19 deletions(-) diff --git a/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/CCUtils.java b/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/CCUtils.java index 5ab441fd84bf..edd3a7f240ac 100644 --- a/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/CCUtils.java +++ b/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/CCUtils.java @@ -18,7 +18,6 @@ import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.openapi.vfs.VirtualFileEvent; import com.intellij.psi.PsiDirectory; import com.intellij.util.DocumentUtil; import com.intellij.util.Function; @@ -31,7 +30,10 @@ import org.jetbrains.annotations.Nullable; import java.io.File; import java.io.IOException; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Map; public class CCUtils { public static final String ANSWER_EXTENSION_DOTTED = ".answer."; @@ -144,11 +146,8 @@ public class CCUtils { return generatedRoot.get(); } - /** - * @param requestor {@link VirtualFileEvent#getRequestor} - */ @Nullable - public static VirtualFile generateFolder(@NotNull Project project, @NotNull Module module, @Nullable Object requestor, String name) { + public static VirtualFile generateFolder(@NotNull Project project, @NotNull Module module, String name) { VirtualFile generatedRoot = getGeneratedFilesFolder(project, module); if (generatedRoot == null) { return null; @@ -159,9 +158,9 @@ public class CCUtils { ApplicationManager.getApplication().runWriteAction(() -> { try { if (folder.get() != null) { - folder.get().delete(requestor); + folder.get().delete(null); } - folder.set(generatedRoot.createChildDirectory(requestor, name)); + folder.set(generatedRoot.createChildDirectory(null, name)); } catch (IOException e) { LOG.info("Failed to generate folder " + name, e); diff --git a/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCAddAnswerPlaceholder.java b/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCAddAnswerPlaceholder.java index 41275862f6f0..0643eaa8cf0c 100644 --- a/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCAddAnswerPlaceholder.java +++ b/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCAddAnswerPlaceholder.java @@ -26,7 +26,7 @@ import java.util.List; public class CCAddAnswerPlaceholder extends CCAnswerPlaceholderAction { public CCAddAnswerPlaceholder() { - super("Add/Delete Answer Placeholder", "Add/Delete answer placeholder", null); + super("Add/Delete Answer Placeholder", "Add/Delete answer placeholder"); } diff --git a/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCAnswerPlaceholderAction.java b/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCAnswerPlaceholderAction.java index 4a0479403094..ba3db4d16fb1 100644 --- a/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCAnswerPlaceholderAction.java +++ b/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCAnswerPlaceholderAction.java @@ -14,12 +14,10 @@ import com.jetbrains.edu.learning.courseFormat.TaskFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import javax.swing.*; - abstract public class CCAnswerPlaceholderAction extends DumbAwareAction { - protected CCAnswerPlaceholderAction(@Nullable String text, @Nullable String description, @Nullable Icon icon) { - super(text, description, icon); + protected CCAnswerPlaceholderAction(@Nullable String text, @Nullable String description) { + super(text, description, null); } @Nullable diff --git a/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateCourseArchive.java b/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateCourseArchive.java index 8425c71b0483..50e2336444f5 100644 --- a/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateCourseArchive.java +++ b/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCCreateCourseArchive.java @@ -77,7 +77,7 @@ public class CCCreateCourseArchive extends DumbAwareAction { final Course course = StudyTaskManager.getInstance(project).getCourse(); if (course == null) return; final VirtualFile baseDir = project.getBaseDir(); - VirtualFile archiveFolder = CCUtils.generateFolder(project, module, null, zipName); + VirtualFile archiveFolder = CCUtils.generateFolder(project, module, zipName); if (archiveFolder == null) { return; } diff --git a/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCEditAnswerPlaceholder.java b/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCEditAnswerPlaceholder.java index 622ddacf1cac..72a33a1e0261 100644 --- a/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCEditAnswerPlaceholder.java +++ b/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCEditAnswerPlaceholder.java @@ -12,7 +12,7 @@ import org.jetbrains.annotations.NotNull; public class CCEditAnswerPlaceholder extends CCAnswerPlaceholderAction { public CCEditAnswerPlaceholder() { - super("Edit Answer Placeholder", "Edit answer placeholder", null); + super("Edit Answer Placeholder", "Edit answer placeholder"); } @Override diff --git a/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/projectView/CCTreeStructureProvider.java b/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/projectView/CCTreeStructureProvider.java index 3ba35d688992..39d0ab89145b 100644 --- a/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/projectView/CCTreeStructureProvider.java +++ b/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/projectView/CCTreeStructureProvider.java @@ -12,7 +12,6 @@ import com.jetbrains.edu.learning.StudyUtils; import com.jetbrains.edu.learning.projectView.StudyTreeStructureProvider; import org.jetbrains.annotations.NotNull; -import java.util.ArrayList; import java.util.Collection; public class CCTreeStructureProvider extends StudyTreeStructureProvider { @@ -24,7 +23,7 @@ public class CCTreeStructureProvider extends StudyTreeStructureProvider { if (!needModify(parent)) { return children; } - Collection modifiedChildren = new ArrayList(super.modify(parent, children, settings)); + Collection modifiedChildren = super.modify(parent, children, settings); for (AbstractTreeNode node : children) { Project project = node.getProject(); @@ -41,7 +40,8 @@ public class CCTreeStructureProvider extends StudyTreeStructureProvider { if (virtualFile == null) { continue; } - if (StudyUtils.getTaskFile(project, virtualFile) == null && !StudyUtils.isTaskDescriptionFile(virtualFile.getName())) { + if (project != null && StudyUtils.getTaskFile(project, virtualFile) == null + && !StudyUtils.isTaskDescriptionFile(virtualFile.getName())) { modifiedChildren.add(new CCStudentInvisibleFileNode(project, ((PsiFileNode)node).getValue(), settings)); } } diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/actions/StudyNextWindowAction.java b/python/educational-core/student/src/com/jetbrains/edu/learning/actions/StudyNextWindowAction.java index 01fd8dcbceec..17769a988282 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/actions/StudyNextWindowAction.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/actions/StudyNextWindowAction.java @@ -26,7 +26,7 @@ public class StudyNextWindowAction extends StudyWindowNavigationAction { List windows = window.getTaskFile().getAnswerPlaceholders(); if (StudyUtils.indexIsValid(index, windows)) { int newIndex = index + 1; - return newIndex == windows.size() ? windows.get(0) : windows.get(newIndex); + return windows.get(newIndex == windows.size() ? 0 : newIndex); } return null; } From 2c051a016112173bef94c5b0ac5e84b87e91aaef Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Mon, 20 Jun 2016 19:42:20 +0300 Subject: [PATCH 042/107] cleanup, removed not needed parameters --- .../edu/learning/stepic/EduAdaptiveStepicConnector.java | 6 +++--- .../edu/learning/stepic/StepicAdaptiveReactionsPanel.java | 7 +++---- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/EduAdaptiveStepicConnector.java b/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/EduAdaptiveStepicConnector.java index 18225c548598..d867774a22c3 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/EduAdaptiveStepicConnector.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/EduAdaptiveStepicConnector.java @@ -403,7 +403,7 @@ public class EduAdaptiveStepicConnector { public static Pair checkTask(@NotNull final Project project, @NotNull final Task task) { int attemptId = -1; try { - attemptId = getAttemptId(project, task, EduStepicNames.ATTEMPTS); + attemptId = getAttemptId(project, task); } catch (IOException e) { LOG.warn(e.getMessage()); @@ -519,10 +519,10 @@ public class EduAdaptiveStepicConnector { return null; } - private static int getAttemptId(@NotNull final Project project, @NotNull Task task, @NotNull final String attempts) throws IOException { + private static int getAttemptId(@NotNull final Project project, @NotNull Task task) throws IOException { final StepicWrappers.AttemptToPostWrapper attemptWrapper = new StepicWrappers.AttemptToPostWrapper(task.getStepicId()); - final HttpPost post = new HttpPost(EduStepicNames.STEPIC_API_URL + attempts); + final HttpPost post = new HttpPost(EduStepicNames.STEPIC_API_URL + EduStepicNames.ATTEMPTS); post.setEntity(new StringEntity(new Gson().toJson(attemptWrapper))); final CloseableHttpClient client = getHttpClient(project); diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/StepicAdaptiveReactionsPanel.java b/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/StepicAdaptiveReactionsPanel.java index 04a52dec8e7d..24db1b1575aa 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/StepicAdaptiveReactionsPanel.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/StepicAdaptiveReactionsPanel.java @@ -38,8 +38,8 @@ public class StepicAdaptiveReactionsPanel extends JPanel { setLayout(new GridBagLayout()); setBackground(UIUtil.getTextFieldBackground()); - myHardPanel = new ReactionButtonPanel(HARD_REACTION, HARD_LABEL_TOOLTIP, SOLVED_TASK_TOOLTIP, TOO_HARD_REACTION); - myBoringPanel = new ReactionButtonPanel(BORING_REACTION, BORING_LABEL_TOOLTIP, SOLVED_TASK_TOOLTIP, TOO_BORING_REACTION); + myHardPanel = new ReactionButtonPanel(HARD_REACTION, HARD_LABEL_TOOLTIP, TOO_HARD_REACTION); + myBoringPanel = new ReactionButtonPanel(BORING_REACTION, BORING_LABEL_TOOLTIP, TOO_BORING_REACTION); addFileListener(); final GridBagConstraints c = new GridBagConstraints(); @@ -99,7 +99,6 @@ public class StepicAdaptiveReactionsPanel extends JPanel { public ReactionButtonPanel(@NotNull final String text, @NotNull final String enabledTooltip, - @NotNull final String disabledTooltip, int reaction) { com.jetbrains.edu.learning.courseFormat.Task task = StudyUtils.getTaskFromSelectedEditor(myProject); final boolean isEnabled = task != null && task.getStatus() != StudyStatus.Solved; @@ -108,7 +107,7 @@ public class StepicAdaptiveReactionsPanel extends JPanel { myButtonPanel = new JPanel(); myButtonPanel.setLayout(new BoxLayout(myButtonPanel, BoxLayout.PAGE_AXIS)); - myButtonPanel.setToolTipText(isEnabled ? enabledTooltip : disabledTooltip); + myButtonPanel.setToolTipText(isEnabled ? enabledTooltip : SOLVED_TASK_TOOLTIP); myButtonPanel.add(Box.createVerticalStrut(5)); myButtonPanel.add(myLabel); myButtonPanel.add(Box.createVerticalStrut(5)); From 0f0674403184529cbddf39482cc82c63cad64955 Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Mon, 20 Jun 2016 19:51:30 +0300 Subject: [PATCH 043/107] cleanup --- .../CCDeleteAllAnswerPlaceholdersAction.java | 2 +- .../handlers/CCLessonMoveHandlerDelegate.java | 1 - .../handlers/CCTaskMoveHandlerDelegate.java | 5 +++-- .../ui/CCCreateStudyItemPanel.java | 2 +- .../learning/actions/StudyCheckAction.java | 2 +- .../edu/learning/checker/StudyCheckTask.java | 2 +- .../edu/learning/checker/StudyCheckUtils.java | 2 +- .../learning/checker/StudySmartChecker.java | 2 +- .../jetbrains/edu/learning/core/EduNames.java | 6 ++--- .../jetbrains/edu/learning/core/EduUtils.java | 5 ++--- .../edu/learning/courseFormat/Course.java | 2 +- .../courseGeneration/StudyGenerator.java | 16 +++++++------- .../projectView/StudyDirectoryNode.java | 4 ++-- .../learning/settings/StudyConfigurable.java | 7 +----- .../edu/learning/stepic/CourseInfo.java | 2 +- .../edu/learning/stepic/EduStepicNames.java | 2 +- .../edu/learning/stepic/StepicWrappers.java | 22 +++++++------------ .../learning/twitter/StudyTwitterUtils.java | 2 +- .../edu/learning/ui/StudyProgressBar.java | 2 +- .../learning/ui/StudyToolWindowFactory.java | 1 - 20 files changed, 38 insertions(+), 51 deletions(-) diff --git a/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCDeleteAllAnswerPlaceholdersAction.java b/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCDeleteAllAnswerPlaceholdersAction.java index 0916e1b678f4..7c10fba712b4 100644 --- a/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCDeleteAllAnswerPlaceholdersAction.java +++ b/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCDeleteAllAnswerPlaceholdersAction.java @@ -107,7 +107,7 @@ public class CCDeleteAllAnswerPlaceholdersAction extends DumbAwareAction { private static class ClearPlaceholders implements UndoableAction { private final List myPlaceholders; private final Editor myEditor; - TaskFile myTaskFile; + private final TaskFile myTaskFile; public ClearPlaceholders(TaskFile taskFile, List placeholders, Editor editor) { myTaskFile = taskFile; diff --git a/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/handlers/CCLessonMoveHandlerDelegate.java b/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/handlers/CCLessonMoveHandlerDelegate.java index d9d6f5adc3df..15da6057e0c7 100644 --- a/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/handlers/CCLessonMoveHandlerDelegate.java +++ b/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/handlers/CCLessonMoveHandlerDelegate.java @@ -21,7 +21,6 @@ import com.intellij.util.Function; import com.jetbrains.edu.coursecreator.CCUtils; import com.jetbrains.edu.coursecreator.ui.CCMoveStudyItemDialog; import com.jetbrains.edu.learning.StudyTaskManager; -import com.jetbrains.edu.coursecreator.CCUtils; import com.jetbrains.edu.learning.core.EduNames; import com.jetbrains.edu.learning.core.EduUtils; import com.jetbrains.edu.learning.courseFormat.Course; diff --git a/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/handlers/CCTaskMoveHandlerDelegate.java b/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/handlers/CCTaskMoveHandlerDelegate.java index e69a1eeb8523..b37e0093c0b4 100644 --- a/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/handlers/CCTaskMoveHandlerDelegate.java +++ b/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/handlers/CCTaskMoveHandlerDelegate.java @@ -17,7 +17,6 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiReference; import com.intellij.refactoring.move.MoveCallback; import com.intellij.refactoring.move.MoveHandlerDelegate; -import com.intellij.util.Function; import com.jetbrains.edu.coursecreator.CCUtils; import com.jetbrains.edu.coursecreator.ui.CCMoveStudyItemDialog; import com.jetbrains.edu.learning.StudyTaskManager; @@ -25,7 +24,6 @@ import com.jetbrains.edu.learning.core.EduNames; import com.jetbrains.edu.learning.core.EduUtils; import com.jetbrains.edu.learning.courseFormat.Course; import com.jetbrains.edu.learning.courseFormat.Lesson; -import com.jetbrains.edu.learning.courseFormat.StudyItem; import com.jetbrains.edu.learning.courseFormat.Task; import org.jetbrains.annotations.Nullable; @@ -91,6 +89,9 @@ public class CCTaskMoveHandlerDelegate extends MoveHandlerDelegate { final Course course = StudyTaskManager.getInstance(project).getCourse(); final PsiDirectory sourceDirectory = (PsiDirectory)elements[0]; + if (course == null) { + return; + } final Task taskToMove = EduUtils.getTask(sourceDirectory, course); if (taskToMove == null) { return; diff --git a/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/ui/CCCreateStudyItemPanel.java b/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/ui/CCCreateStudyItemPanel.java index fd4854ffb359..572ba0806508 100644 --- a/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/ui/CCCreateStudyItemPanel.java +++ b/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/ui/CCCreateStudyItemPanel.java @@ -8,7 +8,7 @@ public class CCCreateStudyItemPanel extends JPanel { private JPanel myPanel; private JTextField myNameField; private CCItemPositionPanel myPositionalPanel; - private String myThresholdName; + private final String myThresholdName; public CCCreateStudyItemPanel(String itemName, String thresholdName, int thresholdIndex) { myThresholdName = thresholdName; diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/actions/StudyCheckAction.java b/python/educational-core/student/src/com/jetbrains/edu/learning/actions/StudyCheckAction.java index 04d692333e01..39ef983b5800 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/actions/StudyCheckAction.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/actions/StudyCheckAction.java @@ -21,7 +21,7 @@ import javax.swing.*; public abstract class StudyCheckAction extends StudyActionWithShortcut { public static final String SHORTCUT = "ctrl alt pressed ENTER"; - protected Ref myCheckInProgress = new Ref<>(false); + protected final Ref myCheckInProgress = new Ref<>(false); public StudyCheckAction() { super("Check Task (" + KeymapUtil.getShortcutText(new KeyboardShortcut(KeyStroke.getKeyStroke(SHORTCUT), null)) + ")", "Check current task", InteractiveLearningIcons.CheckTask); diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/checker/StudyCheckTask.java b/python/educational-core/student/src/com/jetbrains/edu/learning/checker/StudyCheckTask.java index fd98e1690139..a44a3b34a0b8 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/checker/StudyCheckTask.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/checker/StudyCheckTask.java @@ -36,7 +36,7 @@ public class StudyCheckTask extends com.intellij.openapi.progress.Task.Backgroun protected final VirtualFile myTaskDir; protected final StudyTaskManager myTaskManger; private final StudyStatus myStatusBeforeCheck; - private Ref myCheckInProcess; + private final Ref myCheckInProcess; private final Process myTestProcess; private final String myCommandLine; diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/checker/StudyCheckUtils.java b/python/educational-core/student/src/com/jetbrains/edu/learning/checker/StudyCheckUtils.java index a14e89fa6c73..73812b9be5bc 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/checker/StudyCheckUtils.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/checker/StudyCheckUtils.java @@ -185,7 +185,7 @@ public class StudyCheckUtils { if (virtualFile == null) { continue; } - EduUtils.flushWindows(taskFile, virtualFile, true); + EduUtils.flushWindows(taskFile, virtualFile); } } diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/checker/StudySmartChecker.java b/python/educational-core/student/src/com/jetbrains/edu/learning/checker/StudySmartChecker.java index 9621efbd7d39..e67c2b62b227 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/checker/StudySmartChecker.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/checker/StudySmartChecker.java @@ -62,7 +62,7 @@ public class StudySmartChecker { String text = usersDocument.getText(new TextRange(userStart, userEnd)); windowDocument.replaceString(start, end, text); ApplicationManager.getApplication().runWriteAction(() -> documentManager.saveDocument(windowDocument)); - VirtualFile fileWindows = EduUtils.flushWindows(windowTaskFile, windowCopy, true); + VirtualFile fileWindows = EduUtils.flushWindows(windowTaskFile, windowCopy); Process smartTestProcess = testRunner.createCheckProcess(project, windowCopy.getPath()); final CapturingProcessHandler handler = new CapturingProcessHandler(smartTestProcess, null, windowCopy.getPath()); final ProcessOutput output = handler.runProcess(); diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/core/EduNames.java b/python/educational-core/student/src/com/jetbrains/edu/learning/core/EduNames.java index a9537e24d6c5..cf6d4fd21c2e 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/core/EduNames.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/core/EduNames.java @@ -41,11 +41,11 @@ public class EduNames { public static final String SANDBOX_DIR = "Sandbox"; public static final String COURSE_META_FILE = "course.json"; public static final String STUDY = "Study"; - public static String PYCHARM_ADDITIONAL = "PyCharm additional materials"; + public static final String PYCHARM_ADDITIONAL = "PyCharm additional materials"; public static final String PYCHARM = "PyCharm"; - public static String PLACEHOLDER = "Answer Placeholder"; - public static String SRC = "src"; + public static final String PLACEHOLDER = "Answer Placeholder"; + public static final String SRC = "src"; private EduNames() { } diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/core/EduUtils.java b/python/educational-core/student/src/com/jetbrains/edu/learning/core/EduUtils.java index e6e520fca01c..edad8e41cacd 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/core/EduUtils.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/core/EduUtils.java @@ -31,7 +31,7 @@ public class EduUtils { } private static final Logger LOG = Logger.getInstance(EduUtils.class.getName()); - public static Comparator INDEX_COMPARATOR = (o1, o2) -> o1.getIndex() - o2.getIndex(); + public static final Comparator INDEX_COMPARATOR = (o1, o2) -> o1.getIndex() - o2.getIndex(); public static void enableAction(@NotNull final AnActionEvent event, boolean isEnable) { final Presentation presentation = event.getPresentation(); @@ -64,8 +64,7 @@ public class EduUtils { @SuppressWarnings("IOResourceOpenedButNotSafelyClosed") @Nullable - public static VirtualFile flushWindows(@NotNull final TaskFile taskFile, @NotNull final VirtualFile file, - boolean useLength) { + public static VirtualFile flushWindows(@NotNull final TaskFile taskFile, @NotNull final VirtualFile file) { final VirtualFile taskDir = file.getParent(); VirtualFile fileWindows = null; final Document document = FileDocumentManager.getInstance().getDocument(file); diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/courseFormat/Course.java b/python/educational-core/student/src/com/jetbrains/edu/learning/courseFormat/Course.java index 6b60f47f6faa..a5b88246230c 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/courseFormat/Course.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/courseFormat/Course.java @@ -75,7 +75,7 @@ public class Course { } public static String getAuthorsString(@NotNull List authors) { - return StringUtil.join(authors, author -> author.getName(), ", "); + return StringUtil.join(authors, StepicUser::getName, ", "); } public void setAuthors(String[] authors) { diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/courseGeneration/StudyGenerator.java b/python/educational-core/student/src/com/jetbrains/edu/learning/courseGeneration/StudyGenerator.java index 6e031380977b..58687fc2391e 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/courseGeneration/StudyGenerator.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/courseGeneration/StudyGenerator.java @@ -116,15 +116,15 @@ public class StudyGenerator { baseDir.createChildDirectory(project, EduNames.SANDBOX_DIR); File[] files = resourceRoot.listFiles( (dir, name) -> !name.contains(EduNames.LESSON) && !name.equals(EduNames.COURSE_META_FILE) && !name.equals(EduNames.HINTS)); - for (File file : files) { - File dir = new File(baseDir.getPath(), file.getName()); - if (file.isDirectory()) { - FileUtil.copyDir(file, dir); - continue; + if (files != null) { + for (File file : files) { + File dir = new File(baseDir.getPath(), file.getName()); + if (file.isDirectory()) { + FileUtil.copyDir(file, dir); + continue; + } + FileUtil.copy(file, dir); } - - FileUtil.copy(file, dir); - } } catch (IOException e) { diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/projectView/StudyDirectoryNode.java b/python/educational-core/student/src/com/jetbrains/edu/learning/projectView/StudyDirectoryNode.java index c9821a704112..5439bce17d2e 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/projectView/StudyDirectoryNode.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/projectView/StudyDirectoryNode.java @@ -142,7 +142,7 @@ public class StudyDirectoryNode extends PsiDirectoryNode { @Override public void navigate(boolean requestFocus) { final String myValueName = myValue.getName(); - if (myValueName != null && myValueName.contains(EduNames.TASK)) { + if (myValueName.contains(EduNames.TASK)) { TaskFile taskFile = null; VirtualFile virtualFile = null; for (PsiElement child : myValue.getChildren()) { @@ -186,7 +186,7 @@ public class StudyDirectoryNode extends PsiDirectoryNode { @Override public boolean expandOnDoubleClick() { final String myValueName = myValue.getName(); - if (myValueName!= null && myValueName.contains(EduNames.TASK)) { + if (myValueName.contains(EduNames.TASK)) { return false; } return super.expandOnDoubleClick(); diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/settings/StudyConfigurable.java b/python/educational-core/student/src/com/jetbrains/edu/learning/settings/StudyConfigurable.java index ba47bee2c62a..7b45780e26f8 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/settings/StudyConfigurable.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/settings/StudyConfigurable.java @@ -27,7 +27,7 @@ import java.util.List; public class StudyConfigurable extends CompositeConfigurable { public static final String ID = "com.jetbrains.edu.learning.stepic.EduConfigurable"; - private JPanel myMainPanel; + private final JPanel myMainPanel; public StudyConfigurable() { myMainPanel = new JPanel(new VerticalFlowLayout()); @@ -59,11 +59,6 @@ public class StudyConfigurable extends CompositeConfigurable createConfigurables() { return ConfigurableWrapper.createConfigurables(StudyOptionsProviderEP.EP_NAME); diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/CourseInfo.java b/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/CourseInfo.java index 004b313054a1..b29140ba494c 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/CourseInfo.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/CourseInfo.java @@ -12,7 +12,7 @@ import java.util.List; * and when project is being created */ public class CourseInfo { - public static CourseInfo INVALID_COURSE = new CourseInfo(); + public static final CourseInfo INVALID_COURSE = new CourseInfo(); @SerializedName("title") private String myName; int id; diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/EduStepicNames.java b/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/EduStepicNames.java index 5ece7fe02284..7710f5e392c5 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/EduStepicNames.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/EduStepicNames.java @@ -22,5 +22,5 @@ public class EduStepicNames { public static final String STEPS = "/steps"; public static final String SECTIONS = "/sections/"; public static final String ENROLLMENTS = "/enrollments"; - public static String STEPIC_SIGN_IN_LINK = "https://stepic.org/accounts/signup/?next=/users/16516293/learn"; + public static final String STEPIC_SIGN_IN_LINK = "https://stepic.org/accounts/signup/?next=/users/16516293/learn"; } diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/StepicWrappers.java b/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/StepicWrappers.java index 83363d59b082..c5820eaf95cf 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/StepicWrappers.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/StepicWrappers.java @@ -61,15 +61,12 @@ public class StepicWrappers { for (final Map.Entry entry : task.getTaskFiles().entrySet()) { final TaskFile taskFile = new TaskFile(); TaskFile.copy(entry.getValue(), taskFile); - ApplicationManager.getApplication().runWriteAction(new Runnable() { - @Override - public void run() { - final VirtualFile taskDir = task.getTaskDir(project); - assert taskDir != null; - VirtualFile ideaDir = project.getBaseDir().findChild(".idea"); - assert ideaDir != null; - EduUtils.createStudentFileFromAnswer(project, ideaDir, taskDir, entry.getKey(), taskFile); - } + ApplicationManager.getApplication().runWriteAction(() -> { + final VirtualFile taskDir = task.getTaskDir(project); + assert taskDir != null; + VirtualFile ideaDir = project.getBaseDir().findChild(".idea"); + assert ideaDir != null; + EduUtils.createStudentFileFromAnswer(project, ideaDir, taskDir, entry.getKey(), taskFile); }); taskFile.name = entry.getKey(); @@ -98,11 +95,8 @@ public class StepicWrappers { private static void setTests(@NotNull final Task task, @NotNull final StepOptions source, @NotNull final Project project) { final Map testsText = task.getTestsText(); if (testsText.isEmpty()) { - ApplicationManager.getApplication().runReadAction(new Runnable() { - @Override - public void run() { - source.test = Collections.singletonList(new TestFileWrapper(EduNames.TESTS_FILE, task.getTestsText(project))); - } + ApplicationManager.getApplication().runReadAction(() -> { + source.test = Collections.singletonList(new TestFileWrapper(EduNames.TESTS_FILE, task.getTestsText(project))); }); } else { diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/twitter/StudyTwitterUtils.java b/python/educational-core/student/src/com/jetbrains/edu/learning/twitter/StudyTwitterUtils.java index 1192e7bea612..8c6d8668066d 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/twitter/StudyTwitterUtils.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/twitter/StudyTwitterUtils.java @@ -242,7 +242,7 @@ public class StudyTwitterUtils { * Dialog wrapper class with DoNotAsl option for asking user to tweet. * */ private static class TwitterDialogWrapper extends DialogWrapper { - private StudyTwitterUtils.TwitterDialogPanel myPanel; + private final StudyTwitterUtils.TwitterDialogPanel myPanel; TwitterDialogWrapper(@Nullable Project project, @NotNull StudyTwitterUtils.TwitterDialogPanel panel, DoNotAskOption doNotAskOption) { super(project); diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/ui/StudyProgressBar.java b/python/educational-core/student/src/com/jetbrains/edu/learning/ui/StudyProgressBar.java index c21aef13acb7..601bd127e56f 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/ui/StudyProgressBar.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/ui/StudyProgressBar.java @@ -20,7 +20,7 @@ public class StudyProgressBar extends JComponent implements DumbAware { private final int myHeight; private final int myIndent; private double myFraction = 0.0; - private static Color myColor = JBColor.GREEN; + private static final Color myColor = JBColor.GREEN; public StudyProgressBar(double fraction, int height, int indent) { myFraction = fraction; diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/ui/StudyToolWindowFactory.java b/python/educational-core/student/src/com/jetbrains/edu/learning/ui/StudyToolWindowFactory.java index 4530e004504d..2cbb4cff7f99 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/ui/StudyToolWindowFactory.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/ui/StudyToolWindowFactory.java @@ -7,7 +7,6 @@ import com.intellij.openapi.wm.ToolWindow; import com.intellij.openapi.wm.ToolWindowFactory; import com.intellij.ui.content.Content; import com.intellij.ui.content.ContentManager; -import com.jetbrains.edu.learning.StudyProjectComponent; import com.jetbrains.edu.learning.StudyTaskManager; import com.jetbrains.edu.learning.StudyUtils; import com.jetbrains.edu.learning.courseFormat.Course; From 00fe1741a5ab32aee8ad858377126aaf8c7bec8b Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Mon, 20 Jun 2016 19:54:50 +0300 Subject: [PATCH 044/107] fixed Python Introduction course generation --- .../jetbrains/edu/learning/PyStudyDirectoryProjectGenerator.java | 1 + 1 file changed, 1 insertion(+) diff --git a/python/educational-python/student-python/src/com/jetbrains/edu/learning/PyStudyDirectoryProjectGenerator.java b/python/educational-python/student-python/src/com/jetbrains/edu/learning/PyStudyDirectoryProjectGenerator.java index 20d11cb4bc97..1e63ad532000 100644 --- a/python/educational-python/student-python/src/com/jetbrains/edu/learning/PyStudyDirectoryProjectGenerator.java +++ b/python/educational-python/student-python/src/com/jetbrains/edu/learning/PyStudyDirectoryProjectGenerator.java @@ -165,6 +165,7 @@ public class PyStudyDirectoryProjectGenerator extends PythonProjectGenerator imp return generator -> { final List enrolledCoursesIds = myGenerator.getEnrolledCoursesIds(); final CourseInfo course = (CourseInfo)mySettingsPanel.getCoursesComboBox().getSelectedItem(); + if (course == null) return true; if (course.isAdaptive() && !enrolledCoursesIds.contains(course.getId())) { ProgressManager.getInstance().runProcessWithProgressSynchronously(() -> { ProgressManager.getInstance().getProgressIndicator().setIndeterminate(true); From 6c33b7adbb5231cd3ab1694eaebe6569e45bcb04 Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Mon, 20 Jun 2016 19:58:49 +0300 Subject: [PATCH 045/107] do not try to post attempt to stepic if case user not logged in --- .../com/jetbrains/edu/learning/checker/StudyCheckTask.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/checker/StudyCheckTask.java b/python/educational-core/student/src/com/jetbrains/edu/learning/checker/StudyCheckTask.java index a44a3b34a0b8..e032ac0a1bd3 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/checker/StudyCheckTask.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/checker/StudyCheckTask.java @@ -24,6 +24,7 @@ import com.jetbrains.edu.learning.courseFormat.StudyStatus; import com.jetbrains.edu.learning.courseFormat.Task; import com.jetbrains.edu.learning.stepic.EduAdaptiveStepicConnector; import com.jetbrains.edu.learning.stepic.EduStepicConnector; +import com.jetbrains.edu.learning.stepic.StepicUser; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -214,8 +215,10 @@ public class StudyCheckTask extends com.intellij.openapi.progress.Task.Backgroun protected void postAttemptToStepic(@NotNull StudyTestsOutputParser.TestsOutput testsOutput) { final StudyTaskManager studySettings = StudyTaskManager.getInstance(myProject); - final String login = studySettings.getUser().getEmail(); - final String password = StringUtil.isEmptyOrSpaces(login) ? "" : studySettings.getUser().getPassword(); + final StepicUser user = studySettings.getUser(); + if (user == null) return; + final String login = user.getEmail(); + final String password = StringUtil.isEmptyOrSpaces(login) ? "" : user.getPassword(); EduStepicConnector.postAttempt(myTask, testsOutput.isSuccess(), login, password); } } From 7f0c2527e744f099b679dfe31a7aba71d9d4ae75 Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Mon, 20 Jun 2016 20:06:21 +0300 Subject: [PATCH 046/107] extracted field --- .../com/jetbrains/edu/learning/checker/StudyCheckTask.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/checker/StudyCheckTask.java b/python/educational-core/student/src/com/jetbrains/edu/learning/checker/StudyCheckTask.java index e032ac0a1bd3..0a9d5ca85394 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/checker/StudyCheckTask.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/checker/StudyCheckTask.java @@ -40,6 +40,7 @@ public class StudyCheckTask extends com.intellij.openapi.progress.Task.Backgroun private final Ref myCheckInProcess; private final Process myTestProcess; private final String myCommandLine; + private final String FAILED_CHECK_LAUNCH = "Failed to launch checking"; public StudyCheckTask(Project project, StudyState studyState, Ref checkInProcess, Process testProcess, String commandLine) { super(project, "Checking Task"); @@ -119,7 +120,7 @@ public class StudyCheckTask extends com.intellij.openapi.progress.Task.Backgroun String stderr = output.getStderr(); if (!stderr.isEmpty()) { ApplicationManager.getApplication().invokeLater(() -> - StudyCheckUtils.showTestResultPopUp("Failed to launch checking", + StudyCheckUtils.showTestResultPopUp(FAILED_CHECK_LAUNCH, MessageType.WARNING.getPopupBackground(), myProject)); //log error output of tests @@ -150,7 +151,7 @@ public class StudyCheckTask extends com.intellij.openapi.progress.Task.Backgroun runAfterTaskCheckedActions(); } else { - ApplicationManager.getApplication().invokeLater(() -> StudyCheckUtils.showTestResultPopUp("Failed to launch checking", + ApplicationManager.getApplication().invokeLater(() -> StudyCheckUtils.showTestResultPopUp(FAILED_CHECK_LAUNCH, MessageType.WARNING .getPopupBackground(), myProject)); From 5553e9a6f30dde77dfd2c91ad2e3cf027039149b Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Mon, 20 Jun 2016 20:19:52 +0300 Subject: [PATCH 047/107] NPE --- .../jetbrains/edu/learning/stepic/StepicStudyOptions.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/StepicStudyOptions.java b/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/StepicStudyOptions.java index ae823206ddf4..9b48578db82a 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/StepicStudyOptions.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/stepic/StepicStudyOptions.java @@ -108,9 +108,10 @@ public class StepicStudyOptions implements StudyOptionsProvider { Project project = StudyUtils.getStudyProject(); if (project != null) { final StepicUser user = StudyTaskManager.getInstance(project).getUser(); - setLogin(user.getEmail()); - setPassword(DEFAULT_PASSWORD_TEXT); - + if (user != null) { + setLogin(user.getEmail()); + setPassword(DEFAULT_PASSWORD_TEXT); + } resetCredentialsModification(); } else { From 5374b90da3ec2922c9e4df89a59da01a0756b1fb Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Thu, 23 Jun 2016 17:34:03 +0300 Subject: [PATCH 048/107] copy initial state for answer placeholders --- .../src/com/jetbrains/edu/learning/courseFormat/TaskFile.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/courseFormat/TaskFile.java b/python/educational-core/student/src/com/jetbrains/edu/learning/courseFormat/TaskFile.java index 88037f08679c..1223f43f3d10 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/courseFormat/TaskFile.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/courseFormat/TaskFile.java @@ -98,6 +98,8 @@ public class TaskFile { answerPlaceholderCopy.setPossibleAnswer(answerPlaceholder.getPossibleAnswer()); answerPlaceholderCopy.setIndex(answerPlaceholder.getIndex()); answerPlaceholderCopy.setHint(answerPlaceholder.getHint()); + final AnswerPlaceholder.MyInitialState state = answerPlaceholder.getInitialState(); + answerPlaceholderCopy.setInitialState(new AnswerPlaceholder.MyInitialState(state.getOffset(), state.getLength())); answerPlaceholdersCopy.add(answerPlaceholderCopy); } target.name = source.name; From cdf8f4b617af43ac405b49977a86580de89114ac Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Fri, 24 Jun 2016 11:53:34 +0300 Subject: [PATCH 049/107] moved course progress to the description toolwindow --- .../student/resources/META-INF/plugin.xml | 1 - .../edu/learning/StudyProjectComponent.java | 15 +--- .../jetbrains/edu/learning/StudyUtils.java | 38 +++------ .../edu/learning/ui/StudyProgressBar.java | 4 + .../ui/StudyProgressToolWindowFactory.java | 80 ------------------- .../edu/learning/ui/StudyToolWindow.java | 58 +++++++++++++- .../learning/PyStudyInstructionPainter.java | 2 - 7 files changed, 72 insertions(+), 126 deletions(-) delete mode 100644 python/educational-core/student/src/com/jetbrains/edu/learning/ui/StudyProgressToolWindowFactory.java diff --git a/python/educational-core/student/resources/META-INF/plugin.xml b/python/educational-core/student/resources/META-INF/plugin.xml index d950bc814f9b..aafd06787e4e 100644 --- a/python/educational-core/student/resources/META-INF/plugin.xml +++ b/python/educational-core/student/resources/META-INF/plugin.xml @@ -89,7 +89,6 @@ displayName="Education"/> - diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/StudyProjectComponent.java b/python/educational-core/student/src/com/jetbrains/edu/learning/StudyProjectComponent.java index 44cf72f11f58..cfb8faa2bbb0 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/StudyProjectComponent.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/StudyProjectComponent.java @@ -25,15 +25,14 @@ import com.intellij.openapi.wm.ToolWindow; import com.intellij.openapi.wm.ToolWindowAnchor; import com.intellij.openapi.wm.ToolWindowManager; import com.intellij.util.containers.hash.HashMap; +import com.jetbrains.edu.learning.actions.StudyActionWithShortcut; import com.jetbrains.edu.learning.core.EduNames; import com.jetbrains.edu.learning.core.EduUtils; import com.jetbrains.edu.learning.courseFormat.Course; import com.jetbrains.edu.learning.courseFormat.Lesson; import com.jetbrains.edu.learning.courseFormat.Task; import com.jetbrains.edu.learning.courseFormat.TaskFile; -import com.jetbrains.edu.learning.actions.*; import com.jetbrains.edu.learning.editor.StudyEditorFactoryListener; -import com.jetbrains.edu.learning.ui.StudyProgressToolWindowFactory; import com.jetbrains.edu.learning.ui.StudyToolWindow; import com.jetbrains.edu.learning.ui.StudyToolWindowFactory; import javafx.application.Platform; @@ -93,13 +92,9 @@ public class StudyProjectComponent implements ProjectComponent { final ToolWindowManager toolWindowManager = ToolWindowManager.getInstance(myProject); registerToolWindows(toolWindowManager); final ToolWindow studyToolWindow = toolWindowManager.getToolWindow(StudyToolWindowFactory.STUDY_TOOL_WINDOW); - final ToolWindow progressToolWindow = toolWindowManager.getToolWindow(StudyProgressToolWindowFactory.ID); if (studyToolWindow != null) { studyToolWindow.show(null); - } - if (progressToolWindow != null) { StudyUtils.initToolWindows(myProject); - progressToolWindow.show(null); } } } @@ -130,10 +125,6 @@ public class StudyProjectComponent implements ProjectComponent { if (toolWindow == null) { toolWindowManager.registerToolWindow(StudyToolWindowFactory.STUDY_TOOL_WINDOW, true, ToolWindowAnchor.RIGHT, myProject, true); } - ToolWindow progressToolWindow = toolWindowManager.getToolWindow(StudyProgressToolWindowFactory.ID); - if (progressToolWindow == null) { - toolWindowManager.registerToolWindow(StudyProgressToolWindowFactory.ID, true, ToolWindowAnchor.LEFT, myProject, true, true); - } } private void updateCourse() { @@ -221,10 +212,6 @@ public class StudyProjectComponent implements ProjectComponent { if (toolWindow != null) { toolWindow.getContentManager().removeAllContents(false); } - final ToolWindow progressToolWindow = ToolWindowManager.getInstance(myProject).getToolWindow(StudyProgressToolWindowFactory.ID); - if (progressToolWindow != null) { - progressToolWindow.getContentManager().removeAllContents(false); - } KeymapManagerEx keymapManager = KeymapManagerEx.getInstanceEx(); for (Keymap keymap : keymapManager.getAllKeymaps()) { List> pairs = myDeletedShortcuts.get(keymap); diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/StudyUtils.java b/python/educational-core/student/src/com/jetbrains/edu/learning/StudyUtils.java index b85cad3d58bf..69542b448629 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/StudyUtils.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/StudyUtils.java @@ -42,8 +42,8 @@ import com.intellij.psi.PsiFile; import com.intellij.ui.JBColor; import com.intellij.ui.awt.RelativePoint; import com.intellij.ui.content.Content; -import com.intellij.util.TimeoutUtil; import com.intellij.util.ObjectUtils; +import com.intellij.util.TimeoutUtil; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.text.MarkdownUtil; import com.intellij.util.ui.UIUtil; @@ -56,7 +56,6 @@ import com.jetbrains.edu.learning.core.EduUtils; import com.jetbrains.edu.learning.courseFormat.*; import com.jetbrains.edu.learning.courseGeneration.StudyProjectGenerator; import com.jetbrains.edu.learning.editor.StudyEditor; -import com.jetbrains.edu.learning.ui.StudyProgressToolWindowFactory; import com.jetbrains.edu.learning.ui.StudyToolWindow; import com.jetbrains.edu.learning.ui.StudyToolWindowFactory; import com.petebevin.markdown.MarkdownProcessor; @@ -165,10 +164,17 @@ public class StudyUtils { } public static void updateToolWindows(@NotNull final Project project) { - updateStudyToolWindow(project); - - final ToolWindowManager windowManager = ToolWindowManager.getInstance(project); - createProgressToolWindowContent(project, windowManager); + final StudyToolWindow studyToolWindow = getStudyToolWindow(project); + if (studyToolWindow != null) { + String taskText = getTaskText(project); + if (taskText != null) { + studyToolWindow.setTaskText(taskText, null, project); + } + else { + LOG.warn("Task text is null"); + } + studyToolWindow.updateCourseProgress(project); + } } public static void initToolWindows(@NotNull final Project project) { @@ -177,15 +183,8 @@ public class StudyUtils { StudyToolWindowFactory factory = new StudyToolWindowFactory(); factory.createToolWindowContent(project, windowManager.getToolWindow(StudyToolWindowFactory.STUDY_TOOL_WINDOW)); - createProgressToolWindowContent(project, windowManager); } - private static void createProgressToolWindowContent(@NotNull Project project, ToolWindowManager windowManager) { - windowManager.getToolWindow(StudyProgressToolWindowFactory.ID).getContentManager().removeAllContents(false); - StudyProgressToolWindowFactory windowFactory = new StudyProgressToolWindowFactory(); - windowFactory.createToolWindowContent(project, windowManager.getToolWindow(StudyProgressToolWindowFactory.ID)); - } - @Nullable public static StudyToolWindow getStudyToolWindow(@NotNull final Project project) { ToolWindow toolWindow = ToolWindowManager.getInstance(project).getToolWindow(StudyToolWindowFactory.STUDY_TOOL_WINDOW); @@ -558,19 +557,6 @@ public class StudyUtils { return taskFile != null ? taskFile.getTask() : null; } - public static void updateStudyToolWindow(Project project) { - final StudyToolWindow studyToolWindow = getStudyToolWindow(project); - if (studyToolWindow != null) { - String taskText = getTaskText(project); - if (taskText != null) { - studyToolWindow.setTaskText(taskText, null, project); - } - else { - LOG.warn("Task text is null"); - } - } - } - public static boolean isStudyProject(@NotNull Project project) { return StudyTaskManager.getInstance(project).getCourse() != null; } diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/ui/StudyProgressBar.java b/python/educational-core/student/src/com/jetbrains/edu/learning/ui/StudyProgressBar.java index 601bd127e56f..6effcc2df65c 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/ui/StudyProgressBar.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/ui/StudyProgressBar.java @@ -100,4 +100,8 @@ public class StudyProgressBar extends JComponent implements DumbAware { dimension.height = myHeight + 10; return dimension; } + + public void setFraction(double fraction) { + myFraction = fraction; + } } diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/ui/StudyProgressToolWindowFactory.java b/python/educational-core/student/src/com/jetbrains/edu/learning/ui/StudyProgressToolWindowFactory.java deleted file mode 100644 index d57ad24c70f8..000000000000 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/ui/StudyProgressToolWindowFactory.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.jetbrains.edu.learning.ui; - -import com.intellij.openapi.project.DumbAware; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.wm.ToolWindow; -import com.intellij.openapi.wm.ToolWindowFactory; -import com.intellij.ui.content.Content; -import com.intellij.ui.content.ContentFactory; -import com.intellij.util.ui.UIUtil; -import com.jetbrains.edu.learning.core.EduNames; -import com.jetbrains.edu.learning.courseFormat.Course; -import com.jetbrains.edu.learning.courseFormat.Lesson; -import com.jetbrains.edu.learning.courseFormat.StudyStatus; -import com.jetbrains.edu.learning.courseFormat.Task; -import com.jetbrains.edu.learning.StudyTaskManager; -import icons.InteractiveLearningIcons; -import org.jetbrains.annotations.NotNull; - -import javax.swing.*; -import java.awt.*; -import java.util.List; - -public class StudyProgressToolWindowFactory implements ToolWindowFactory, DumbAware { - public static final String ID = "Course Progress"; - - - @Override - public void createToolWindowContent(@NotNull final Project project, @NotNull final ToolWindow toolWindow) { - toolWindow.setIcon(InteractiveLearningIcons.CourseProgress); - JPanel contentPanel = new JPanel(); - StudyTaskManager taskManager = StudyTaskManager.getInstance(project); - if (taskManager.getCourse() != null) { - contentPanel.setLayout(new BoxLayout(contentPanel, BoxLayout.PAGE_AXIS)); - contentPanel.add(Box.createRigidArea(new Dimension(10, 0))); - - Course course = taskManager.getCourse(); - if (course == null) { - return; - } - int taskNum = 0; - int taskSolved = 0; - List lessons = course.getLessons(); - for (Lesson lesson : lessons) { - if (lesson.getName().equals(EduNames.PYCHARM_ADDITIONAL)) continue; - taskNum += lesson.getTaskList().size(); - taskSolved += getSolvedTasks(lesson); - } - String completedTasks = String.format("%d of %d tasks completed", taskSolved, taskNum); - - double percent = (taskSolved * 100.0) / taskNum; - contentPanel.add(Box.createRigidArea(new Dimension(0, 10))); - StudyProgressBar studyProgressBar = new StudyProgressBar(percent / 100, 40, 10); - contentPanel.add(studyProgressBar); - contentPanel.add(Box.createRigidArea(new Dimension(0, 10))); - addStatistics(completedTasks, contentPanel); - contentPanel.setPreferredSize(new Dimension(100, 50)); - ContentFactory contentFactory = ContentFactory.SERVICE.getInstance(); - Content content = contentFactory.createContent(contentPanel, "", false); - contentPanel.setMinimumSize(new Dimension(300, 100)); - toolWindow.getContentManager().addContent(content); - } - } - - private static void addStatistics(String statistics, JPanel contentPanel) { - String labelText = UIUtil.toHtml(statistics, 5); - contentPanel.add(Box.createRigidArea(new Dimension(0, 10))); - JLabel statisticLabel = new JLabel(labelText); - contentPanel.add(statisticLabel); - } - - private static int getSolvedTasks(@NotNull final Lesson lesson) { - int solved = 0; - for (Task task : lesson.getTaskList()) { - if (task.getStatus() == StudyStatus.Solved) { - solved += 1; - } - } - return solved; - } -} diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/ui/StudyToolWindow.java b/python/educational-core/student/src/com/jetbrains/edu/learning/ui/StudyToolWindow.java index d47ef138d308..85f1511f9bf8 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/ui/StudyToolWindow.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/ui/StudyToolWindow.java @@ -30,16 +30,18 @@ import com.intellij.openapi.ui.SimpleToolWindowPanel; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.JBCardLayout; +import com.intellij.ui.JBColor; import com.intellij.ui.OnePixelSplitter; import com.intellij.util.ui.JBUI; import com.jetbrains.edu.learning.*; -import com.jetbrains.edu.learning.courseFormat.Course; -import com.jetbrains.edu.learning.courseFormat.TaskFile; +import com.jetbrains.edu.learning.core.EduNames; +import com.jetbrains.edu.learning.courseFormat.*; import com.jetbrains.edu.learning.stepic.StepicAdaptiveReactionsPanel; import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.awt.*; +import java.util.List; import java.util.Map; public abstract class StudyToolWindow extends SimpleToolWindowPanel implements DataProvider, Disposable { @@ -50,6 +52,8 @@ public abstract class StudyToolWindow extends SimpleToolWindowPanel implements D private final JBCardLayout myCardLayout; private final JPanel myContentPanel; private final OnePixelSplitter mySplitPane; + private JLabel myStatisticLabel; + private StudyProgressBar myStudyProgressBar; public StudyToolWindow() { super(true, true); @@ -72,6 +76,7 @@ public abstract class StudyToolWindow extends SimpleToolWindowPanel implements D } JComponent taskInfoPanel = createTaskInfoPanel(project); panel.add(taskInfoPanel, BorderLayout.CENTER); + panel.add(createCourseProgress(project), BorderLayout.SOUTH); myContentPanel.add(TASK_INFO_ID, panel); mySplitPane.setFirstComponent(myContentPanel); addAdditionalPanels(project); @@ -231,6 +236,53 @@ public abstract class StudyToolWindow extends SimpleToolWindowPanel implements D WebBrowserManager.getInstance().setShowBrowserHover(true); mySplitPane.setFirstComponent(myContentPanel); StudyTaskManager.getInstance(project).setToolWindowMode(StudyToolWindowMode.TEXT); - StudyUtils.updateStudyToolWindow(project); + StudyUtils.updateToolWindows(project); + } + + private JPanel createCourseProgress(@NotNull final Project project) { + JPanel contentPanel = new JPanel(); + contentPanel.setBackground(JBColor.WHITE); + contentPanel.setLayout(new BoxLayout(contentPanel, BoxLayout.PAGE_AXIS)); + contentPanel.add(Box.createRigidArea(new Dimension(10, 0))); + contentPanel.add(Box.createRigidArea(new Dimension(0, 10))); + myStudyProgressBar = new StudyProgressBar(0, 20, 10); + + myStatisticLabel = new JLabel("", SwingConstants.LEFT); + contentPanel.add(myStatisticLabel); + contentPanel.add(myStudyProgressBar); + + contentPanel.setPreferredSize(new Dimension(100, 60)); + contentPanel.setMinimumSize(new Dimension(300, 40)); + updateCourseProgress(project); + return contentPanel; + } + + public void updateCourseProgress(@NotNull final Project project) { + final Course course = StudyTaskManager.getInstance(project).getCourse(); + if (course != null) { + int taskNum = 0; + int taskSolved = 0; + List lessons = course.getLessons(); + for (Lesson lesson : lessons) { + if (lesson.getName().equals(EduNames.PYCHARM_ADDITIONAL)) continue; + taskNum += lesson.getTaskList().size(); + taskSolved += getSolvedTasks(lesson); + } + String completedTasks = String.format("%d of %d tasks completed", taskSolved, taskNum); + double percent = (taskSolved * 100.0) / taskNum; + + myStatisticLabel.setText(completedTasks); + myStudyProgressBar.setFraction(percent / 100); + } + } + + private static int getSolvedTasks(@NotNull final Lesson lesson) { + int solved = 0; + for (Task task : lesson.getTaskList()) { + if (task.getStatus() == StudyStatus.Solved) { + solved += 1; + } + } + return solved; } } diff --git a/python/educational-python/student-python/src/com/jetbrains/edu/learning/PyStudyInstructionPainter.java b/python/educational-python/student-python/src/com/jetbrains/edu/learning/PyStudyInstructionPainter.java index c8dc443d26f6..0496db550dbb 100644 --- a/python/educational-python/student-python/src/com/jetbrains/edu/learning/PyStudyInstructionPainter.java +++ b/python/educational-python/student-python/src/com/jetbrains/edu/learning/PyStudyInstructionPainter.java @@ -5,7 +5,6 @@ import com.intellij.openapi.fileEditor.impl.EditorEmptyTextPainter; import com.intellij.openapi.keymap.KeymapUtil; import com.intellij.util.ui.UIUtil; import com.jetbrains.edu.learning.actions.*; -import com.jetbrains.edu.learning.ui.StudyProgressToolWindowFactory; import org.jetbrains.annotations.NotNull; import javax.swing.*; @@ -23,6 +22,5 @@ public class PyStudyInstructionPainter extends EditorEmptyTextPainter { appendAction(painter, "Reset current task file", getActionShortcutText(StudyRefreshTaskFileAction.ACTION_ID)); appendAction(painter, "Check task", getActionShortcutText(PyStudyCheckAction.ACTION_ID)); appendAction(painter, "Get hint for the answer placeholder", getActionShortcutText(StudyShowHintAction.ACTION_ID)); - appendLine(painter, "To see your progress open the '" + StudyProgressToolWindowFactory.ID + "' panel"); } } \ No newline at end of file From 8f0c8541fb82729fa4e4243d3d64992aadf05241 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 24 Jun 2016 10:54:55 +0300 Subject: [PATCH 050/107] delegate params: hide copy javadoc option to prevent confusion (IDEA-148667) --- .../daemon/impl/quickfix/DefineParamsDefaultValueAction.java | 1 + 1 file changed, 1 insertion(+) diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DefineParamsDefaultValueAction.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DefineParamsDefaultValueAction.java index 7440f6feb0e8..e92273709657 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DefineParamsDefaultValueAction.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DefineParamsDefaultValueAction.java @@ -70,6 +70,7 @@ public class DefineParamsDefaultValueAction extends DelegateWithDefaultParamValu new MemberChooser(members, false, true, element.getProject()); chooser.selectElements(members); chooser.setTitle("Choose Default Value Parameters"); + chooser.setCopyJavadocVisible(false); if (chooser.showAndGet()) { final List elements = chooser.getSelectedElements(); if (elements != null) { From 923b6cf2528db8bcaca355653b6f65b1ca729f98 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 24 Jun 2016 11:43:00 +0300 Subject: [PATCH 051/107] delegate params: compound 2 intentions in one, set preselection (IDEA-112043) --- .../DefineParamsDefaultValueAction.java | 165 ++++++++++++++- ...eWithDefaultParamValueIntentionAction.java | 191 ------------------ .../delegateWithDefaultValue/after1.java | 2 +- .../afterAbstractMethod.java | 2 +- .../afterCommentsInBody.java | 2 +- .../afterConstructor.java | 2 +- .../afterExistinMethod.java | 6 + .../afterInterface.java | 2 +- .../afterJavadoc.java | 2 +- .../afterReturnValue.java | 2 +- .../afterStaticMethodInInterface.java | 2 +- .../afterTypeParams.java | 2 +- .../afterVarargs.java | 2 +- .../delegateWithDefaultValue/before1.java | 2 +- .../beforeAbstractMethod.java | 2 +- .../beforeCommentsInBody.java | 2 +- .../beforeConstructor.java | 2 +- .../beforeExistinMethod.java | 2 +- .../beforeInterface.java | 2 +- .../beforeJavadoc.java | 2 +- .../beforeReturnValue.java | 2 +- .../beforeStaticMethodInInterface.java | 2 +- .../beforeTypeParams.java | 2 +- .../beforeVarargs.java | 2 +- .../DelegateWithDefaultParamValueTest.java | 5 +- .../after.java.template | 9 - .../before.java.template | 5 - .../description.html | 5 - resources/src/META-INF/IdeaPlugin.xml | 4 - 29 files changed, 184 insertions(+), 248 deletions(-) delete mode 100644 java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DelegateWithDefaultParamValueIntentionAction.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/afterExistinMethod.java delete mode 100644 resources-en/src/intentionDescriptions/DelegateWithDefaultParamValueIntentionAction/after.java.template delete mode 100644 resources-en/src/intentionDescriptions/DelegateWithDefaultParamValueIntentionAction/before.java.template delete mode 100644 resources-en/src/intentionDescriptions/DelegateWithDefaultParamValueIntentionAction/description.html diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DefineParamsDefaultValueAction.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DefineParamsDefaultValueAction.java index e92273709657..8374967361d3 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DefineParamsDefaultValueAction.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DefineParamsDefaultValueAction.java @@ -15,24 +15,62 @@ */ package com.intellij.codeInsight.daemon.impl.quickfix; +import com.intellij.codeInsight.FileModificationService; +import com.intellij.codeInsight.generation.ClassMember; +import com.intellij.codeInsight.hint.HintManager; +import com.intellij.codeInsight.intention.LowPriorityAction; +import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction; import com.intellij.codeInsight.intention.impl.ParameterClassMember; +import com.intellij.codeInsight.template.Template; +import com.intellij.codeInsight.template.TemplateBuilderImpl; +import com.intellij.codeInsight.template.impl.TextExpression; +import com.intellij.icons.AllIcons; import com.intellij.ide.util.MemberChooser; import com.intellij.lang.java.JavaLanguage; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.RangeMarker; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Iconable; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; +import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; +import com.intellij.refactoring.util.RefactoringUtil; +import com.intellij.util.ArrayUtil; +import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import javax.swing.*; +import java.util.Arrays; +import java.util.HashSet; import java.util.List; /** * User: anna * Date: 8/2/12 */ -public class DefineParamsDefaultValueAction extends DelegateWithDefaultParamValueIntentionAction { +public class DefineParamsDefaultValueAction extends PsiElementBaseIntentionAction implements Iconable, LowPriorityAction { + private static final Logger LOG = Logger.getInstance(DefineParamsDefaultValueAction.class); + + @Override + public boolean startInWriteAction() { + return false; + } + + @NotNull + @Override + public String getFamilyName() { + return "Generate overloaded method with default parameter values"; + } + + @Override + public Icon getIcon(int flags) { + return AllIcons.Actions.RefactoringBulb; + } @Override public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element) { @@ -56,19 +94,104 @@ public class DefineParamsDefaultValueAction extends DelegateWithDefaultParamValu return true; } - @Nullable @Override + public void invoke(@NotNull final Project project, final Editor editor, @NotNull PsiElement element) throws IncorrectOperationException { + final PsiParameter[] parameters = getParams(element); + if (parameters == null || parameters.length == 0) return; + final PsiMethod method = (PsiMethod)parameters[0].getDeclarationScope(); + final PsiMethod methodPrototype = generateMethodPrototype(method, parameters); + final PsiClass containingClass = method.getContainingClass(); + if (containingClass == null) return; + final PsiMethod existingMethod = containingClass.findMethodBySignature(methodPrototype, false); + if (existingMethod != null) { + editor.getCaretModel().moveToOffset(existingMethod.getTextOffset()); + HintManager.getInstance().showErrorHint(editor, (existingMethod.isConstructor() ? "Constructor" : "Method") + + " with the chosen signature already exists"); + return; + } + + if (!FileModificationService.getInstance().preparePsiElementForWrite(element)) return; + + Runnable runnable = () -> { + final PsiMethod prototype = (PsiMethod)containingClass.addBefore(methodPrototype, method); + RefactoringUtil.fixJavadocsForParams(prototype, new HashSet(Arrays.asList(prototype.getParameterList().getParameters()))); + TemplateBuilderImpl builder = new TemplateBuilderImpl(prototype); + + PsiCodeBlock body = prototype.getBody(); + final String callArgs = + "(" + StringUtil.join(method.getParameterList().getParameters(), psiParameter -> { + if (ArrayUtil.find(parameters, psiParameter) > -1) return "IntelliJIDEARulezzz"; + return psiParameter.getName(); + }, ",") + ");"; + final String methodCall; + if (method.getReturnType() == null) { + methodCall = "this"; + } else if (!PsiType.VOID.equals(method.getReturnType())) { + methodCall = "return " + method.getName(); + } else { + methodCall = method.getName(); + } + LOG.assertTrue(body != null); + body.add(JavaPsiFacade.getElementFactory(project).createStatementFromText(methodCall + callArgs, method)); + body = (PsiCodeBlock)CodeStyleManager.getInstance(project).reformat(body); + final PsiStatement stmt = body.getStatements()[0]; + PsiExpression expr = null; + if (stmt instanceof PsiReturnStatement) { + expr = ((PsiReturnStatement)stmt).getReturnValue(); + } else if (stmt instanceof PsiExpressionStatement) { + expr = ((PsiExpressionStatement)stmt).getExpression(); + } + if (expr instanceof PsiMethodCallExpression) { + PsiMethodCallExpression methodCallExp = (PsiMethodCallExpression)expr; + RangeMarker rangeMarker = editor.getDocument().createRangeMarker(prototype.getTextRange()); + for (PsiParameter parameter : parameters) { + final PsiExpression exprToBeDefault = + methodCallExp.getArgumentList().getExpressions()[method.getParameterList().getParameterIndex(parameter)]; + builder.replaceElement(exprToBeDefault, new TextExpression("")); + } + Template template = builder.buildTemplate(); + editor.getCaretModel().moveToOffset(rangeMarker.getStartOffset()); + + PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.getDocument()); + editor.getDocument().deleteString(rangeMarker.getStartOffset(), rangeMarker.getEndOffset()); + + rangeMarker.dispose(); + + CreateFromUsageBaseFix.startTemplate(editor, template, project); + } + }; + if (startInWriteAction()) { + runnable.run(); + } else { + ApplicationManager.getApplication().runWriteAction(runnable); + } + } + + @Nullable protected PsiParameter[] getParams(PsiElement element) { final PsiMethod method = PsiTreeUtil.getParentOfType(element, PsiMethod.class); assert method != null; final PsiParameter[] parameters = method.getParameterList().getParameters(); + if (parameters.length == 1) { + return parameters; + } final ParameterClassMember[] members = new ParameterClassMember[parameters.length]; for (int i = 0; i < members.length; i++) { members[i] = new ParameterClassMember(parameters[i]); } + final PsiParameter selectedParam = PsiTreeUtil.getParentOfType(element, PsiParameter.class); + final int idx = selectedParam != null ? ArrayUtil.find(parameters, selectedParam) : -1; + if (ApplicationManager.getApplication().isUnitTestMode()) { + return idx >= 0 ? new PsiParameter[] {selectedParam} : null; + } final MemberChooser chooser = new MemberChooser(members, false, true, element.getProject()); - chooser.selectElements(members); + if (idx >= 0) { + chooser.selectElements(new ClassMember[] {members[idx]}); + } + else { + chooser.selectElements(members); + } chooser.setTitle("Choose Default Value Parameters"); chooser.setCopyJavadocVisible(false); if (chooser.showAndGet()) { @@ -84,14 +207,34 @@ public class DefineParamsDefaultValueAction extends DelegateWithDefaultParamValu return null; } - @Override - public boolean startInWriteAction() { - return false; - } + private static PsiMethod generateMethodPrototype(PsiMethod method, PsiParameter... params) { + final PsiMethod prototype = (PsiMethod)method.copy(); + final PsiCodeBlock body = prototype.getBody(); + final PsiCodeBlock emptyBody = JavaPsiFacade.getElementFactory(method.getProject()).createMethodFromText("void foo(){}", prototype).getBody(); + assert emptyBody != null; + if (body != null) { + body.replace(emptyBody); + } else { + prototype.getModifierList().setModifierProperty(PsiModifier.ABSTRACT, false); + prototype.addBefore(emptyBody, null); + } - @NotNull - @Override - public String getFamilyName() { - return "Generate overloaded method with default parameter values"; + final PsiClass aClass = method.getContainingClass(); + if (aClass != null && aClass.isInterface() && !method.hasModifierProperty(PsiModifier.STATIC)) { + prototype.getModifierList().setModifierProperty(PsiModifier.DEFAULT, true); + } + + final PsiParameterList parameterList = method.getParameterList(); + Arrays.sort(params, (p1, p2) -> { + final int parameterIndex1 = parameterList.getParameterIndex(p1); + final int parameterIndex2 = parameterList.getParameterIndex(p2); + return parameterIndex1 > parameterIndex2 ? -1 : 1; + }); + + for (PsiParameter param : params) { + final int parameterIndex = parameterList.getParameterIndex(param); + prototype.getParameterList().getParameters()[parameterIndex].delete(); + } + return prototype; } } 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 deleted file mode 100644 index d3bbc2bed94d..000000000000 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DelegateWithDefaultParamValueIntentionAction.java +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright 2000-2015 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.codeInsight.daemon.impl.quickfix; - -import com.intellij.codeInsight.FileModificationService; -import com.intellij.codeInsight.hint.HintManager; -import com.intellij.codeInsight.intention.LowPriorityAction; -import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction; -import com.intellij.codeInsight.template.Template; -import com.intellij.codeInsight.template.TemplateBuilderImpl; -import com.intellij.codeInsight.template.impl.TextExpression; -import com.intellij.icons.AllIcons; -import com.intellij.lang.StdLanguages; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.editor.RangeMarker; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Iconable; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.psi.*; -import com.intellij.psi.codeStyle.CodeStyleManager; -import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.psi.util.PsiUtil; -import com.intellij.refactoring.util.RefactoringUtil; -import com.intellij.util.ArrayUtil; -import com.intellij.util.Function; -import com.intellij.util.IncorrectOperationException; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import javax.swing.*; -import java.util.Arrays; -import java.util.Comparator; -import java.util.HashSet; - -/** - * User: anna - */ -public class DelegateWithDefaultParamValueIntentionAction extends PsiElementBaseIntentionAction implements Iconable, LowPriorityAction { - @Override - public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element) { - final PsiParameter parameter = PsiTreeUtil.getParentOfType(element, PsiParameter.class); - if (parameter != null) { - if (!parameter.getLanguage().isKindOf(StdLanguages.JAVA)) return false; - final PsiElement declarationScope = parameter.getDeclarationScope(); - if (declarationScope instanceof PsiMethod) { - final PsiMethod method = (PsiMethod)declarationScope; - final PsiClass containingClass = method.getContainingClass(); - if (containingClass != null && (!containingClass.isInterface() || PsiUtil.isLanguageLevel8OrHigher(method))) { - if (containingClass.findMethodBySignature(generateMethodPrototype(method, parameter), false) != null) { - return false; - } - setText("Generate overloaded " + (method.isConstructor() ? "constructor" : "method") + " with default parameter value"); - return true; - } - } - } - return false; - } - - @Override - public Icon getIcon(int flags) { - return AllIcons.Actions.RefactoringBulb; - } - - private static PsiMethod generateMethodPrototype(PsiMethod method, PsiParameter... params) { - final PsiMethod prototype = (PsiMethod)method.copy(); - final PsiCodeBlock body = prototype.getBody(); - final PsiCodeBlock emptyBody = JavaPsiFacade.getElementFactory(method.getProject()).createMethodFromText("void foo(){}", prototype).getBody(); - assert emptyBody != null; - if (body != null) { - body.replace(emptyBody); - } else { - prototype.getModifierList().setModifierProperty(PsiModifier.ABSTRACT, false); - prototype.addBefore(emptyBody, null); - } - - final PsiClass aClass = method.getContainingClass(); - if (aClass != null && aClass.isInterface() && !method.hasModifierProperty(PsiModifier.STATIC)) { - prototype.getModifierList().setModifierProperty(PsiModifier.DEFAULT, true); - } - - final PsiParameterList parameterList = method.getParameterList(); - Arrays.sort(params, (p1, p2) -> { - final int parameterIndex1 = parameterList.getParameterIndex(p1); - final int parameterIndex2 = parameterList.getParameterIndex(p2); - return parameterIndex1 > parameterIndex2 ? -1 : 1; - }); - - for (PsiParameter param : params) { - final int parameterIndex = parameterList.getParameterIndex(param); - prototype.getParameterList().getParameters()[parameterIndex].delete(); - } - return prototype; - } - - @Override - public void invoke(@NotNull final Project project, final Editor editor, @NotNull PsiElement element) throws IncorrectOperationException { - final PsiParameter[] parameters = getParams(element); - if (parameters == null || parameters.length == 0) return; - final PsiMethod method = (PsiMethod)parameters[0].getDeclarationScope(); - final PsiMethod methodPrototype = generateMethodPrototype(method, parameters); - final PsiMethod existingMethod = method.getContainingClass().findMethodBySignature(methodPrototype, false); - if (existingMethod != null) { - editor.getCaretModel().moveToOffset(existingMethod.getTextOffset()); - HintManager.getInstance().showErrorHint(editor, (existingMethod.isConstructor() ? "Constructor" : "Method") + - " with the chosen signature already exists"); - return; - } - - if (!FileModificationService.getInstance().preparePsiElementForWrite(element)) return; - - Runnable runnable = () -> { - - final PsiMethod prototype = (PsiMethod)method.getContainingClass().addBefore(methodPrototype, method); - RefactoringUtil.fixJavadocsForParams(prototype, new HashSet(Arrays.asList(prototype.getParameterList().getParameters()))); - TemplateBuilderImpl builder = new TemplateBuilderImpl(prototype); - - PsiCodeBlock body = prototype.getBody(); - final String callArgs = - "(" + StringUtil.join(method.getParameterList().getParameters(), psiParameter -> { - if (ArrayUtil.find(parameters, psiParameter) > -1) return "IntelliJIDEARulezzz"; - return psiParameter.getName(); - }, ",") + ");"; - final String methodCall; - if (method.getReturnType() == null) { - methodCall = "this"; - } else if (!PsiType.VOID.equals(method.getReturnType())) { - methodCall = "return " + method.getName(); - } else { - methodCall = method.getName(); - } - body.add(JavaPsiFacade.getElementFactory(project).createStatementFromText(methodCall + callArgs, method)); - body = (PsiCodeBlock)CodeStyleManager.getInstance(project).reformat(body); - final PsiStatement stmt = body.getStatements()[0]; - PsiExpression expr = null; - if (stmt instanceof PsiReturnStatement) { - expr = ((PsiReturnStatement)stmt).getReturnValue(); - } else if (stmt instanceof PsiExpressionStatement) { - expr = ((PsiExpressionStatement)stmt).getExpression(); - } - if (expr instanceof PsiMethodCallExpression) { - PsiMethodCallExpression methodCallExp = (PsiMethodCallExpression)expr; - RangeMarker rangeMarker = editor.getDocument().createRangeMarker(prototype.getTextRange()); - for (PsiParameter parameter : parameters) { - final PsiExpression exprToBeDefault = - methodCallExp.getArgumentList().getExpressions()[method.getParameterList().getParameterIndex(parameter)]; - builder.replaceElement(exprToBeDefault, new TextExpression("")); - } - Template template = builder.buildTemplate(); - editor.getCaretModel().moveToOffset(rangeMarker.getStartOffset()); - - PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.getDocument()); - editor.getDocument().deleteString(rangeMarker.getStartOffset(), rangeMarker.getEndOffset()); - - rangeMarker.dispose(); - - CreateFromUsageBaseFix.startTemplate(editor, template, project); - } - }; - if (startInWriteAction()) { - runnable.run(); - } else { - ApplicationManager.getApplication().runWriteAction(runnable); - } - } - - @Nullable - protected PsiParameter[] getParams(PsiElement element) { - return new PsiParameter[]{PsiTreeUtil.getParentOfType(element, PsiParameter.class)}; - } - - @NotNull - @Override - public String getFamilyName() { - return "Generate overloaded method with default parameter value"; - } -} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/after1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/after1.java index 89683098fc6b..d785f80ad35f 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/after1.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/after1.java @@ -1,4 +1,4 @@ -// "Generate overloaded method with default parameter value" "true" +// "Generate overloaded method with default parameter values" "true" class Test { void foo() { foo(); diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/afterAbstractMethod.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/afterAbstractMethod.java index e72764fff0dc..768f01176512 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/afterAbstractMethod.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/afterAbstractMethod.java @@ -1,4 +1,4 @@ -// "Generate overloaded method with default parameter value" "true" +// "Generate overloaded method with default parameter values" "true" abstract class Test { int foo(boolean... args) { return foo(, args); diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/afterCommentsInBody.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/afterCommentsInBody.java index 4844902fdf14..0bd44690c430 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/afterCommentsInBody.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/afterCommentsInBody.java @@ -1,4 +1,4 @@ -// "Generate overloaded method with default parameter value" "true" +// "Generate overloaded method with default parameter values" "true" class Test { int foo() { return foo(); diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/afterConstructor.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/afterConstructor.java index b73c48ebd2df..1f3d305ec5b1 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/afterConstructor.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/afterConstructor.java @@ -1,4 +1,4 @@ -// "Generate overloaded constructor with default parameter value" "true" +// "Generate overloaded constructor with default parameter values" "true" class Test { Test() { this(); diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/afterExistinMethod.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/afterExistinMethod.java new file mode 100644 index 000000000000..d1e063f7955a --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/afterExistinMethod.java @@ -0,0 +1,6 @@ +// "Generate overloaded method with default parameter values" "true" +class Test { + void foo(){} + void foo(int ii){ + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/afterInterface.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/afterInterface.java index decd3f141818..7a3ddc85e93d 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/afterInterface.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/afterInterface.java @@ -1,4 +1,4 @@ -// "Generate overloaded method with default parameter value" "true" +// "Generate overloaded method with default parameter values" "true" interface Test { default void foo() { foo(); diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/afterJavadoc.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/afterJavadoc.java index 3f15183133d7..697c0e305b6a 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/afterJavadoc.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/afterJavadoc.java @@ -1,4 +1,4 @@ -// "Generate overloaded method with default parameter value" "true" +// "Generate overloaded method with default parameter values" "true" class Test { /** */ diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/afterReturnValue.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/afterReturnValue.java index 1e89e83a3cb7..971da0d8e6da 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/afterReturnValue.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/afterReturnValue.java @@ -1,4 +1,4 @@ -// "Generate overloaded method with default parameter value" "true" +// "Generate overloaded method with default parameter values" "true" class Test { int foo() { return foo(); diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/afterStaticMethodInInterface.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/afterStaticMethodInInterface.java index 01e1bdab551b..eb84d0998b75 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/afterStaticMethodInInterface.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/afterStaticMethodInInterface.java @@ -1,4 +1,4 @@ -// "Generate overloaded method with default parameter value" "true" +// "Generate overloaded method with default parameter values" "true" interface Test { static void foo() { foo(); diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/afterTypeParams.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/afterTypeParams.java index 57fb3563e0ac..c392c5a86323 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/afterTypeParams.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/afterTypeParams.java @@ -1,4 +1,4 @@ -// "Generate overloaded method with default parameter value" "true" +// "Generate overloaded method with default parameter values" "true" class Test { int foo(boolean... args) { return foo(, args); diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/afterVarargs.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/afterVarargs.java index 68e2eaeec564..d9878cc69b41 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/afterVarargs.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/afterVarargs.java @@ -1,4 +1,4 @@ -// "Generate overloaded method with default parameter value" "true" +// "Generate overloaded method with default parameter values" "true" class Test { int foo(boolean... args) { return foo(, args); diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/before1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/before1.java index 48895a8251b2..558e6e4c68f6 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/before1.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/before1.java @@ -1,4 +1,4 @@ -// "Generate overloaded method with default parameter value" "true" +// "Generate overloaded method with default parameter values" "true" class Test { void foo(int ii){ } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeAbstractMethod.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeAbstractMethod.java index 320debae10f2..9080288f6fa8 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeAbstractMethod.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeAbstractMethod.java @@ -1,4 +1,4 @@ -// "Generate overloaded method with default parameter value" "true" +// "Generate overloaded method with default parameter values" "true" abstract class Test { abstract int foo(int ii, boolean... args); } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeCommentsInBody.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeCommentsInBody.java index 9a6ad6184854..97357c6b3e0e 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeCommentsInBody.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeCommentsInBody.java @@ -1,4 +1,4 @@ -// "Generate overloaded method with default parameter value" "true" +// "Generate overloaded method with default parameter values" "true" class Test { int foo(int ii){ //comment1 diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeConstructor.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeConstructor.java index 7fe236b65cf4..a8b8be8ba4b8 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeConstructor.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeConstructor.java @@ -1,4 +1,4 @@ -// "Generate overloaded constructor with default parameter value" "true" +// "Generate overloaded constructor with default parameter values" "true" class Test { Test(int ii){} } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeExistinMethod.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeExistinMethod.java index 52fa17401c5d..f8dbe503ccc7 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeExistinMethod.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeExistinMethod.java @@ -1,4 +1,4 @@ -// "Generate overloaded method with default parameter value" "false" +// "Generate overloaded method with default parameter values" "true" class Test { void foo(){} void foo(int ii){ diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeInterface.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeInterface.java index 1f960d28b21d..8217a2c642fe 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeInterface.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeInterface.java @@ -1,4 +1,4 @@ -// "Generate overloaded method with default parameter value" "true" +// "Generate overloaded method with default parameter values" "true" interface Test { void foo(int ii); } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeJavadoc.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeJavadoc.java index 267cdf9f901a..c4906ebcfafb 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeJavadoc.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeJavadoc.java @@ -1,4 +1,4 @@ -// "Generate overloaded method with default parameter value" "true" +// "Generate overloaded method with default parameter values" "true" class Test { /** * @param i diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeReturnValue.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeReturnValue.java index 4df7057f4e31..056d8badf78b 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeReturnValue.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeReturnValue.java @@ -1,4 +1,4 @@ -// "Generate overloaded method with default parameter value" "true" +// "Generate overloaded method with default parameter values" "true" class Test { int foo(int ii){ return 1; diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeStaticMethodInInterface.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeStaticMethodInInterface.java index 5ea839e503a6..f2026953d9f3 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeStaticMethodInInterface.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeStaticMethodInInterface.java @@ -1,4 +1,4 @@ -// "Generate overloaded method with default parameter value" "true" +// "Generate overloaded method with default parameter values" "true" interface Test { static void foo(int ii) {} } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeTypeParams.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeTypeParams.java index e55000a24f37..4ab9ec7459fd 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeTypeParams.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeTypeParams.java @@ -1,4 +1,4 @@ -// "Generate overloaded method with default parameter value" "true" +// "Generate overloaded method with default parameter values" "true" class Test { int foo(T ii, boolean... args){ return 1; diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeVarargs.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeVarargs.java index 6ddbc5a9069c..7f6628882710 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeVarargs.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeVarargs.java @@ -1,4 +1,4 @@ -// "Generate overloaded method with default parameter value" "true" +// "Generate overloaded method with default parameter values" "true" class Test { int foo(int ii, boolean... args){ return 1; diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/DelegateWithDefaultParamValueTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/DelegateWithDefaultParamValueTest.java index c53bb0085d87..eb9825dd8c70 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/DelegateWithDefaultParamValueTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/DelegateWithDefaultParamValueTest.java @@ -30,8 +30,9 @@ public class DelegateWithDefaultParamValueTest extends LightQuickFixParameterize if (actionShouldBeAvailable) { TemplateState state = TemplateManagerImpl.getTemplateState(getEditor()); - assert state != null; - state.gotoEnd(false); + if (state != null) { + state.gotoEnd(false); + } } } diff --git a/resources-en/src/intentionDescriptions/DelegateWithDefaultParamValueIntentionAction/after.java.template b/resources-en/src/intentionDescriptions/DelegateWithDefaultParamValueIntentionAction/after.java.template deleted file mode 100644 index 8b1a0e1d4fe8..000000000000 --- a/resources-en/src/intentionDescriptions/DelegateWithDefaultParamValueIntentionAction/after.java.template +++ /dev/null @@ -1,9 +0,0 @@ -class Test { - void foo(int a) { - foo(a, |); - } - - void foo(int a, int b) { - //do smth - } -} \ No newline at end of file diff --git a/resources-en/src/intentionDescriptions/DelegateWithDefaultParamValueIntentionAction/before.java.template b/resources-en/src/intentionDescriptions/DelegateWithDefaultParamValueIntentionAction/before.java.template deleted file mode 100644 index 0ecad2088cdf..000000000000 --- a/resources-en/src/intentionDescriptions/DelegateWithDefaultParamValueIntentionAction/before.java.template +++ /dev/null @@ -1,5 +0,0 @@ -class Test { - void foo(int a, int b) { - //do smth - } -} \ No newline at end of file diff --git a/resources-en/src/intentionDescriptions/DelegateWithDefaultParamValueIntentionAction/description.html b/resources-en/src/intentionDescriptions/DelegateWithDefaultParamValueIntentionAction/description.html deleted file mode 100644 index 821c26642038..000000000000 --- a/resources-en/src/intentionDescriptions/DelegateWithDefaultParamValueIntentionAction/description.html +++ /dev/null @@ -1,5 +0,0 @@ - - -Generates an overloaded method which delegates to the current one setting the selected parameter to the specified default value. - - diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml index 241fb3149571..29201b0565b2 100644 --- a/resources/src/META-INF/IdeaPlugin.xml +++ b/resources/src/META-INF/IdeaPlugin.xml @@ -960,10 +960,6 @@ com.intellij.codeInsight.intention.impl.AddOverrideAnnotationAction Java/Annotations - - com.intellij.codeInsight.daemon.impl.quickfix.DelegateWithDefaultParamValueIntentionAction - Java/Declaration - com.intellij.codeInsight.daemon.impl.quickfix.DefineParamsDefaultValueAction Java/Declaration From 6cf80674b1f2f03204fdf641fa5dcf76e5e81b1e Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Thu, 23 Jun 2016 14:27:43 +0300 Subject: [PATCH 052/107] cleanup --- .../src/com/intellij/util/concurrency/SchedulingWrapper.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/platform/util/src/com/intellij/util/concurrency/SchedulingWrapper.java b/platform/util/src/com/intellij/util/concurrency/SchedulingWrapper.java index 52aad13bc246..bdf89a41ddd6 100644 --- a/platform/util/src/com/intellij/util/concurrency/SchedulingWrapper.java +++ b/platform/util/src/com/intellij/util/concurrency/SchedulingWrapper.java @@ -183,8 +183,7 @@ class SchedulingWrapper implements ScheduledExecutorService { @Override public int compareTo(@NotNull Delayed other) { - if (other == this) // compare zero if same object - { + if (other == this) { return 0; } if (other instanceof MyScheduledFutureTask) { From 73684fa942160fb21071923ef04df52d9bb0f234 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Fri, 24 Jun 2016 12:04:16 +0300 Subject: [PATCH 053/107] more diagnostics on exception in applyInformation --- .../daemon/impl/PassExecutorService.java | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PassExecutorService.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PassExecutorService.java index 534ec24f9e19..87c490400fec 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PassExecutorService.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PassExecutorService.java @@ -35,18 +35,17 @@ import com.intellij.openapi.fileEditor.FileEditor; import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.fileEditor.TextEditor; import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx; +import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.DumbAwareRunnable; import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.util.Consumer; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.MultiMap; import gnu.trove.THashMap; @@ -57,7 +56,10 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.TestOnly; import java.util.*; -import java.util.concurrent.*; +import java.util.concurrent.CancellationException; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicInteger; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -506,10 +508,18 @@ class PassExecutorService implements Disposable { pass.applyInformationToEditor(); } } - catch (RuntimeException e) { + catch (ProcessCanceledException e) { log(updateProgress, pass, "Error " + e); throw e; } + catch (RuntimeException e) { + Document document = pass.getDocument(); + VirtualFile file = document == null ? null : FileDocumentManager.getInstance().getFile(document); + FileType fileType = file == null ? null : file.getFileType(); + String message = "Exception while applying information to " + fileEditor + "("+fileType+")"; + log(updateProgress, pass, message + e); + throw new RuntimeException(message, e); + } if (threadsToStartCountdown.decrementAndGet() == 0) { log(updateProgress, pass, "Stopping "); updateProgress.stopIfRunning(); From 1699a0d80ded08a38e5c87b28ad9be6737395582 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Fri, 24 Jun 2016 12:05:59 +0300 Subject: [PATCH 054/107] notnull, cleanup --- .../fileEditor/TextEditorLocation.java | 2 +- .../com/intellij/openapi/wm/ToolWindow.java | 6 +- .../intellij/openapi/wm/ToolWindowAnchor.java | 13 +- .../openapi/wm/ToolWindowManager.java | 24 +- .../intellij/designer/LightToolWindow.java | 25 +- .../DefaultFrameEditorComponentProvider.java | 5 +- .../wm/ex/FrameEditorComponentProvider.java | 4 +- .../openapi/wm/ex/ToolWindowManagerEx.java | 7 +- .../intellij/openapi/wm/impl/ActiveStack.java | 20 +- .../openapi/wm/impl/DesktopLayout.java | 66 ++-- .../openapi/wm/impl/FloatingDecorator.java | 5 +- .../openapi/wm/impl/InternalDecorator.java | 12 +- .../wm/impl/InternalDecoratorListener.java | 20 +- .../com/intellij/openapi/wm/impl/Stripe.java | 7 +- .../openapi/wm/impl/ToolWindowHeader.java | 53 +-- .../impl/ToolWindowHeadlessManagerImpl.java | 34 +- .../openapi/wm/impl/ToolWindowImpl.java | 34 +- .../wm/impl/ToolWindowManagerImpl.java | 372 +++++++----------- .../openapi/wm/impl/ToolWindowsPane.java | 236 +++++------ .../openapi/wm/impl/WindowInfoImpl.java | 80 ++-- .../openapi/wm/impl/WindowedDecorator.java | 5 +- .../wm/impl/commands/FinalizableCommand.java | 7 +- .../src/com/intellij/mock/Mock.java | 8 +- .../src/com/intellij/util/RetinaImage.java | 4 + .../util/src/com/intellij/util/ui/UIUtil.java | 2 + 25 files changed, 513 insertions(+), 538 deletions(-) diff --git a/platform/platform-api/src/com/intellij/openapi/fileEditor/TextEditorLocation.java b/platform/platform-api/src/com/intellij/openapi/fileEditor/TextEditorLocation.java index 9477beb04a11..ef1c4ed6dd23 100644 --- a/platform/platform-api/src/com/intellij/openapi/fileEditor/TextEditorLocation.java +++ b/platform/platform-api/src/com/intellij/openapi/fileEditor/TextEditorLocation.java @@ -50,7 +50,7 @@ public class TextEditorLocation implements FileEditorLocation { } @Override - public int compareTo(FileEditorLocation fileEditorLocation) { + public int compareTo(@NotNull FileEditorLocation fileEditorLocation) { TextEditorLocation otherLocation = (TextEditorLocation)fileEditorLocation; if (myEditor != otherLocation.myEditor) { LOG.error("Different editors: " + myEditor + "; and " + otherLocation.myEditor); diff --git a/platform/platform-api/src/com/intellij/openapi/wm/ToolWindow.java b/platform/platform-api/src/com/intellij/openapi/wm/ToolWindow.java index 841b46bf6148..9460fd2c3f36 100644 --- a/platform/platform-api/src/com/intellij/openapi/wm/ToolWindow.java +++ b/platform/platform-api/src/com/intellij/openapi/wm/ToolWindow.java @@ -29,7 +29,7 @@ import java.awt.event.InputEvent; public interface ToolWindow extends BusyObject { - Key SHOW_CONTENT_ICON = new Key("ContentIcon"); + Key SHOW_CONTENT_ICON = new Key<>("ContentIcon"); /** * @exception IllegalStateException if tool window isn't installed. @@ -74,7 +74,7 @@ public interface ToolWindow extends BusyObject { /** * @exception IllegalStateException if tool window isn't installed. */ - void setAnchor(ToolWindowAnchor anchor, @Nullable Runnable runnable); + void setAnchor(@NotNull ToolWindowAnchor anchor, @Nullable Runnable runnable); /** * @exception IllegalStateException if tool window isn't installed. @@ -104,7 +104,7 @@ public interface ToolWindow extends BusyObject { /** * @exception IllegalStateException if tool window isn't installed. */ - void setType(ToolWindowType type, @Nullable Runnable runnable); + void setType(@NotNull ToolWindowType type, @Nullable Runnable runnable); /** * @return window icon. Returns null if window has no icon. diff --git a/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowAnchor.java b/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowAnchor.java index 1628a6f679bf..88f544d237de 100644 --- a/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowAnchor.java +++ b/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowAnchor.java @@ -17,6 +17,7 @@ package com.intellij.openapi.wm; import com.intellij.ide.ui.UISettings; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; import javax.swing.*; @@ -26,9 +27,10 @@ public final class ToolWindowAnchor { public static final ToolWindowAnchor BOTTOM = new ToolWindowAnchor("bottom"); public static final ToolWindowAnchor RIGHT = new ToolWindowAnchor("right"); + @NotNull private final String myText; - private ToolWindowAnchor(@NonNls String text){ + private ToolWindowAnchor(@NonNls @NotNull String text){ myText = text; } @@ -40,6 +42,7 @@ public final class ToolWindowAnchor { return this == TOP || this == BOTTOM; } + @NotNull public static ToolWindowAnchor get(int swingOrientationConstant) { switch(swingOrientationConstant) { case SwingConstants.TOP: @@ -56,12 +59,16 @@ public final class ToolWindowAnchor { } public boolean isSplitVertically() { - return (this == LEFT && !UISettings.getInstance().LEFT_HORIZONTAL_SPLIT) || (this == RIGHT && !UISettings.getInstance().RIGHT_HORIZONTAL_SPLIT); + return this == LEFT && !UISettings.getInstance().LEFT_HORIZONTAL_SPLIT + || this == RIGHT && !UISettings.getInstance().RIGHT_HORIZONTAL_SPLIT; } + @NotNull public static ToolWindowAnchor fromText(String anchor) { for (ToolWindowAnchor a : new ToolWindowAnchor[]{TOP, LEFT, BOTTOM, RIGHT}) { - if (a.myText.equals(anchor)) return a; + if (a.myText.equals(anchor)) { + return a; + } } throw new IllegalArgumentException("Unknown anchor constant: " + anchor); } diff --git a/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowManager.java b/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowManager.java index 8baa090b2af2..96fbb41189ad 100644 --- a/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowManager.java +++ b/platform/platform-api/src/com/intellij/openapi/wm/ToolWindowManager.java @@ -73,7 +73,7 @@ public abstract class ToolWindowManager { public abstract ToolWindow registerToolWindow(@NotNull String id, @NotNull JComponent component, @NotNull ToolWindowAnchor anchor, - Disposable parentDisposable, + @NotNull Disposable parentDisposable, boolean canWorkInDumbMode); /** * @deprecated {@link ToolWindowManager#registerToolWindow(String, boolean, ToolWindowAnchor)} @@ -83,7 +83,7 @@ public abstract class ToolWindowManager { public abstract ToolWindow registerToolWindow(@NotNull String id, @NotNull JComponent component, @NotNull ToolWindowAnchor anchor, - Disposable parentDisposable, + @NotNull Disposable parentDisposable, boolean canWorkInDumbMode, boolean canCloseContents); @@ -91,19 +91,31 @@ public abstract class ToolWindowManager { public abstract ToolWindow registerToolWindow(@NotNull String id, boolean canCloseContent, @NotNull ToolWindowAnchor anchor); @NotNull - public abstract ToolWindow registerToolWindow(@NotNull String id, boolean canCloseContent, @NotNull ToolWindowAnchor anchor, boolean secondary); + public abstract ToolWindow registerToolWindow(@NotNull String id, + boolean canCloseContent, + @NotNull ToolWindowAnchor anchor, + boolean secondary); @NotNull - public abstract ToolWindow registerToolWindow(@NotNull String id, boolean canCloseContent, @NotNull ToolWindowAnchor anchor, Disposable parentDisposable, boolean canWorkInDumbMode); + public abstract ToolWindow registerToolWindow(@NotNull String id, + boolean canCloseContent, + @NotNull ToolWindowAnchor anchor, + @NotNull Disposable parentDisposable, + boolean canWorkInDumbMode); @NotNull - public abstract ToolWindow registerToolWindow(@NotNull String id, boolean canCloseContent, @NotNull ToolWindowAnchor anchor, Disposable parentDisposable, boolean canWorkInDumbMode, boolean secondary); + public abstract ToolWindow registerToolWindow(@NotNull String id, + boolean canCloseContent, + @NotNull ToolWindowAnchor anchor, + @NotNull Disposable parentDisposable, + boolean canWorkInDumbMode, + boolean secondary); @NotNull public ToolWindow registerToolWindow(@NotNull final String id, final boolean canCloseContent, @NotNull final ToolWindowAnchor anchor, - final Disposable parentDisposable) { + @NotNull Disposable parentDisposable) { return registerToolWindow(id, canCloseContent, anchor, parentDisposable, false); } diff --git a/platform/platform-impl/src/com/intellij/designer/LightToolWindow.java b/platform/platform-impl/src/com/intellij/designer/LightToolWindow.java index 7bdb59ea19e2..b1b8a84de370 100644 --- a/platform/platform-impl/src/com/intellij/designer/LightToolWindow.java +++ b/platform/platform-impl/src/com/intellij/designer/LightToolWindow.java @@ -46,9 +46,9 @@ import java.awt.event.*; * @author Alexander Lobas */ public class LightToolWindow extends JPanel { - public static final String LEFT_MIN_KEY = "left"; - public static final String RIGHT_MIN_KEY = "right"; - public static final int MINIMIZE_WIDTH = 25; + static final String LEFT_MIN_KEY = "left"; + static final String RIGHT_MIN_KEY = "right"; + static final int MINIMIZE_WIDTH = 25; private static final String IGNORE_WIDTH_KEY = "ignore_width"; private final LightToolWindowContent myContent; @@ -139,12 +139,14 @@ public class LightToolWindow extends JPanel { add(contentWrapper, BorderLayout.CENTER); addMouseListener(new MouseAdapter() { + @Override public void mouseReleased(final MouseEvent e) { IdeFocusManager.getInstance(myProject).requestFocus(myFocusedComponent, true); } }); addMouseListener(new PopupHandler() { + @Override public void invokePopup(Component component, int x, int y) { showGearPopup(component, x, y); } @@ -167,12 +169,9 @@ public class LightToolWindow extends JPanel { return myAnchor; } }; - myMinimizeButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - myMinimizeButton.setSelected(false); - updateContent(true, true); - } + myMinimizeButton.addActionListener(e -> { + myMinimizeButton.setSelected(false); + updateContent(true, true); }); myMinimizeButton.setBorder(BorderFactory.createEmptyBorder(5, 5, 0, 5)); myMinimizeButton.setFocusable(false); @@ -233,7 +232,7 @@ public class LightToolWindow extends JPanel { } } - public void updateAnchor(ToolWindowAnchor newAnchor) { + void updateAnchor(ToolWindowAnchor newAnchor) { JComponent minimizeParent = myContentSplitter.getInnerComponent(); minimizeParent.putClientProperty(IGNORE_WIDTH_KEY, Boolean.TRUE); @@ -374,7 +373,7 @@ public class LightToolWindow extends JPanel { } private class GearAction extends AnAction { - public GearAction() { + GearAction() { Presentation presentation = getTemplatePresentation(); presentation.setIcon(AllIcons.General.Gear); presentation.setHoveredIcon(AllIcons.General.GearHover); @@ -462,7 +461,7 @@ public class LightToolWindow extends JPanel { } private class ToggleWindowedModeAction extends ToggleTypeModeAction { - public ToggleWindowedModeAction() { + ToggleWindowedModeAction() { super(ToolWindowType.WINDOWED, InternalDecorator.TOGGLE_WINDOWED_MODE_ACTION_ID); } @@ -475,7 +474,7 @@ public class LightToolWindow extends JPanel { private class ToggleTypeModeAction extends ToggleAction { private final ToolWindowType myType; - public ToggleTypeModeAction(ToolWindowType type, String id) { + ToggleTypeModeAction(@NotNull ToolWindowType type, @NotNull String id) { myType = type; copyFrom(ActionManager.getInstance().getAction(id)); } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/ex/DefaultFrameEditorComponentProvider.java b/platform/platform-impl/src/com/intellij/openapi/wm/ex/DefaultFrameEditorComponentProvider.java index efab9e503b62..96346063e4a4 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/ex/DefaultFrameEditorComponentProvider.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/ex/DefaultFrameEditorComponentProvider.java @@ -2,6 +2,7 @@ package com.intellij.openapi.wm.ex; import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx; import com.intellij.openapi.project.Project; +import org.jetbrains.annotations.NotNull; import javax.swing.*; @@ -10,8 +11,8 @@ import javax.swing.*; */ public class DefaultFrameEditorComponentProvider implements FrameEditorComponentProvider { @Override - public JComponent createEditorComponent(Project project) { + public JComponent createEditorComponent(@NotNull Project project) { FileEditorManagerEx editorManager = FileEditorManagerEx.getInstanceEx(project); - return editorManager.getComponent(); + return editorManager.getComponent(); } } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/ex/FrameEditorComponentProvider.java b/platform/platform-impl/src/com/intellij/openapi/wm/ex/FrameEditorComponentProvider.java index f6fce90c56ab..5f012185e89e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/ex/FrameEditorComponentProvider.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/ex/FrameEditorComponentProvider.java @@ -2,14 +2,16 @@ package com.intellij.openapi.wm.ex; import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.openapi.project.Project; +import org.jetbrains.annotations.NotNull; import javax.swing.*; /** * @author Konstantin Bulenkov */ +@FunctionalInterface public interface FrameEditorComponentProvider { ExtensionPointName EP = ExtensionPointName.create("com.intellij.frameEditorComponentProvider"); - JComponent createEditorComponent(Project project); + JComponent createEditorComponent(@NotNull Project project); } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/ex/ToolWindowManagerEx.java b/platform/platform-impl/src/com/intellij/openapi/wm/ex/ToolWindowManagerEx.java index d8414ddc37ed..f38d3bab16b2 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/ex/ToolWindowManagerEx.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/ex/ToolWindowManagerEx.java @@ -35,9 +35,9 @@ public abstract class ToolWindowManagerEx extends ToolWindowManager { return (ToolWindowManagerEx)getInstance(project); } - public abstract void addToolWindowManagerListener(@NotNull ToolWindowManagerListener l); - public abstract void addToolWindowManagerListener(@NotNull ToolWindowManagerListener l, @NotNull Disposable parentDisposable); - public abstract void removeToolWindowManagerListener(@NotNull ToolWindowManagerListener l); + public abstract void addToolWindowManagerListener(@NotNull ToolWindowManagerListener listener); + public abstract void addToolWindowManagerListener(@NotNull ToolWindowManagerListener listener, @NotNull Disposable parentDisposable); + public abstract void removeToolWindowManagerListener(@NotNull ToolWindowManagerListener listener); /** * @return ID of tool window that was activated last time. @@ -69,5 +69,6 @@ public abstract class ToolWindowManagerEx extends ToolWindowManager { public abstract void hideToolWindow(@NotNull String id, boolean hideSide); + @NotNull public abstract List getIdsOn(@NotNull ToolWindowAnchor anchor); } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ActiveStack.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ActiveStack.java index ef8cdf338406..f99d3e221238 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ActiveStack.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ActiveStack.java @@ -15,8 +15,10 @@ */ package com.intellij.openapi.wm.impl; +import com.intellij.util.containers.Stack; +import org.jetbrains.annotations.NotNull; + import java.util.Iterator; -import java.util.Stack; /** * Actually this class represent two stacks. @@ -43,8 +45,8 @@ final class ActiveStack { * Creates enabled window stack. */ ActiveStack() { - myStack = new Stack(); - myPersistentStack = new Stack(); + myStack = new Stack<>(); + myPersistentStack = new Stack<>(); } /** @@ -61,10 +63,12 @@ final class ActiveStack { return myStack.isEmpty(); } + @NotNull String pop() { return myStack.pop(); } + @NotNull String peek() { return myStack.peek(); } @@ -73,10 +77,12 @@ final class ActiveStack { return myStack.size(); } - String peek(int i) { + @NotNull + private String peek(int i) { return myStack.get(getSize() - i - 1); } + @NotNull String[] getStack() { String[] result = new String[getSize()]; for (int i = 0; i < getSize(); i++) { @@ -85,6 +91,7 @@ final class ActiveStack { return result; } + @NotNull String[] getPersistentStack() { String[] result = new String[getPersistentSize()]; for (int i = 0; i < getPersistentSize(); i++) { @@ -93,7 +100,7 @@ final class ActiveStack { return result; } - void push(final String id) { + void push(@NotNull String id) { remove(id, true); myStack.push(id); myPersistentStack.push(id); @@ -106,6 +113,7 @@ final class ActiveStack { /** * Peeks element at the persistent stack. 0 means the top of the stack. */ + @NotNull String peekPersistent(final int index) { return myPersistentStack.get(myPersistentStack.size() - index - 1); } @@ -117,7 +125,7 @@ final class ActiveStack { * @param removePersistentAlso if true then clears last active ID * if it's the last active ID. */ - void remove(final String id, final boolean removePersistentAlso) { + void remove(@NotNull String id, final boolean removePersistentAlso) { for (Iterator i = myStack.iterator(); i.hasNext();) { if (id.equals(i.next())) { i.remove(); diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/DesktopLayout.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/DesktopLayout.java index 62c77fcb1357..a3cc0dea6e31 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/DesktopLayout.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/DesktopLayout.java @@ -36,11 +36,11 @@ public final class DesktopLayout implements JDOMExternalizable { /** * Map between ids and registered WindowInfos. */ - private final Map myRegisteredId2Info; + private final Map myRegisteredId2Info = new HashMap<>(); /** * Map between ids and unregistered WindowInfos. */ - private final Map myUnregisteredId2Info; + private final Map myUnregisteredId2Info = new HashMap<>(); /** * */ @@ -63,19 +63,15 @@ public final class DesktopLayout implements JDOMExternalizable { * if the cached data is invalid. */ private WindowInfoImpl[] myAllInfos; - @NonNls public static final String ID_ATTR = "id"; + @NonNls private static final String ID_ATTR = "id"; - public DesktopLayout() { - myRegisteredId2Info = new HashMap(); - myUnregisteredId2Info = new HashMap(); - } /** * Copies itself from the passed * * @param layout to be copied. */ - public final void copyFrom(final DesktopLayout layout) { + public final void copyFrom(@NotNull DesktopLayout layout) { final WindowInfoImpl[] infos = layout.getAllInfos(); for (WindowInfoImpl info1 : infos) { WindowInfoImpl info = myRegisteredId2Info.get(info1.getId()); @@ -128,7 +124,7 @@ public final class DesktopLayout implements JDOMExternalizable { return info; } - final void unregister(final String id) { + final void unregister(@NotNull String id) { final WindowInfoImpl info = myRegisteredId2Info.remove(id).copy(); myUnregisteredId2Info.put(id, info); // invalidate caches @@ -142,14 +138,12 @@ public final class DesktopLayout implements JDOMExternalizable { * If onlyRegistered is true then returns not null * value if and only if window with id is registered one. */ - final WindowInfoImpl getInfo(final String id, final boolean onlyRegistered) { + final WindowInfoImpl getInfo(String id, final boolean onlyRegistered) { final WindowInfoImpl info = myRegisteredId2Info.get(id); if (onlyRegistered || info != null) { return info; } - else { - return myUnregisteredId2Info.get(id); - } + return myUnregisteredId2Info.get(id); } @Nullable @@ -166,6 +160,7 @@ public final class DesktopLayout implements JDOMExternalizable { /** * @return WindowInfos for all registered tool windows. */ + @NotNull final WindowInfoImpl[] getInfos() { if (myRegisteredInfos == null) { myRegisteredInfos = myRegisteredId2Info.values().toArray(new WindowInfoImpl[myRegisteredId2Info.size()]); @@ -176,6 +171,7 @@ public final class DesktopLayout implements JDOMExternalizable { /** * @return WindowInfoss for all windows that are currently unregistered. */ + @NotNull private WindowInfoImpl[] getUnregisteredInfos() { if (myUnregisteredInfos == null) { myUnregisteredInfos = myUnregisteredId2Info.values().toArray(new WindowInfoImpl[myUnregisteredId2Info.size()]); @@ -186,7 +182,8 @@ public final class DesktopLayout implements JDOMExternalizable { /** * @return WindowInfos of all (registered and unregistered) tool windows. */ - WindowInfoImpl[] getAllInfos() { + @NotNull + private WindowInfoImpl[] getAllInfos() { final WindowInfoImpl[] registeredInfos = getInfos(); final WindowInfoImpl[] unregisteredInfos = getUnregisteredInfos(); myAllInfos = ArrayUtil.mergeArrays(registeredInfos, unregisteredInfos); @@ -197,9 +194,10 @@ public final class DesktopLayout implements JDOMExternalizable { * @return all (registered and not unregistered) WindowInfos for the specified anchor. * Returned infos are sorted by order. */ - private WindowInfoImpl[] getAllInfos(final ToolWindowAnchor anchor) { + @NotNull + private WindowInfoImpl[] getAllInfos(@NotNull ToolWindowAnchor anchor) { WindowInfoImpl[] infos = getAllInfos(); - final ArrayList list = new ArrayList(infos.length); + final ArrayList list = new ArrayList<>(infos.length); for (WindowInfoImpl info : infos) { if (anchor == info.getAnchor()) { list.add(info); @@ -214,7 +212,7 @@ public final class DesktopLayout implements JDOMExternalizable { * Normalizes order of windows in the passed array. Note, that array should be * sorted by order (by ascending). Order of first window will be 0. */ - private static void normalizeOrder(final WindowInfoImpl[] infos) { + private static void normalizeOrder(@NotNull WindowInfoImpl[] infos) { for (int i = 0; i < infos.length; i++) { infos[i].setOrder(i); } @@ -228,7 +226,8 @@ public final class DesktopLayout implements JDOMExternalizable { * @return comparator which compares StripeButtons in the stripe with * specified anchor. */ - final Comparator comparator(final ToolWindowAnchor anchor) { + @NotNull + final Comparator comparator(@NotNull ToolWindowAnchor anchor) { return new MyStripeButtonComparator(anchor); } @@ -237,7 +236,7 @@ public final class DesktopLayout implements JDOMExternalizable { * @return maximum ordinal number in the specified stripe. Returns -1 * if there is no any tool window with the specified anchor. */ - private int getMaxOrder(final ToolWindowAnchor anchor) { + private int getMaxOrder(@NotNull ToolWindowAnchor anchor) { int res = -1; final WindowInfoImpl[] infos = getAllInfos(); for (final WindowInfoImpl info : infos) { @@ -255,7 +254,7 @@ public final class DesktopLayout implements JDOMExternalizable { * @param newAnchor new anchor * @param newOrder new order */ - final void setAnchor(final String id, final ToolWindowAnchor newAnchor, int newOrder) { + final void setAnchor(@NotNull String id, @NotNull ToolWindowAnchor newAnchor, int newOrder) { if (newOrder == -1) { // if order isn't defined then the window will the last in the stripe newOrder = getMaxOrder(newAnchor) + 1; } @@ -279,11 +278,12 @@ public final class DesktopLayout implements JDOMExternalizable { } } - final void setSplitMode(final String id, boolean split) { + final void setSplitMode(@NotNull String id, boolean split) { final WindowInfoImpl info = getInfo(id, true); info.setSplit(split); } + @Override public final void readExternal(final Element layoutElement) { myUnregisteredInfos = null; for (Object o : layoutElement.getChildren()) { @@ -301,6 +301,7 @@ public final class DesktopLayout implements JDOMExternalizable { } } + @Override public final void writeExternal(final Element layoutElement) { final WindowInfoImpl[] infos = getAllInfos(); for (WindowInfoImpl info : infos) { @@ -310,30 +311,30 @@ public final class DesktopLayout implements JDOMExternalizable { } } - public List getVisibleIdsOn(final ToolWindowAnchor anchor, ToolWindowManagerImpl manager) { - ArrayList ids = new ArrayList(); + @NotNull + List getVisibleIdsOn(@NotNull ToolWindowAnchor anchor, @NotNull ToolWindowManagerImpl manager) { + List ids = new ArrayList<>(); for (WindowInfoImpl each : getAllInfos(anchor)) { - if (manager == null) break; - final ToolWindow window = manager.getToolWindow(each.getId()); - if (window == null) continue; - if (window.isAvailable() || UISettings.getInstance().ALWAYS_SHOW_WINDOW_BUTTONS) { - ids.add(each.getId()); - } + final ToolWindow window = manager.getToolWindow(each.getId()); + if (window == null) continue; + if (window.isAvailable() || UISettings.getInstance().ALWAYS_SHOW_WINDOW_BUTTONS) { + ids.add(each.getId()); + } } return ids; } private static final class MyWindowInfoComparator implements Comparator { + @Override public int compare(final WindowInfoImpl info1, final WindowInfoImpl info2) { return info1.getOrder() - info2.getOrder(); } } private final class MyStripeButtonComparator implements Comparator { - private final HashMap myId2Info; + private final HashMap myId2Info = new HashMap<>(); - public MyStripeButtonComparator(final ToolWindowAnchor anchor) { - myId2Info = new HashMap(); + public MyStripeButtonComparator(@NotNull ToolWindowAnchor anchor) { final WindowInfoImpl[] infos = getInfos(); for (final WindowInfoImpl info : infos) { if (anchor == info.getAnchor()) { @@ -342,6 +343,7 @@ public final class DesktopLayout implements JDOMExternalizable { } } + @Override public final int compare(final StripeButton obj1, final StripeButton obj2) { final WindowInfoImpl info1 = myId2Info.get(obj1.getWindowInfo().getId()); final int order1 = info1 != null ? info1.getOrder() : 0; diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/FloatingDecorator.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/FloatingDecorator.java index dabd6ada57f2..c3d0bc2f54fb 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/FloatingDecorator.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/FloatingDecorator.java @@ -28,6 +28,7 @@ import com.intellij.ui.JBColor; import com.intellij.ui.ScreenUtil; import com.intellij.util.Alarm; import com.intellij.util.ui.UIUtil; +import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.awt.*; @@ -66,7 +67,7 @@ public final class FloatingDecorator extends JDialog { private float myEndRatio; // start and end alpha ratio for transparency animation - FloatingDecorator(final IdeFrameImpl owner,final WindowInfoImpl info,final InternalDecorator internalDecorator){ + FloatingDecorator(final IdeFrameImpl owner, @NotNull WindowInfoImpl info, @NotNull InternalDecorator internalDecorator){ super(owner,internalDecorator.getToolWindow().getId()); MnemonicHelper.init(getContentPane()); myInternalDecorator=internalDecorator; @@ -154,7 +155,7 @@ public final class FloatingDecorator extends JDialog { super.dispose(); } - final void apply(final WindowInfoImpl info){ + final void apply(@NotNull WindowInfoImpl info){ LOG.assertTrue(info.isFloating()); myInfo=info; // Set alpha mode diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecorator.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecorator.java index 2dcec6aed305..a214765244fa 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecorator.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecorator.java @@ -116,7 +116,7 @@ public final class InternalDecorator extends JPanel implements Queryable, DataPr } @Override - protected void toolWindowTypeChanged(ToolWindowType type) { + protected void toolWindowTypeChanged(@NotNull ToolWindowType type) { fireTypeChanged(type); } @@ -214,7 +214,7 @@ public final class InternalDecorator extends JPanel implements Queryable, DataPr myProject = null; } - private void fireAnchorChanged(ToolWindowAnchor anchor) { + private void fireAnchorChanged(@NotNull ToolWindowAnchor anchor) { myDispatcher.getMulticaster().anchorChanged(this, anchor); } @@ -243,7 +243,7 @@ public final class InternalDecorator extends JPanel implements Queryable, DataPr myDispatcher.getMulticaster().activated(this); } - private void fireTypeChanged(ToolWindowType type) { + private void fireTypeChanged(@NotNull ToolWindowType type) { myDispatcher.getMulticaster().typeChanged(this, type); } @@ -255,7 +255,7 @@ public final class InternalDecorator extends JPanel implements Queryable, DataPr myDispatcher.getMulticaster().sideStatusChanged(this, isSide); } - private void fireContentUiTypeChanges(ToolWindowContentUiType type) { + private void fireContentUiTypeChanges(@NotNull ToolWindowContentUiType type) { myDispatcher.getMulticaster().contentUiTypeChanges(this, type); } @@ -512,9 +512,9 @@ public final class InternalDecorator extends JPanel implements Queryable, DataPr } private final class ChangeAnchorAction extends AnAction implements DumbAware { - private final ToolWindowAnchor myAnchor; + @NotNull private final ToolWindowAnchor myAnchor; - public ChangeAnchorAction(final String title, final ToolWindowAnchor anchor) { + public ChangeAnchorAction(@NotNull String title, @NotNull ToolWindowAnchor anchor) { super(title); myAnchor = anchor; } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecoratorListener.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecoratorListener.java index b59657225a06..38bba5916e71 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecoratorListener.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecoratorListener.java @@ -27,23 +27,23 @@ import java.util.EventListener; */ interface InternalDecoratorListener extends EventListener{ - public void anchorChanged(InternalDecorator source,ToolWindowAnchor anchor); + void anchorChanged(@NotNull InternalDecorator source, @NotNull ToolWindowAnchor anchor); - public void autoHideChanged(InternalDecorator source,boolean autoHide); + void autoHideChanged(@NotNull InternalDecorator source, boolean autoHide); - public void hidden(InternalDecorator source); + void hidden(@NotNull InternalDecorator source); - public void hiddenSide(InternalDecorator source); + void hiddenSide(@NotNull InternalDecorator source); - public void resized(InternalDecorator source); + void resized(@NotNull InternalDecorator source); - public void activated(InternalDecorator source); + void activated(@NotNull InternalDecorator source); - public void typeChanged(InternalDecorator source,ToolWindowType type); + void typeChanged(@NotNull InternalDecorator source, @NotNull ToolWindowType type); - public void sideStatusChanged(InternalDecorator source,boolean isSideTool); + void sideStatusChanged(@NotNull InternalDecorator source, boolean isSideTool); - public void contentUiTypeChanges(InternalDecorator sources, @NotNull ToolWindowContentUiType type); + void contentUiTypeChanges(@NotNull InternalDecorator sources, @NotNull ToolWindowContentUiType type); - public void visibleStripeButtonChanged(InternalDecorator source, boolean visible); + void visibleStripeButtonChanged(@NotNull InternalDecorator source, boolean visible); } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/Stripe.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/Stripe.java index 53124343ae01..a381b93e5168 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/Stripe.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/Stripe.java @@ -28,6 +28,7 @@ import com.intellij.ui.ColorUtil; import com.intellij.ui.Gray; import com.intellij.ui.ScreenUtil; import com.intellij.util.ui.UIUtil; +import org.jetbrains.annotations.NotNull; import javax.swing.*; import javax.swing.border.Border; @@ -166,7 +167,7 @@ final class Stripe extends JPanel implements UISettingsListener { super.removeNotify(); } - void addButton(final StripeButton button, final Comparator comparator) { + void addButton(@NotNull StripeButton button, final Comparator comparator) { myPrefSize = null; myButtons.add(button); Collections.sort(myButtons, comparator); @@ -174,7 +175,7 @@ final class Stripe extends JPanel implements UISettingsListener { revalidate(); } - void removeButton(final StripeButton button) { + void removeButton(@NotNull StripeButton button) { myPrefSize = null; myButtons.remove(button); remove(button); @@ -475,7 +476,7 @@ final class Stripe extends JPanel implements UISettingsListener { } } - public boolean containsScreen(final Rectangle screenRec) { + public boolean containsScreen(@NotNull Rectangle screenRec) { final Point point = screenRec.getLocation(); SwingUtilities.convertPointFromScreen(point, this); return new Rectangle(point, screenRec.getSize()).intersects( diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeader.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeader.java index 66633a9f6d83..dc3c222572be 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeader.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeader.java @@ -49,7 +49,6 @@ import javax.swing.plaf.PanelUI; import java.awt.*; import java.awt.event.*; import java.awt.image.BufferedImage; -import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.List; @@ -74,7 +73,7 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS private final DefaultActionGroup myActionGroup = new DefaultActionGroup(); private List myVisibleActions = ContainerUtil.newArrayListWithCapacity(2); - public ToolWindowHeader(final ToolWindowImpl toolWindow, @NotNull WindowInfoImpl info, @NotNull final Producer gearProducer) { + ToolWindowHeader(final ToolWindowImpl toolWindow, @NotNull WindowInfoImpl info, @NotNull final Producer gearProducer) { setLayout(new BorderLayout()); myToolWindow = toolWindow; @@ -89,7 +88,7 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS Component c = getComponent(0); Dimension size = c.getPreferredSize(); - if (size.width < (r.width - insets.left - insets.right)) { + if (size.width < r.width - insets.left - insets.right) { c.setBounds(insets.left, insets.top, size.width, r.height - insets.top - insets.bottom); } else { c.setBounds(insets.left, insets.top, r.width - insets.left - insets.right, r.height - insets.top - insets.bottom); @@ -170,6 +169,7 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS myButtonPanel = eastPanel; westPanel.addMouseListener(new PopupHandler() { + @Override public void invokePopup(final Component comp, final int x, final int y) { toolWindow.getContentUI().showContextMenu(comp, x, y, toolWindow.getPopupGroup(), toolWindow.getContentManager().getSelectedContent()); } @@ -182,6 +182,7 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS }); addMouseListener(new MouseAdapter() { + @Override public void mouseReleased(final MouseEvent e) { if (!e.isPopupTrigger()) { if (UIUtil.isCloseClick(e, MouseEvent.MOUSE_RELEASED)) { @@ -227,7 +228,7 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS @Override public void mouseReleased(final MouseEvent e) { Runnable runnable = - () -> ToolWindowHeader.this.dispatchEvent(SwingUtilities.convertMouseEvent(e.getComponent(), e, ToolWindowHeader.this)); + () -> dispatchEvent(SwingUtilities.convertMouseEvent(e.getComponent(), e, ToolWindowHeader.this)); //noinspection SSBasedInspection SwingUtilities.invokeLater(runnable); } @@ -253,7 +254,7 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS myInfo = null; } - public void setAdditionalTitleActions(AnAction[] actions) { + void setAdditionalTitleActions(AnAction[] actions) { myActionGroup.removeAll(); myActionGroup.addAll(actions); myUpdater.updateActions(false, true); @@ -300,7 +301,7 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS if (anchor == ToolWindowAnchor.BOTTOM) { return AllIcons.General.HideDownPart; } - else if (anchor == ToolWindowAnchor.RIGHT) { + if (anchor == ToolWindowAnchor.RIGHT) { return AllIcons.General.HideRightPart; } @@ -312,7 +313,7 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS if (anchor == ToolWindowAnchor.BOTTOM) { return AllIcons.General.HideDown; } - else if (anchor == ToolWindowAnchor.RIGHT) { + if (anchor == ToolWindowAnchor.RIGHT) { return AllIcons.General.HideRight; } @@ -324,7 +325,7 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS if (anchor == ToolWindowAnchor.BOTTOM) { return AllIcons.General.HideDownPartHover; } - else if (anchor == ToolWindowAnchor.RIGHT) { + if (anchor == ToolWindowAnchor.RIGHT) { return AllIcons.General.HideRightPartHover; } @@ -336,7 +337,7 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS if (anchor == ToolWindowAnchor.BOTTOM) { return AllIcons.General.HideDownHover; } - else if (anchor == ToolWindowAnchor.RIGHT) { + if (anchor == ToolWindowAnchor.RIGHT) { return AllIcons.General.HideRightHover; } @@ -419,7 +420,7 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS protected abstract void sideHidden(); - protected abstract void toolWindowTypeChanged(ToolWindowType type); + protected abstract void toolWindowTypeChanged(@NotNull ToolWindowType type); @Override public Dimension getPreferredSize() { @@ -468,18 +469,15 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS setIcon(getActiveIcon(), getInactiveIcon() == null ? getActiveIcon() : getInactiveIcon(), getActiveHoveredIcon()); - PropertyChangeListener listener = new PropertyChangeListener() { - @Override - public void propertyChange(PropertyChangeEvent evt) { - if (myAlternativeAction == null) return; - if ("ancestor".equals(evt.getPropertyName())) { - if (evt.getNewValue() == null) { - AltStateManager.getInstance().removeListener(ActionButton.this); - switchAlternativeAction(false); - } - else { - AltStateManager.getInstance().addListener(ActionButton.this); - } + PropertyChangeListener listener = evt -> { + if (myAlternativeAction == null) return; + if ("ancestor".equals(evt.getPropertyName())) { + if (evt.getNewValue() == null) { + AltStateManager.getInstance().removeListener(this); + switchAlternativeAction(false); + } + else { + AltStateManager.getInstance().addListener(this); } } }; @@ -487,7 +485,7 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS addPropertyChangeListener(listener); } - public void updateTooltip() { + void updateTooltip() { myButton.setToolTipText(getToolTipTextByAction(myCurrentAction)); } @@ -533,6 +531,7 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS this(action, activeIcon, activeIcon); } + @Override public void actionPerformed(final ActionEvent e) { AnAction action = myAlternativeAction != null && BitUtil.isSet(e.getModifiers(), InputEvent.ALT_MASK) ? myAlternativeAction : myAction; @@ -557,6 +556,7 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS myButton.setIcons(active, inactive, hovered); } + @Override public void setToolTipText(final String text) { myButton.setToolTipText(text); } @@ -588,15 +588,17 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS } private abstract class HideSideAction extends AnAction implements DumbAware { - @NonNls public static final String HIDE_ACTIVE_SIDE_WINDOW_ACTION_ID = ToolWindowHeader.HIDE_ACTIVE_SIDE_WINDOW_ACTION_ID; + @NonNls static final String HIDE_ACTIVE_SIDE_WINDOW_ACTION_ID = ToolWindowHeader.HIDE_ACTIVE_SIDE_WINDOW_ACTION_ID; public HideSideAction() { copyFrom(ActionManager.getInstance().getAction(HIDE_ACTIVE_SIDE_WINDOW_ACTION_ID)); getTemplatePresentation().setText(UIBundle.message("tool.window.hideSide.action.name")); } + @Override public abstract void actionPerformed(@NotNull final AnActionEvent e); + @Override public final void update(@NotNull final AnActionEvent event) { final Presentation presentation = event.getPresentation(); presentation.setEnabled(myInfo.isVisible()); @@ -604,13 +606,14 @@ public abstract class ToolWindowHeader extends JPanel implements Disposable, UIS } private abstract class HideAction extends AnAction implements DumbAware { - @NonNls public static final String HIDE_ACTIVE_WINDOW_ACTION_ID = ToolWindowHeader.HIDE_ACTIVE_WINDOW_ACTION_ID; + @NonNls static final String HIDE_ACTIVE_WINDOW_ACTION_ID = ToolWindowHeader.HIDE_ACTIVE_WINDOW_ACTION_ID; public HideAction() { copyFrom(ActionManager.getInstance().getAction(HIDE_ACTIVE_WINDOW_ACTION_ID)); getTemplatePresentation().setText(UIBundle.message("tool.window.hide.action.name")); } + @Override public final void update(@NotNull final AnActionEvent event) { final Presentation presentation = event.getPresentation(); presentation.setEnabled(myInfo.isVisible()); diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeadlessManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeadlessManagerImpl.java index 3c89e2642939..29f8cbeae9ca 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeadlessManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeadlessManagerImpl.java @@ -53,9 +53,9 @@ import java.beans.PropertyChangeListener; import java.util.*; import java.util.List; -@SuppressWarnings({"ConstantConditions"}) +@SuppressWarnings("ConstantConditions") public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx { - private final Map myToolWindows = new HashMap(); + private final Map myToolWindows = new HashMap<>(); private final Project myProject; public ToolWindowHeadlessManagerImpl(Project project) { @@ -75,12 +75,7 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx { MockToolWindow tw = new MockToolWindow(myProject); myToolWindows.put(id, tw); if (parentDisposable != null) { - Disposer.register(parentDisposable, new Disposable() { - @Override - public void dispose() { - unregisterToolWindow(id); - } - }); + Disposer.register(parentDisposable, () -> unregisterToolWindow(id)); } return tw; } @@ -90,7 +85,7 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx { public ToolWindow registerToolWindow(@NotNull String id, @NotNull JComponent component, @NotNull ToolWindowAnchor anchor, - Disposable parentDisposable, + @NotNull Disposable parentDisposable, boolean canWorkInDumbMode) { return doRegisterToolWindow(id, parentDisposable); } @@ -106,7 +101,7 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx { public ToolWindow registerToolWindow(@NotNull String id, @NotNull JComponent component, @NotNull ToolWindowAnchor anchor, - Disposable parentDisposable, + @NotNull Disposable parentDisposable, boolean canWorkInDumbMode, boolean canCloseContents) { return doRegisterToolWindow(id, parentDisposable); @@ -139,7 +134,7 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx { @NotNull @Override public ToolWindow registerToolWindow(@NotNull final String id, final boolean canCloseContent, @NotNull final ToolWindowAnchor anchor, - final Disposable parentDisposable, final boolean dumbAware) { + @NotNull final Disposable parentDisposable, final boolean dumbAware) { return doRegisterToolWindow(id, parentDisposable); } @@ -148,7 +143,7 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx { public ToolWindow registerToolWindow(@NotNull String id, boolean canCloseContent, @NotNull ToolWindowAnchor anchor, - Disposable parentDisposable, + @NotNull Disposable parentDisposable, boolean canWorkInDumbMode, boolean secondary) { return doRegisterToolWindow(id, parentDisposable); @@ -222,16 +217,16 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx { } @Override - public void addToolWindowManagerListener(@NotNull ToolWindowManagerListener l) { + public void addToolWindowManagerListener(@NotNull ToolWindowManagerListener listener) { } @Override - public void addToolWindowManagerListener(@NotNull ToolWindowManagerListener l, @NotNull Disposable parentDisposable) { + public void addToolWindowManagerListener(@NotNull ToolWindowManagerListener listener, @NotNull Disposable parentDisposable) { } @Override - public void removeToolWindowManagerListener(@NotNull ToolWindowManagerListener l) { + public void removeToolWindowManagerListener(@NotNull ToolWindowManagerListener listener) { } @Override @@ -270,9 +265,10 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx { public void hideToolWindow(@NotNull final String id, final boolean hideSide) { } + @NotNull @Override public List getIdsOn(@NotNull final ToolWindowAnchor anchor) { - return new ArrayList(); + return new ArrayList<>(); } public static class MockToolWindow implements ToolWindowEx { @@ -330,7 +326,7 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx { } @Override - public void setAnchor(ToolWindowAnchor anchor, @Nullable Runnable runnable) { + public void setAnchor(@NotNull ToolWindowAnchor anchor, @Nullable Runnable runnable) { } @Override @@ -367,7 +363,7 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx { } @Override - public void setType(ToolWindowType type, @Nullable Runnable runnable) { + public void setType(@NotNull ToolWindowType type, @Nullable Runnable runnable) { } @Override @@ -500,7 +496,7 @@ public class ToolWindowHeadlessManagerImpl extends ToolWindowManagerEx { private static class MockContentManager implements ContentManager { private final EventDispatcher myDispatcher = EventDispatcher.create(ContentManagerListener.class); - private final List myContents = new ArrayList(); + private final List myContents = new ArrayList<>(); private Content mySelected; @NotNull diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowImpl.java index d58f6ce9a646..c97831818eec 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowImpl.java @@ -60,11 +60,11 @@ import java.util.Set; * @author Vladimir Kondratyev */ public final class ToolWindowImpl implements ToolWindowEx { - private final PropertyChangeSupport myChangeSupport; + private final PropertyChangeSupport myChangeSupport = new PropertyChangeSupport(this); private final ToolWindowManagerImpl myToolWindowManager; private final String myId; private final JComponent myComponent; - private boolean myAvailable; + private boolean myAvailable = true; private final ContentManager myContentManager; private Icon myIcon; private String myStripeTitle; @@ -74,18 +74,18 @@ public final class ToolWindowImpl implements ToolWindowEx { private InternalDecorator myDecorator; - private boolean myHideOnEmptyContent = false; + private boolean myHideOnEmptyContent; private boolean myPlaceholderMode; private ToolWindowFactory myContentFactory; - private static Set FORWARD_TRAVERSAL_KEYSTROKES = new HashSet(Arrays.asList( - new KeyStroke[] { + private static final Set FORWARD_TRAVERSAL_KEYSTROKES = new HashSet<>(Arrays.asList( + new KeyStroke[]{ KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0) } )); - private static Set BACKWARD_TRAVERSAL_KEYSTROKES = new HashSet(Arrays.asList( - new KeyStroke[] { + private static final Set BACKWARD_TRAVERSAL_KEYSTROKES = new HashSet<>(Arrays.asList( + new KeyStroke[]{ KeyStroke.getKeyStroke(KeyEvent.VK_TAB, InputEvent.SHIFT_DOWN_MASK) } )); @@ -102,16 +102,13 @@ public final class ToolWindowImpl implements ToolWindowEx { private static final Logger LOG = Logger.getInstance(ToolWindowImpl.class); - ToolWindowImpl(final ToolWindowManagerImpl toolWindowManager, final String id, boolean canCloseContent, @Nullable final JComponent component) { + ToolWindowImpl(@NotNull ToolWindowManagerImpl toolWindowManager, @NotNull String id, boolean canCloseContent, @Nullable final JComponent component) { myToolWindowManager = toolWindowManager; - myChangeSupport = new PropertyChangeSupport(this); myId = id; - myAvailable = true; final ContentFactory contentFactory = ServiceManager.getService(ContentFactory.class); myContentUI = new ToolWindowContentUi(this); - myContentManager = - contentFactory.createContentManager(myContentUI, canCloseContent, toolWindowManager.getProject()); + myContentManager = contentFactory.createContentManager(myContentUI, canCloseContent, toolWindowManager.getProject()); if (component != null) { final Content content = contentFactory.createContent(component, "", false); @@ -224,7 +221,7 @@ public final class ToolWindowImpl implements ToolWindowEx { public ActionCallback getReady(@NotNull final Object requestor) { final ActionCallback result = new ActionCallback(); myShowing.getReady(this).doWhenDone(() -> { - ArrayList cmd = new ArrayList(); + ArrayList cmd = new ArrayList<>(); cmd.add(new FinalizableCommand(null) { @Override public void run() { @@ -268,7 +265,7 @@ public final class ToolWindowImpl implements ToolWindowEx { } @Override - public final void setAnchor(final ToolWindowAnchor anchor, @Nullable final Runnable runnable) { + public final void setAnchor(@NotNull final ToolWindowAnchor anchor, @Nullable final Runnable runnable) { ApplicationManager.getApplication().assertIsDispatchThread(); myToolWindowManager.setToolWindowAnchor(myId, anchor); if (runnable != null) { @@ -330,7 +327,7 @@ public final class ToolWindowImpl implements ToolWindowEx { } @Override - public final void setType(final ToolWindowType type, @Nullable final Runnable runnable) { + public final void setType(@NotNull final ToolWindowType type, @Nullable final Runnable runnable) { ApplicationManager.getApplication().assertIsDispatchThread(); myToolWindowManager.setToolWindowType(myId, type); if (runnable != null) { @@ -416,6 +413,7 @@ public final class ToolWindowImpl implements ToolWindowEx { //return getSelectedContent().getIcon(); } + @NotNull public final String getId() { return myId; } @@ -531,11 +529,11 @@ public final class ToolWindowImpl implements ToolWindowEx { return myContentManager.isDisposed(); } - public boolean isPlaceholderMode() { + boolean isPlaceholderMode() { return myPlaceholderMode; } - public void setPlaceholderMode(final boolean placeholderMode) { + void setPlaceholderMode(final boolean placeholderMode) { myPlaceholderMode = placeholderMode; } @@ -546,7 +544,7 @@ public final class ToolWindowImpl implements ToolWindowEx { } @NotNull - public ActionCallback setActivation(@NotNull ActionCallback activation) { + ActionCallback setActivation(@NotNull ActionCallback activation) { if (!myActivation.isProcessed() && !myActivation.equals(activation)) { myActivation.setRejected(); } 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 977407222522..1fcbb33e3af1 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 @@ -95,26 +95,26 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements private final Project myProject; private final WindowManagerEx myWindowManager; private final EventDispatcher myDispatcher = EventDispatcher.create(ToolWindowManagerListener.class); - private final DesktopLayout myLayout; - private final Map myId2InternalDecorator; - private final Map myId2FloatingDecorator; - private final Map myId2WindowedDecorator; - private final Map myId2StripeButton; - private final Map myId2FocusWatcher; + private final DesktopLayout myLayout = new DesktopLayout(); + private final Map myId2InternalDecorator = new HashMap<>(); + private final Map myId2FloatingDecorator = new HashMap<>(); + private final Map myId2WindowedDecorator = new HashMap<>(); + private final Map myId2StripeButton = new HashMap<>(); + private final Map myId2FocusWatcher = new HashMap<>(); private final Set myDumbAwareIds = Collections.synchronizedSet(ContainerUtil.newTroveSet()); - private final EditorComponentFocusWatcher myEditorComponentFocusWatcher; - private final MyToolWindowPropertyChangeListener myToolWindowPropertyChangeListener; - private final InternalDecoratorListener myInternalDecoratorListener; + private final EditorComponentFocusWatcher myEditorComponentFocusWatcher = new EditorComponentFocusWatcher(); + private final MyToolWindowPropertyChangeListener myToolWindowPropertyChangeListener = new MyToolWindowPropertyChangeListener(); + private final InternalDecoratorListener myInternalDecoratorListener = new MyInternalDecoratorListener(); private boolean myEditorWasActive; - private final ActiveStack myActiveStack; - private final SideStack mySideStack; + private final ActiveStack myActiveStack = new ActiveStack(); + private final SideStack mySideStack = new SideStack(); private ToolWindowsPane myToolWindowsPane; private IdeFrameImpl myFrame; - private DesktopLayout myLayoutToRestoreLater = null; + private DesktopLayout myLayoutToRestoreLater; @NonNls private static final String EDITOR_ELEMENT = "editor"; @NonNls private static final String ACTIVE_ATTR_VALUE = "active"; @NonNls private static final String FRAME_ELEMENT = "frame"; @@ -127,8 +127,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements private final FileEditorManager myFileEditorManager; private final LafManager myLafManager; - private final Map myWindow2Balloon = new HashMap(); - private Pair myMaximizedToolwindowSize = null; + private final Map myWindow2Balloon = new HashMap<>(); private KeyState myCurrentState = KeyState.waiting; private final Alarm myWaiterForSecondPress = new Alarm(); @@ -139,7 +138,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements }; private final PropertyChangeListener myFocusListener; - public boolean isToolWindowRegistered(String id) { + boolean isToolWindowRegistered(@NotNull String id) { return myLayout.isToolWindowRegistered(id); } @@ -148,7 +147,6 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements } private final Alarm myUpdateHeadersAlarm = new Alarm(); - private final Runnable myUpdateHeadersRunnable = () -> updateToolWindowHeaders(); /** * invoked by reflection @@ -182,22 +180,8 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements }, project); } - myLayout = new DesktopLayout(); myLayout.copyFrom(windowManagerEx.getLayout()); - myId2InternalDecorator = new HashMap(); - myId2FloatingDecorator = new HashMap(); - myId2WindowedDecorator = new HashMap(); - myId2StripeButton = new HashMap(); - myId2FocusWatcher = new HashMap(); - - myEditorComponentFocusWatcher = new EditorComponentFocusWatcher(); - myToolWindowPropertyChangeListener = new MyToolWindowPropertyChangeListener(); - myInternalDecoratorListener = new MyInternalDecoratorListener(); - - myActiveStack = new ActiveStack(); - mySideStack = new SideStack(); - project.getMessageBus().connect().subscribe(FileEditorManagerListener.FILE_EDITOR_MANAGER, new FileEditorManagerListener() { @Override public void fileOpened(@NotNull FileEditorManager source, @NotNull VirtualFile file) { @@ -220,13 +204,10 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements } }); - myFocusListener = new PropertyChangeListener() { - @Override - public void propertyChange(PropertyChangeEvent evt) { - if ("focusOwner".equals(evt.getPropertyName())) { - myUpdateHeadersAlarm.cancelAllRequests(); - myUpdateHeadersAlarm.addRequest(myUpdateHeadersRunnable, 50); - } + myFocusListener = evt -> { + if ("focusOwner".equals(evt.getPropertyName())) { + myUpdateHeadersAlarm.cancelAllRequests(); + myUpdateHeadersAlarm.addRequest(this::updateToolWindowHeaders, 50); } }; KeyboardFocusManager.getCurrentKeyboardFocusManager().addPropertyChangeListener(myFocusListener); @@ -253,7 +234,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements }); } - public boolean dispatchKeyEvent(KeyEvent e) { + public boolean dispatchKeyEvent(@NotNull KeyEvent e) { if (e.getKeyCode() != KeyEvent.VK_CONTROL && e.getKeyCode() != KeyEvent.VK_ALT && e.getKeyCode() != KeyEvent.VK_SHIFT && @@ -299,8 +280,9 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements return false; } - public static Set getActivateToolWindowVKs() { - if (ApplicationManager.getApplication() == null) return new HashSet(); + @NotNull + private static Set getActivateToolWindowVKs() { + if (ApplicationManager.getApplication() == null) return new HashSet<>(); Keymap keymap = KeymapManager.getInstance().getActiveKeymap(); Shortcut[] baseShortcut = keymap.getShortcuts("ActivateProjectToolWindow"); @@ -373,7 +355,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements @Override public void disposeComponent() { - for (String id : new ArrayList(myId2StripeButton.keySet())) { + for (String id : new ArrayList<>(myId2StripeButton.keySet())) { unregisterToolWindow(id); } @@ -390,21 +372,17 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements UIManager.addPropertyChangeListener(uiManagerPropertyListener); myLafManager.addLafManagerListener(lafManagerListener); - Disposer.register(myProject, new Disposable() { - @Override - public void dispose() { - UIManager.removePropertyChangeListener(uiManagerPropertyListener); - myLafManager.removeLafManagerListener(lafManagerListener); - } + Disposer.register(myProject, () -> { + UIManager.removePropertyChangeListener(uiManagerPropertyListener); + myLafManager.removeLafManagerListener(lafManagerListener); }); myFrame = myWindowManager.allocateFrame(myProject); LOG.assertTrue(myFrame != null); - final ArrayList commandsList = new ArrayList(); - myToolWindowsPane = new ToolWindowsPane(myFrame, this); Disposer.register(myProject, myToolWindowsPane); ((IdeRootPane)myFrame.getRootPane()).setToolWindowsPane(myToolWindowsPane); + List commandsList = new ArrayList<>(); appendUpdateToolWindowsPaneCmd(commandsList); myFrame.setTitle(FrameTitleBuilder.getInstance().getProjectTitle(myProject)); @@ -432,13 +410,10 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements }; myProject.getMessageBus().connect().subscribe(DumbService.DUMB_MODE, dumbModeListener); - StartupManager.getInstance(myProject).registerPostStartupActivity(new DumbAwareRunnable() { - @Override - public void run() { - registerToolWindowsFromBeans(); - if (DumbService.getInstance(myProject).isDumb()) { - disableStripeButtons(); - } + StartupManager.getInstance(myProject).registerPostStartupActivity((DumbAwareRunnable)() -> { + registerToolWindowsFromBeans(); + if (DumbService.getInstance(myProject).isDumb()) { + disableStripeButtons(); } }); @@ -446,7 +421,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements if (e instanceof KeyEvent) { dispatchKeyEvent((KeyEvent)e); } - if (e instanceof WindowEvent && (e.getID() == WindowEvent.WINDOW_LOST_FOCUS) && e.getSource() == myFrame) { + if (e instanceof WindowEvent && e.getID() == WindowEvent.WINDOW_LOST_FOCUS && e.getSource() == myFrame) { resetHoldState(); } return false; @@ -467,7 +442,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements } } - private JComponent createEditorComponent(Project project) { + private static JComponent createEditorComponent(@NotNull Project project) { return FrameEditorComponentProvider.EP.getExtensions()[0].createEditorComponent(project); } @@ -542,19 +517,16 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements WindowInfoImpl info = getInfo(bean.id); if (!info.isSplit() && bean.secondary && !info.wasRead()) { - toolWindow.setSplitMode(bean.secondary, null); + toolWindow.setSplitMode(true, null); } final ActionCallback activation = toolWindow.setActivation(new ActionCallback()); - final DumbAwareRunnable runnable = new DumbAwareRunnable() { - @Override - public void run() { - if (toolWindow.isDisposed()) return; + final DumbAwareRunnable runnable = () -> { + if (toolWindow.isDisposed()) return; - toolWindow.ensureContentInitialized(); - activation.setDone(); - } + toolWindow.ensureContentInitialized(); + activation.setDone(); }; if (ApplicationManager.getApplication().isUnitTestMode()) { runnable.run(); @@ -566,7 +538,6 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements @Override public void projectClosed() { - final ArrayList commandsList = new ArrayList(); final String[] ids = getToolWindowIds(); // Remove ToolWindowsPane @@ -574,6 +545,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements ((IdeRootPane)myFrame.getRootPane()).setToolWindowsPane(null); myWindowManager.releaseFrame(myFrame); } + List commandsList = new ArrayList<>(); appendUpdateToolWindowsPaneCmd(commandsList); // Hide all tool windows @@ -591,18 +563,18 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements } @Override - public void addToolWindowManagerListener(@NotNull ToolWindowManagerListener l) { - myDispatcher.addListener(l); + public void addToolWindowManagerListener(@NotNull ToolWindowManagerListener listener) { + myDispatcher.addListener(listener); } @Override - public void addToolWindowManagerListener(@NotNull ToolWindowManagerListener l, @NotNull Disposable parentDisposable) { - myDispatcher.addListener(l, parentDisposable); + public void addToolWindowManagerListener(@NotNull ToolWindowManagerListener listener, @NotNull Disposable parentDisposable) { + myDispatcher.addListener(listener, parentDisposable); } @Override - public void removeToolWindowManagerListener(@NotNull ToolWindowManagerListener l) { - myDispatcher.removeListener(l); + public void removeToolWindowManagerListener(@NotNull ToolWindowManagerListener listener) { + myDispatcher.removeListener(listener); } /** @@ -641,7 +613,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements final ExpirableRunnable runnable = new ExpirableRunnable.ForProject(myProject) { @Override public void run() { - final ArrayList commandList = new ArrayList(); + List commandList = new ArrayList<>(); activateEditorComponentImpl(commandList, forced); execute(commandList); } @@ -669,15 +641,14 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements } } - private void activateEditorComponentImpl(List commandList, final boolean forced) { + private void activateEditorComponentImpl(@NotNull List commandList, final boolean forced) { final String active = getActiveToolWindowId(); // Now we have to request focus into most recent focused editor appendRequestFocusInEditorComponentCmd(commandList, forced).doWhenDone(() -> { - final ArrayList commandList12 = new ArrayList(); - if (LOG.isDebugEnabled()) { LOG.debug("editor activated"); } + List commandList12 = new ArrayList<>(); deactivateWindows(null, commandList12); myActiveStack.clear(); @@ -688,9 +659,9 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements @NotNull @Override public ActionCallback run() { - final ArrayList commandList1 = new ArrayList(); + List commandList1 = new ArrayList<>(); - final WindowInfoImpl toReactivate = getInfo(active); + final WindowInfoImpl toReactivate = active == null ? null : getInfo(active); final boolean reactivateLastActive = toReactivate != null && !isToHideOnDeactivation(toReactivate); deactivateWindows(reactivateLastActive ? active : null, commandList1); execute(commandList1); @@ -714,7 +685,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements }); } - private void deactivateWindows( @Nullable String idToIgnore, final List commandList) { + private void deactivateWindows(@Nullable String idToIgnore, @NotNull List commandList) { final WindowInfoImpl[] infos = myLayout.getInfos(); for (final WindowInfoImpl info : infos) { if (idToIgnore != null && idToIgnore.equals(info.getId())) { @@ -736,11 +707,10 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements * * @param dirtyMode if true then all UI operations are performed in "dirty" mode. * It means that UI isn't validated and repainted just after each add/remove operation. - * @see ToolWindowManagerImpl#prepareForActivation */ - private void showAndActivate(final String id, + private void showAndActivate(@NotNull String id, final boolean dirtyMode, - List commandsList, + @NotNull List commandsList, boolean autoFocusContents, boolean forcedFocusRequest) { if (!getToolWindow(id).isAvailable()) { @@ -766,7 +736,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements } } - void activateToolWindow(final String id, boolean forced, boolean autoFocusContents) { + void activateToolWindow(@NotNull String id, boolean forced, boolean autoFocusContents) { if (LOG.isDebugEnabled()) { LOG.debug("enter: activateToolWindow(" + id + ")"); } @@ -776,13 +746,13 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements return; } - final ArrayList commandList = new ArrayList(); + List commandList = new ArrayList<>(); activateToolWindowImpl(id, commandList, forced, autoFocusContents); execute(commandList); } - private void activateToolWindowImpl(final String id, - List commandList, + private void activateToolWindowImpl(@NotNull String id, + @NotNull List commandList, boolean forced, boolean autoFocusContents) { if (!FocusManagerImpl.getInstance().isUnforcedRequestAllowed() && !forced) return; @@ -810,7 +780,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements * * @throws IllegalStateException if tool window isn't installed. */ - private void checkId(final String id) { + private void checkId(@NotNull String id) { if (!myLayout.isToolWindowRegistered(id)) { throw new IllegalStateException("window with id=\"" + id + "\" isn't registered"); } @@ -822,7 +792,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements * @param id id of the tool window to be deactivated. * @param shouldHide if true then also hides specified tool window. */ - private void deactivateToolWindowImpl(final String id, final boolean shouldHide, final List commandsList) { + private void deactivateToolWindowImpl(@NotNull String id, final boolean shouldHide, @NotNull List commandsList) { if (LOG.isDebugEnabled()) { LOG.debug("enter: deactivateToolWindowImpl(" + id + "," + shouldHide + ")"); } @@ -887,37 +857,38 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements /** * @return floating decorator for the tool window with specified ID. */ - private FloatingDecorator getFloatingDecorator(final String id) { + private FloatingDecorator getFloatingDecorator(@NotNull String id) { return myId2FloatingDecorator.get(id); } /** * @return windowed decorator for the tool window with specified ID. */ - private WindowedDecorator getWindowedDecorator(String id) { + private WindowedDecorator getWindowedDecorator(@NotNull String id) { return myId2WindowedDecorator.get(id); } /** * @return internal decorator for the tool window with specified ID. */ - private InternalDecorator getInternalDecorator(final String id) { + private InternalDecorator getInternalDecorator(@NotNull String id) { return myId2InternalDecorator.get(id); } /** * @return tool button for the window with specified ID. */ - private StripeButton getStripeButton(final String id) { + private StripeButton getStripeButton(@NotNull String id) { return myId2StripeButton.get(id); } /** * @return info for the tool window with specified ID. */ - private WindowInfoImpl getInfo(final String id) { + private WindowInfoImpl getInfo(@NotNull String id) { return myLayout.getInfo(id, true); } @Override + @NotNull public List getIdsOn(@NotNull final ToolWindowAnchor anchor) { return myLayout.getVisibleIdsOn(anchor, this); } @@ -931,12 +902,12 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements return decorator != null ? decorator.getToolWindow() : null; } - void showToolWindow(final String id) { + void showToolWindow(@NotNull String id) { if (LOG.isDebugEnabled()) { LOG.debug("enter: showToolWindow(" + id + ")"); } ApplicationManager.getApplication().assertIsDispatchThread(); - final ArrayList commandList = new ArrayList(); + List commandList = new ArrayList<>(); showToolWindowImpl(id, false, commandList); execute(commandList); } @@ -946,12 +917,12 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements hideToolWindow(id, hideSide, true); } - public void hideToolWindow(final String id, final boolean hideSide, final boolean moveFocus) { + public void hideToolWindow(@NotNull String id, final boolean hideSide, final boolean moveFocus) { ApplicationManager.getApplication().assertIsDispatchThread(); checkId(id); final WindowInfoImpl info = getInfo(id); if (!info.isVisible()) return; - final ArrayList commandList = new ArrayList(); + List commandList = new ArrayList<>(); final boolean wasActive = info.isActive(); // hide and deactivate @@ -1024,7 +995,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements } else { final String toBeActivatedId = myActiveStack.pop(); - if (toBeActivatedId != null && (getInfo(toBeActivatedId).isVisible() || isStackEnabled())) { + if (getInfo(toBeActivatedId).isVisible() || isStackEnabled()) { activateToolWindowImpl(toBeActivatedId, commandList, false, true); } else { @@ -1044,7 +1015,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements /** * @param dirtyMode if true then all UI operations are performed in dirty mode. */ - private void showToolWindowImpl(final String id, final boolean dirtyMode, final List commandsList) { + private void showToolWindowImpl(@NotNull String id, final boolean dirtyMode, @NotNull List commandsList) { final WindowInfoImpl toBeShownInfo = getInfo(id); if (toBeShownInfo.isVisible() || !getToolWindow(id).isAvailable()) { return; @@ -1184,7 +1155,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements public ToolWindow registerToolWindow(@NotNull String id, boolean canCloseContent, @NotNull ToolWindowAnchor anchor, - Disposable parentDisposable, + @NotNull Disposable parentDisposable, boolean canWorkInDumbMode, boolean secondary) { ToolWindow window = registerToolWindow(id, null, anchor, secondary, canCloseContent, canWorkInDumbMode); @@ -1226,7 +1197,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements final StripeButton button = new StripeButton(decorator, myToolWindowsPane); myId2StripeButton.put(id, button); - List commandsList = new ArrayList(); + List commandsList = new ArrayList<>(); appendAddButtonCmd(button, info, commandsList); if (canWorkInDumbMode) { @@ -1260,12 +1231,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements @NotNull private ToolWindow registerDisposable(@NotNull final String id, @NotNull final Disposable parentDisposable, @NotNull ToolWindow window) { - Disposer.register(parentDisposable, new Disposable() { - @Override - public void dispose() { - unregisterToolWindow(id); - } - }); + Disposer.register(parentDisposable, () -> unregisterToolWindow(id)); return window; } @@ -1284,7 +1250,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements // Save recent appearance of tool window myLayout.unregister(id); // Remove decorator and tool button from the screen - final ArrayList commandsList = new ArrayList(); + List commandsList = new ArrayList<>(); if (info.isVisible()) { info.setVisible(false); if (info.isFloating()) { @@ -1338,7 +1304,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements @Override public void setLayout(@NotNull final DesktopLayout layout) { ApplicationManager.getApplication().assertIsDispatchThread(); - final ArrayList commandList = new ArrayList(); + List commandList = new ArrayList<>(); // hide tool window that are invisible in new layout final WindowInfoImpl[] currentInfos = myLayout.getInfos(); for (final WindowInfoImpl currentInfo : currentInfos) { @@ -1400,7 +1366,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements @Override public void invokeLater(@NotNull final Runnable runnable) { - List commandList = new ArrayList(); + List commandList = new ArrayList<>(); commandList.add(new InvokeLaterCmd(runnable, myWindowManager.getCommandProcessor())); execute(commandList); } @@ -1480,19 +1446,16 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements }); listenerWrapper.myBalloon = balloon; myWindow2Balloon.put(toolWindowId, balloon); - Disposer.register(balloon, new Disposable() { - @Override - public void dispose() { - window.setPlaceholderMode(false); - stripe.updatePresentation(); - stripe.revalidate(); - stripe.repaint(); - myWindow2Balloon.remove(toolWindowId); - } + Disposer.register(balloon, () -> { + window.setPlaceholderMode(false); + stripe.updatePresentation(); + stripe.revalidate(); + stripe.repaint(); + myWindow2Balloon.remove(toolWindowId); }); Disposer.register(getProject(), balloon); - execute(new ArrayList(Arrays.asList(new FinalizableCommand(null) { + execute(new ArrayList<>(Collections.singletonList(new FinalizableCommand(null) { @Override public void run() { final StripeButton button = stripe.getButtonFor(toolWindowId); @@ -1550,7 +1513,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements }; if (!button.isValid()) { - SwingUtilities.invokeLater(() -> show.run()); + SwingUtilities.invokeLater(show); } else { show.run(); @@ -1573,27 +1536,28 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements return splitters != null; } - ToolWindowAnchor getToolWindowAnchor(final String id) { + @NotNull + ToolWindowAnchor getToolWindowAnchor(@NotNull String id) { checkId(id); return getInfo(id).getAnchor(); } - void setToolWindowAnchor(final String id, final ToolWindowAnchor anchor) { + void setToolWindowAnchor(@NotNull String id, @NotNull ToolWindowAnchor anchor) { ApplicationManager.getApplication().assertIsDispatchThread(); setToolWindowAnchor(id, anchor, -1); } - void setToolWindowAnchor(final String id, final ToolWindowAnchor anchor, final int order) { + private void setToolWindowAnchor(@NotNull String id, @NotNull ToolWindowAnchor anchor, final int order) { ApplicationManager.getApplication().assertIsDispatchThread(); - final ArrayList commandList = new ArrayList(); + List commandList = new ArrayList<>(); setToolWindowAnchorImpl(id, anchor, order, commandList); execute(commandList); } - private void setToolWindowAnchorImpl(final String id, - final ToolWindowAnchor anchor, + private void setToolWindowAnchorImpl(@NotNull String id, + @NotNull ToolWindowAnchor anchor, final int order, - final ArrayList commandsList) { + @NotNull List commandsList) { checkId(id); final WindowInfoImpl info = getInfo(id); if (anchor == info.getAnchor() && order == info.getOrder()) { @@ -1630,42 +1594,42 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements } } - boolean isSplitMode(String id) { + boolean isSplitMode(@NotNull String id) { ApplicationManager.getApplication().assertIsDispatchThread(); checkId(id); return getInfo(id).isSplit(); } @NotNull - ToolWindowContentUiType getContentUiType(String id) { + ToolWindowContentUiType getContentUiType(@NotNull String id) { ApplicationManager.getApplication().assertIsDispatchThread(); checkId(id); return getInfo(id).getContentUiType(); } - void setSideTool(String id, boolean isSide) { - final ArrayList commandList = new ArrayList(); + void setSideTool(@NotNull String id, boolean isSide) { + List commandList = new ArrayList<>(); setSplitModeImpl(id, isSide, commandList); execute(commandList); } - public void setContentUiType(String id, @NotNull ToolWindowContentUiType type) { - final ArrayList commandList = new ArrayList(); + void setContentUiType(@NotNull String id, @NotNull ToolWindowContentUiType type) { checkId(id); WindowInfoImpl info = getInfo(id); info.setContentUiType(type); + List commandList = new ArrayList<>(); appendApplyWindowInfoCmd(info, commandList); execute(commandList); } - void setSideToolAndAnchor(String id, ToolWindowAnchor anchor, int order, boolean isSide) { - final ArrayList commandList = new ArrayList(); + void setSideToolAndAnchor(@NotNull String id, @NotNull ToolWindowAnchor anchor, int order, boolean isSide) { setToolWindowAnchor(id, anchor, order); + List commandList = new ArrayList<>(); setSplitModeImpl(id, isSide, commandList); execute(commandList); } - private void setSplitModeImpl(final String id, final boolean isSplit, final ArrayList commandList) { + private void setSplitModeImpl(@NotNull String id, final boolean isSplit, @NotNull List commandList) { checkId(id); final WindowInfoImpl info = getInfo(id); if (isSplit == info.isSplit()) { @@ -1688,18 +1652,18 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements commandList.add(myToolWindowsPane.createUpdateButtonPositionCmd(id, myWindowManager.getCommandProcessor())); } - ToolWindowType getToolWindowInternalType(final String id) { + ToolWindowType getToolWindowInternalType(@NotNull String id) { ApplicationManager.getApplication().assertIsDispatchThread(); checkId(id); return getInfo(id).getInternalType(); } - ToolWindowType getToolWindowType(final String id) { + ToolWindowType getToolWindowType(@NotNull String id) { checkId(id); return getInfo(id).getType(); } - private void fireToolWindowRegistered(final String id) { + private void fireToolWindowRegistered(@NotNull String id) { myDispatcher.getMulticaster().toolWindowRegistered(id); } @@ -1707,31 +1671,31 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements myDispatcher.getMulticaster().stateChanged(); } - boolean isToolWindowActive(final String id) { + boolean isToolWindowActive(@NotNull String id) { ApplicationManager.getApplication().assertIsDispatchThread(); checkId(id); return getInfo(id).isActive(); } - boolean isToolWindowAutoHide(final String id) { + boolean isToolWindowAutoHide(@NotNull String id) { ApplicationManager.getApplication().assertIsDispatchThread(); checkId(id); return getInfo(id).isAutoHide(); } - boolean isToolWindowVisible(final String id) { + boolean isToolWindowVisible(@NotNull String id) { checkId(id); return getInfo(id).isVisible(); } - void setToolWindowAutoHide(final String id, final boolean autoHide) { + void setToolWindowAutoHide(@NotNull String id, final boolean autoHide) { ApplicationManager.getApplication().assertIsDispatchThread(); - final ArrayList commandList = new ArrayList(); + List commandList = new ArrayList<>(); setToolWindowAutoHideImpl(id, autoHide, commandList); execute(commandList); } - private void setToolWindowAutoHideImpl(final String id, final boolean autoHide, final ArrayList commandsList) { + private void setToolWindowAutoHideImpl(@NotNull String id, final boolean autoHide, @NotNull List commandsList) { checkId(id); final WindowInfoImpl info = getInfo(id); if (info.isAutoHide() == autoHide) { @@ -1745,14 +1709,14 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements } } - void setToolWindowType(final String id, final ToolWindowType type) { + void setToolWindowType(@NotNull String id, @NotNull ToolWindowType type) { ApplicationManager.getApplication().assertIsDispatchThread(); - final ArrayList commandList = new ArrayList(); + List commandList = new ArrayList<>(); setToolWindowTypeImpl(id, type, commandList); execute(commandList); } - private void setToolWindowTypeImpl(final String id, final ToolWindowType type, final ArrayList commandsList) { + private void setToolWindowTypeImpl(@NotNull String id, @NotNull ToolWindowType type, @NotNull List commandsList) { checkId(id); final WindowInfoImpl info = getInfo(id); if (info.getType() == type) { @@ -1782,7 +1746,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements } } - private void appendApplyWindowInfoCmd(final WindowInfoImpl info, final List commandsList) { + private void appendApplyWindowInfoCmd(@NotNull WindowInfoImpl info, @NotNull List commandsList) { final StripeButton button = getStripeButton(info.getId()); final InternalDecorator decorator = getInternalDecorator(info.getId()); commandsList.add(new ApplyWindowInfoCmd(info, button, decorator, myWindowManager.getCommandProcessor())); @@ -1791,10 +1755,10 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements /** * @see ToolWindowsPane#createAddDecoratorCmd */ - private void appendAddDecoratorCmd(final InternalDecorator decorator, - final WindowInfoImpl info, + private void appendAddDecoratorCmd(@NotNull InternalDecorator decorator, + @NotNull WindowInfoImpl info, final boolean dirtyMode, - final List commandsList) { + @NotNull List commandsList) { final CommandProcessor commandProcessor = myWindowManager.getCommandProcessor(); final FinalizableCommand command = myToolWindowsPane.createAddDecoratorCmd(decorator, info, dirtyMode, commandProcessor); commandsList.add(command); @@ -1803,17 +1767,17 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements /** * @see ToolWindowsPane#createRemoveDecoratorCmd */ - private void appendRemoveDecoratorCmd(final String id, final boolean dirtyMode, final List commandsList) { + private void appendRemoveDecoratorCmd(@NotNull String id, final boolean dirtyMode, @NotNull List commandsList) { final FinalizableCommand command = myToolWindowsPane.createRemoveDecoratorCmd(id, dirtyMode, myWindowManager.getCommandProcessor()); commandsList.add(command); } - private void appendRemoveFloatingDecoratorCmd(final WindowInfoImpl info, final List commandsList) { + private void appendRemoveFloatingDecoratorCmd(@NotNull WindowInfoImpl info, @NotNull List commandsList) { final RemoveFloatingDecoratorCmd command = new RemoveFloatingDecoratorCmd(info); commandsList.add(command); } - private void appendRemoveWindowedDecoratorCmd(final WindowInfoImpl info, final List commandsList) { + private void appendRemoveWindowedDecoratorCmd(@NotNull WindowInfoImpl info, @NotNull List commandsList) { final RemoveWindowedDecoratorCmd command = new RemoveWindowedDecoratorCmd(info); commandsList.add(command); } @@ -1821,7 +1785,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements /** * @see ToolWindowsPane#createAddButtonCmd */ - private void appendAddButtonCmd(final StripeButton button, final WindowInfoImpl info, final List commandsList) { + private void appendAddButtonCmd(final StripeButton button, @NotNull WindowInfoImpl info, @NotNull List commandsList) { final Comparator comparator = myLayout.comparator(info.getAnchor()); final CommandProcessor commandProcessor = myWindowManager.getCommandProcessor(); final FinalizableCommand command = myToolWindowsPane.createAddButtonCmd(button, info, comparator, commandProcessor); @@ -1831,7 +1795,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements /** * @see ToolWindowsPane#createAddButtonCmd */ - private void appendRemoveButtonCmd(final String id, final List commandsList) { + private void appendRemoveButtonCmd(@NotNull String id, @NotNull List commandsList) { final FinalizableCommand command = myToolWindowsPane.createRemoveButtonCmd(id, myWindowManager.getCommandProcessor()); commandsList.add(command); } @@ -1855,7 +1819,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements /** * @see ToolWindowsPane#createSetEditorComponentCmd */ - public void appendSetEditorComponentCmd(@Nullable final JComponent component, final List commandsList) { + private void appendSetEditorComponentCmd(@Nullable final JComponent component, @NotNull List commandsList) { final CommandProcessor commandProcessor = myWindowManager.getCommandProcessor(); final FinalizableCommand command = myToolWindowsPane.createSetEditorComponentCmd(component, commandProcessor); commandsList.add(command); @@ -1885,36 +1849,6 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements return splitters != null ? splitters : fem.getSplitters(); } - /** - * @return true if tool window with the specified id - * is floating and has modal showing child dialog. Such windows should not be closed - * when auto-hide windows are gone. - */ - private boolean hasModalChild(final WindowInfoImpl info) { - if (!info.isVisible() || !info.isFloating()) { - return false; - } - final FloatingDecorator decorator = getFloatingDecorator(info.getId()); - LOG.assertTrue(decorator != null); - return isModalOrHasModalChild(decorator); - } - - private static boolean isModalOrHasModalChild(final Window window) { - if (window instanceof Dialog) { - final Dialog dialog = (Dialog)window; - if (dialog.isModal() && dialog.isShowing()) { - return true; - } - final Window[] ownedWindows = dialog.getOwnedWindows(); - for (int i = ownedWindows.length - 1; i >= 0; i--) { - if (isModalOrHasModalChild(ownedWindows[i])) { - return true; - } - } - } - return false; - } - @Override public void clearSideStack() { mySideStack.clear(); @@ -2000,14 +1934,14 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements } } - public void setDefaultContentUiType(ToolWindowImpl toolWindow, @NotNull ToolWindowContentUiType type) { + void setDefaultContentUiType(@NotNull ToolWindowImpl toolWindow, @NotNull ToolWindowContentUiType type) { final WindowInfoImpl info = getInfo(toolWindow.getId()); if (info.wasRead()) return; toolWindow.setContentUiType(type, null); } - public void stretchWidth(ToolWindowImpl toolWindow, int value) { + void stretchWidth(@NotNull ToolWindowImpl toolWindow, int value) { myToolWindowsPane.stretchWidth(toolWindow, value); } @@ -2021,7 +1955,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements myToolWindowsPane.setMaximized(wnd, maximized); } - public void stretchHeight(ToolWindowImpl toolWindow, int value) { + void stretchHeight(ToolWindowImpl toolWindow, int value) { myToolWindowsPane.stretchHeight(toolWindow, value); } @@ -2029,7 +1963,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements private Balloon myBalloon; private final HyperlinkListener myListener; - public BalloonHyperlinkListener(HyperlinkListener listener) { + BalloonHyperlinkListener(HyperlinkListener listener) { myListener = listener; } @@ -2054,7 +1988,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements /** * Creates floating decorator for specified internal decorator. */ - private AddFloatingDecoratorCmd(final InternalDecorator decorator, final WindowInfoImpl info) { + private AddFloatingDecoratorCmd(@NotNull InternalDecorator decorator, @NotNull WindowInfoImpl info) { super(myWindowManager.getCommandProcessor()); myFloatingDecorator = new FloatingDecorator(myFrame, info.copy(), decorator); myId2FloatingDecorator.put(info.getId(), myFloatingDecorator); @@ -2093,7 +2027,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements private final class RemoveFloatingDecoratorCmd extends FinalizableCommand { private final FloatingDecorator myFloatingDecorator; - private RemoveFloatingDecoratorCmd(final WindowInfoImpl info) { + private RemoveFloatingDecoratorCmd(@NotNull WindowInfoImpl info) { super(myWindowManager.getCommandProcessor()); myFloatingDecorator = getFloatingDecorator(info.getId()); myId2FloatingDecorator.remove(info.getId()); @@ -2126,7 +2060,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements /** * Creates windowed decorator for specified internal decorator. */ - private AddWindowedDecoratorCmd(final InternalDecorator decorator, final WindowInfoImpl info) { + private AddWindowedDecoratorCmd(@NotNull InternalDecorator decorator, @NotNull WindowInfoImpl info) { super(myWindowManager.getCommandProcessor()); myWindowedDecorator = new WindowedDecorator(myProject, info.copy(), decorator); Window window = myWindowedDecorator.getFrame(); @@ -2146,12 +2080,9 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements window.setLocationRelativeTo(myFrame); } myId2WindowedDecorator.put(info.getId(), myWindowedDecorator); - myWindowedDecorator.addDisposable(new Disposable() { - @Override - public void dispose() { - if (myId2WindowedDecorator.get(info.getId()) != null) { - hideToolWindow(info.getId(), false); - } + myWindowedDecorator.addDisposable(() -> { + if (myId2WindowedDecorator.get(info.getId()) != null) { + hideToolWindow(info.getId(), false); } }); } @@ -2183,7 +2114,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements private final class RemoveWindowedDecoratorCmd extends FinalizableCommand { private final WindowedDecorator myWindowedDecorator; - private RemoveWindowedDecoratorCmd(final WindowInfoImpl info) { + private RemoveWindowedDecoratorCmd(@NotNull WindowInfoImpl info) { super(myWindowManager.getCommandProcessor()); myWindowedDecorator = getWindowedDecorator(info.getId()); myId2WindowedDecorator.remove(info.getId()); @@ -2255,8 +2186,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements private final String myId; private final ToolWindowImpl myToolWindow; - - private ToolWindowFocusWatcher(final ToolWindowImpl toolWindow) { + private ToolWindowFocusWatcher(@NotNull ToolWindowImpl toolWindow) { myId = toolWindow.getId(); install(toolWindow.getComponent()); myToolWindow = toolWindow; @@ -2317,27 +2247,27 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements */ private final class MyInternalDecoratorListener implements InternalDecoratorListener { @Override - public void anchorChanged(final InternalDecorator source, final ToolWindowAnchor anchor) { + public void anchorChanged(@NotNull final InternalDecorator source, @NotNull final ToolWindowAnchor anchor) { setToolWindowAnchor(source.getToolWindow().getId(), anchor); } @Override - public void autoHideChanged(final InternalDecorator source, final boolean autoHide) { + public void autoHideChanged(@NotNull final InternalDecorator source, final boolean autoHide) { setToolWindowAutoHide(source.getToolWindow().getId(), autoHide); } @Override - public void hidden(final InternalDecorator source) { + public void hidden(@NotNull final InternalDecorator source) { hideToolWindow(source.getToolWindow().getId(), false); } @Override - public void hiddenSide(final InternalDecorator source) { + public void hiddenSide(@NotNull final InternalDecorator source) { hideToolWindow(source.getToolWindow().getId(), true); } @Override - public void contentUiTypeChanges(InternalDecorator source, @NotNull ToolWindowContentUiType type) { + public void contentUiTypeChanges(@NotNull InternalDecorator source, @NotNull ToolWindowContentUiType type) { setContentUiType(source.getToolWindow().getId(), type); } @@ -2346,13 +2276,12 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements * tool window depending on decoration type. */ @Override - public void resized(final InternalDecorator source) { + public void resized(@NotNull final InternalDecorator source) { if (!source.isShowing()) { return; // do not recalculate the tool window size if it is not yet shown (and, therefore, has 0,0,0,0 bounds) } final WindowInfoImpl info = getInfo(source.getToolWindow().getId()); - InternalDecorator another = null; if (info.isFloating()) { final Window owner = SwingUtilities.getWindowAncestor(source); if (owner != null) { @@ -2367,6 +2296,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements } else { // docked and sliding windows ToolWindowAnchor anchor = info.getAnchor(); + InternalDecorator another = null; if (source.getParent() instanceof Splitter) { float sizeInSplit = anchor.isSplitVertically() ? source.getHeight() : source.getWidth(); Splitter splitter = (Splitter)source.getParent(); @@ -2399,21 +2329,22 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements } @Override - public void activated(final InternalDecorator source) { + public void activated(@NotNull final InternalDecorator source) { activateToolWindow(source.getToolWindow().getId(), true, true); } @Override - public void typeChanged(final InternalDecorator source, final ToolWindowType type) { + public void typeChanged(@NotNull final InternalDecorator source, @NotNull final ToolWindowType type) { setToolWindowType(source.getToolWindow().getId(), type); } @Override - public void sideStatusChanged(final InternalDecorator source, final boolean isSideTool) { + public void sideStatusChanged(@NotNull final InternalDecorator source, final boolean isSideTool) { setSideTool(source.getToolWindow().getId(), isSideTool); } - public void visibleStripeButtonChanged(InternalDecorator source, boolean visible) { + @Override + public void visibleStripeButtonChanged(@NotNull InternalDecorator source, boolean visible) { setShowStripeButton(source.getToolWindow().getId(), visible); } } @@ -2546,11 +2477,12 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements return IdeFocusManager.getInstance(myProject).dispatch(e); } + @NotNull public Expirable getTimestamp(boolean trackOnlyForcedCommands) { return IdeFocusManager.getInstance(myProject).getTimestamp(trackOnlyForcedCommands); } - public void setShowStripeButton(String id, boolean visibleOnPanel) { + void setShowStripeButton(@NotNull String id, boolean visibleOnPanel) { checkId(id); WindowInfoImpl info = getInfo(id); if (visibleOnPanel == info.isShowStripeButton()) { @@ -2559,12 +2491,12 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements info.setShowStripeButton(visibleOnPanel); UsageTrigger.trigger("StripeButton[" + id + "]." + (visibleOnPanel ? "shown" : "hidden")); - final ArrayList commandList = new ArrayList(); + List commandList = new ArrayList<>(); appendApplyWindowInfoCmd(info, commandList); execute(commandList); } - public boolean isShowStripeButton(String id) { + boolean isShowStripeButton(@NotNull String id) { WindowInfoImpl info = getInfo(id); return info == null || info.isShowStripeButton(); } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowsPane.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowsPane.java index 2f626df5477e..86a45f418e26 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowsPane.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowsPane.java @@ -42,10 +42,10 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; import java.awt.image.BufferedImage; -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; +import java.lang.ref.Reference; import java.util.ArrayList; import java.util.Comparator; +import java.util.List; /** * This panel contains all tool stripes and JLayeredPanle at the center area. All tool windows are @@ -59,12 +59,12 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi private final IdeFrameImpl myFrame; - private final HashMap myId2Button; - private final HashMap myId2Decorator; - private final HashMap myButton2Info; - private final HashMap myDecorator2Info; - private final HashMap myId2SplitProportion; - private Pair myMaximizedProportion = null; + private final HashMap myId2Button = new HashMap<>(); + private final HashMap myId2Decorator = new HashMap<>(); + private final HashMap myButton2Info = new HashMap<>(); + private final HashMap myDecorator2Info = new HashMap<>(); + private final HashMap myId2SplitProportion = new HashMap<>(); + private Pair myMaximizedProportion; /** * This panel is the layered pane where all sliding tool windows are located. The DEFAULT * layer contains splitters. The PALETTE layer contains all sliding tool windows. @@ -84,29 +84,23 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi private final Stripe myBottomStripe; private final Stripe myTopStripe; - private final ArrayList myStripes = new ArrayList(); + private final List myStripes = new ArrayList<>(); private final ToolWindowManagerImpl myManager; private boolean myStripesOverlayed; private final Disposable myDisposable = Disposer.newDisposable(); - private boolean myWidescreen = false; - private boolean myLeftHorizontalSplit = false; - private boolean myRightHorizontalSplit = false; + private boolean myWidescreen; + private boolean myLeftHorizontalSplit; + private boolean myRightHorizontalSplit; - ToolWindowsPane(final IdeFrameImpl frame, ToolWindowManagerImpl manager) { + ToolWindowsPane(@NotNull IdeFrameImpl frame, @NotNull ToolWindowManagerImpl manager) { myManager = manager; setOpaque(false); myFrame = frame; - myId2Button = new HashMap(); - myId2Decorator = new HashMap(); - myButton2Info = new HashMap(); - myDecorator2Info = new HashMap(); - myId2SplitProportion = new HashMap(); // Splitters - myVerticalSplitter = new ThreeComponentsSplitter(true); Disposer.register(this, myVerticalSplitter); myVerticalSplitter.setDividerWidth(0); @@ -193,6 +187,7 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi /** * Invoked when enclosed frame is being shown. */ + @Override public final void addNotify() { super.addNotify(); } @@ -200,6 +195,7 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi /** * Invoked when enclosed frame is being disposed. */ + @Override public final void removeNotify() { if (ScreenUtil.isStandardAddRemoveNotify(this)) { Disposer.dispose(myDisposable); @@ -211,6 +207,7 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi return myFrame.getProject(); } + @Override public final void uiSettingsChanged(final UISettings source) { updateToolStripesVisibility(); updateLayout(); @@ -225,10 +222,11 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi * @param comparator which is used to sort buttons within the stripe. * @param finishCallBack invoked when the command is completed. */ + @NotNull final FinalizableCommand createAddButtonCmd(final StripeButton button, - final WindowInfoImpl info, - final Comparator comparator, - final Runnable finishCallBack) { + @NotNull WindowInfoImpl info, + @NotNull Comparator comparator, + @NotNull Runnable finishCallBack) { final WindowInfoImpl copiedInfo = info.copy(); myId2Button.put(copiedInfo.getId(), button); myButton2Info.put(button, copiedInfo); @@ -242,12 +240,11 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi * @param dirtyMode if true then JRootPane will not be validated and repainted after adding * the decorator. Moreover in this (dirty) mode animation doesn't work. */ - final FinalizableCommand createAddDecoratorCmd( - final InternalDecorator decorator, - final WindowInfoImpl info, - final boolean dirtyMode, - final Runnable finishCallBack - ) { + @NotNull + final FinalizableCommand createAddDecoratorCmd(@NotNull InternalDecorator decorator, + @NotNull WindowInfoImpl info, + final boolean dirtyMode, + @NotNull Runnable finishCallBack) { final WindowInfoImpl copiedInfo = info.copy(); final String id = copiedInfo.getId(); @@ -276,10 +273,11 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi * * @param id ID of the button to be removed. */ - final FinalizableCommand createRemoveButtonCmd(final String id, final Runnable finishCallBack) { + @NotNull + final FinalizableCommand createRemoveButtonCmd(@NotNull String id, @NotNull Runnable finishCallBack) { final StripeButton button = getButtonById(id); final WindowInfoImpl info = getButtonInfoById(id); - // + myButton2Info.remove(button); myId2Button.remove(id); return new RemoveToolStripeButtonCmd(button, info, finishCallBack); @@ -291,7 +289,8 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi * @param dirtyMode if true then JRootPane will not be validated and repainted after removing * the decorator. Moreover in this (dirty) mode animation doesn't work. */ - final FinalizableCommand createRemoveDecoratorCmd(final String id, final boolean dirtyMode, final Runnable finishCallBack) { + @NotNull + final FinalizableCommand createRemoveDecoratorCmd(@NotNull String id, final boolean dirtyMode, @NotNull Runnable finishCallBack) { final Component decorator = getDecoratorById(id); final WindowInfoImpl info = getDecoratorInfoById(id); @@ -321,14 +320,17 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi * * @param component component to be set. */ - final FinalizableCommand createSetEditorComponentCmd(final JComponent component, final Runnable finishCallBack) { + @NotNull + final FinalizableCommand createSetEditorComponentCmd(final JComponent component, @NotNull Runnable finishCallBack) { return new SetEditorComponentCmd(component, finishCallBack); } - final FinalizableCommand createUpdateButtonPositionCmd(String id, final Runnable finishCallback) { + @NotNull + final FinalizableCommand createUpdateButtonPositionCmd(@NotNull String id, @NotNull Runnable finishCallback) { return new UpdateButtonPositionCmd(id, finishCallback); } + @NotNull public final JComponent getMyLayeredPane() { return myLayeredPane; } @@ -361,7 +363,7 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi /** * Sets (docks) specified component to the specified anchor. */ - private void setComponent(final JComponent component, final ToolWindowAnchor anchor, final float weight) { + private void setComponent(final JComponent component, @NotNull ToolWindowAnchor anchor, final float weight) { if (ToolWindowAnchor.TOP == anchor) { myVerticalSplitter.setFirstComponent(component); myVerticalSplitter.setFirstSize((int)(myLayeredPane.getHeight() * weight)); @@ -383,7 +385,7 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi } } - private JComponent getComponentAt(ToolWindowAnchor anchor) { + private JComponent getComponentAt(@NotNull ToolWindowAnchor anchor) { if (ToolWindowAnchor.TOP == anchor) { return myVerticalSplitter.getFirstComponent(); } @@ -402,12 +404,12 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi } } - private float getPreferredSplitProportion(String id, float defaultValue) { + private float getPreferredSplitProportion(@NotNull String id, float defaultValue) { Float f = myId2SplitProportion.get(id); - return (f == null ? defaultValue : f); + return f == null ? defaultValue : f; } - private WindowInfoImpl getDockedInfoAt(ToolWindowAnchor anchor, boolean side) { + private WindowInfoImpl getDockedInfoAt(@NotNull ToolWindowAnchor anchor, boolean side) { for (WindowInfoImpl info : myDecorator2Info.values()) { if (info.isVisible() && info.isDocked() && info.getAnchor() == anchor && side == info.isSplit()) { return info; @@ -417,7 +419,7 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi return null; } - public void setDocumentComponent(final JComponent component) { + private void setDocumentComponent(final JComponent component) { (myWidescreen ? myVerticalSplitter : myHorizontalSplitter).setInnerComponent(component); } @@ -464,13 +466,13 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi if (ToolWindowAnchor.TOP == anchor) { return myTopStripe; } - else if (ToolWindowAnchor.BOTTOM == anchor) { + if (ToolWindowAnchor.BOTTOM == anchor) { return myBottomStripe; } - else if (ToolWindowAnchor.LEFT == anchor) { + if (ToolWindowAnchor.LEFT == anchor) { return myLeftStripe; } - else if (ToolWindowAnchor.RIGHT == anchor) { + if (ToolWindowAnchor.RIGHT == anchor) { return myRightStripe; } @@ -478,7 +480,7 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi } @Nullable - Stripe getStripeFor(final Rectangle screenRec, Stripe preferred) { + Stripe getStripeFor(@NotNull Rectangle screenRec, @NotNull Stripe preferred) { if (preferred.containsScreen(screenRec)) { return myStripes.get(myStripes.indexOf(preferred)); } @@ -504,15 +506,15 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi } } - public void stretchWidth(ToolWindow wnd, int value) { + void stretchWidth(@NotNull ToolWindow wnd, int value) { stretch(wnd, value); } - public void stretchHeight(ToolWindow wnd, int value) { + void stretchHeight(@NotNull ToolWindow wnd, int value) { stretch(wnd, value); } - private void stretch(ToolWindow wnd, int value) { + private void stretch(@NotNull ToolWindow wnd, int value) { Pair pair = findResizerAndComponent(wnd); if (pair == null) return; @@ -520,13 +522,13 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi int actualSize = (vertical ? pair.second.getHeight() : pair.second.getWidth()) + value; boolean first = wnd.getAnchor() == ToolWindowAnchor.LEFT || wnd.getAnchor() == ToolWindowAnchor.TOP; int maxValue = vertical ? myVerticalSplitter.getMaxSize(first) : myHorizontalSplitter.getMaxSize(first); - int minValue = vertical ? myVerticalSplitter.getMinSize(first) : myHorizontalSplitter.getMinSize(first);; + int minValue = vertical ? myVerticalSplitter.getMinSize(first) : myHorizontalSplitter.getMinSize(first); pair.first.setSize(Math.max(minValue, Math.min(maxValue, actualSize))); } @Nullable - private Pair findResizerAndComponent(ToolWindow wnd) { + private Pair findResizerAndComponent(@NotNull ToolWindow wnd) { if (!wnd.isVisible()) return null; Resizer resizer = null; @@ -620,7 +622,7 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi return myMaximizedProportion != null && myMaximizedProportion.first == wnd; } - public void setMaximized(@NotNull ToolWindow wnd, boolean maximized) { + void setMaximized(@NotNull ToolWindow wnd, boolean maximized) { Pair resizerAndComponent = findResizerAndComponent(wnd); if (resizerAndComponent == null) return; @@ -638,6 +640,7 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi } + @FunctionalInterface interface Resizer { void setSize(int size); @@ -645,25 +648,27 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi abstract class Splitter implements Resizer { ThreeComponentsSplitter mySplitter; - Splitter(ThreeComponentsSplitter splitter) { + Splitter(@NotNull ThreeComponentsSplitter splitter) { mySplitter = splitter; } static class FirstComponent extends Splitter { - FirstComponent(ThreeComponentsSplitter splitter) { + FirstComponent(@NotNull ThreeComponentsSplitter splitter) { super(splitter); } + @Override public void setSize(int size) { mySplitter.setFirstSize(size); } } static class LastComponent extends Splitter { - LastComponent(ThreeComponentsSplitter splitter) { + LastComponent(@NotNull ThreeComponentsSplitter splitter) { super(splitter); } + @Override public void setSize(int size) { mySplitter.setLastSize(size); } @@ -673,10 +678,11 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi abstract class LayeredPane implements Resizer { Component myComponent; - protected LayeredPane(Component component) { + LayeredPane(@NotNull Component component) { myComponent = component; } + @Override public final void setSize(int size) { _setSize(size); if (myComponent.getParent() instanceof JComponent) { @@ -690,20 +696,22 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi static class Left extends LayeredPane { - Left(Component component) { + Left(@NotNull Component component) { super(component); } + @Override public void _setSize(int size) { myComponent.setSize(size, myComponent.getHeight()); } } static class Right extends LayeredPane { - Right(Component component) { + Right(@NotNull Component component) { super(component); } + @Override public void _setSize(int size) { Rectangle bounds = myComponent.getBounds(); int delta = size - bounds.width; @@ -714,20 +722,22 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi } static class Top extends LayeredPane { - Top(Component component) { + Top(@NotNull Component component) { super(component); } + @Override public void _setSize(int size) { myComponent.setSize(myComponent.getWidth(), size); } } static class Bottom extends LayeredPane { - Bottom(Component component) { + Bottom(@NotNull Component component) { super(component); } + @Override public void _setSize(int size) { Rectangle bounds = myComponent.getBounds(); int delta = size - bounds.height; @@ -744,16 +754,17 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi private final WindowInfoImpl myInfo; private final boolean myDirtyMode; - public AddDockedComponentCmd(final JComponent component, - final WindowInfoImpl info, + public AddDockedComponentCmd(@NotNull JComponent component, + @NotNull WindowInfoImpl info, final boolean dirtyMode, - final Runnable finishCallBack) { + @NotNull Runnable finishCallBack) { super(finishCallBack); myComponent = component; myInfo = info; myDirtyMode = dirtyMode; } + @Override public final void run() { try { final ToolWindowAnchor anchor = myInfo.getAnchor(); @@ -774,17 +785,19 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi private final WindowInfoImpl myInfo; private final boolean myDirtyMode; - private AddAndSplitDockedComponentCmd(final JComponent newComponent, - final WindowInfoImpl info, final boolean dirtyMode, final Runnable finishCallBack) { + private AddAndSplitDockedComponentCmd(@NotNull JComponent newComponent, + @NotNull WindowInfoImpl info, + final boolean dirtyMode, + @NotNull Runnable finishCallBack) { super(finishCallBack); myNewComponent = newComponent; myInfo = info; myDirtyMode = dirtyMode; } + @Override public void run() { try { - float newWeight; final ToolWindowAnchor anchor = myInfo.getAnchor(); class MySplitter extends Splitter implements UISettingsListener { @Override @@ -801,28 +814,26 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi splitter.setOrientation(anchor.isSplitVertically()); if (!anchor.isHorizontal()) { splitter.setAllowSwitchOrientationByMouseClick(true); - splitter.addPropertyChangeListener(new PropertyChangeListener() { - @Override - public void propertyChange(PropertyChangeEvent evt) { - if (!Splitter.PROP_ORIENTATION.equals(evt.getPropertyName())) return; - boolean isSplitterHorizontalNow = !splitter.isVertical(); - UISettings settings = UISettings.getInstance(); - if (anchor == ToolWindowAnchor.LEFT) { - if (settings.LEFT_HORIZONTAL_SPLIT != isSplitterHorizontalNow) { - settings.LEFT_HORIZONTAL_SPLIT = isSplitterHorizontalNow; - settings.fireUISettingsChanged(); - } + splitter.addPropertyChangeListener(evt -> { + if (!Splitter.PROP_ORIENTATION.equals(evt.getPropertyName())) return; + boolean isSplitterHorizontalNow = !splitter.isVertical(); + UISettings settings = UISettings.getInstance(); + if (anchor == ToolWindowAnchor.LEFT) { + if (settings.LEFT_HORIZONTAL_SPLIT != isSplitterHorizontalNow) { + settings.LEFT_HORIZONTAL_SPLIT = isSplitterHorizontalNow; + settings.fireUISettingsChanged(); } - if (anchor == ToolWindowAnchor.RIGHT) { - if (settings.RIGHT_HORIZONTAL_SPLIT != isSplitterHorizontalNow) { - settings.RIGHT_HORIZONTAL_SPLIT = isSplitterHorizontalNow; - settings.fireUISettingsChanged(); - } + } + if (anchor == ToolWindowAnchor.RIGHT) { + if (settings.RIGHT_HORIZONTAL_SPLIT != isSplitterHorizontalNow) { + settings.RIGHT_HORIZONTAL_SPLIT = isSplitterHorizontalNow; + settings.fireUISettingsChanged(); } } }); } JComponent c = getComponentAt(anchor); + float newWeight; if (c instanceof InternalDecorator) { InternalDecorator oldComponent = (InternalDecorator)c; if (myInfo.isSplit()) { @@ -872,15 +883,16 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi private final WindowInfoImpl myInfo; private final boolean myDirtyMode; - public AddSlidingComponentCmd(final Component component, - final WindowInfoImpl info, + public AddSlidingComponentCmd(@NotNull Component component, + @NotNull WindowInfoImpl info, final boolean dirtyMode, - final Runnable finishCallBack) { + @NotNull Runnable finishCallBack) { super(finishCallBack); myComponent = component; myInfo = info; myDirtyMode = dirtyMode; } + @Override public final void run() { try { // Show component. @@ -946,15 +958,16 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi private final Comparator myComparator; public AddToolStripeButtonCmd(final StripeButton button, - final WindowInfoImpl info, - final Comparator comparator, - final Runnable finishCallBack) { + @NotNull WindowInfoImpl info, + @NotNull Comparator comparator, + @NotNull Runnable finishCallBack) { super(finishCallBack); myButton = button; myInfo = info; myComparator = comparator; } + @Override public final void run() { try { final ToolWindowAnchor anchor = myInfo.getAnchor(); @@ -986,12 +999,13 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi private final StripeButton myButton; private final WindowInfoImpl myInfo; - public RemoveToolStripeButtonCmd(final StripeButton button, final WindowInfoImpl info, final Runnable finishCallBack) { + public RemoveToolStripeButtonCmd(@NotNull StripeButton button, @NotNull WindowInfoImpl info, @NotNull Runnable finishCallBack) { super(finishCallBack); myButton = button; myInfo = info; } + @Override public final void run() { try { final ToolWindowAnchor anchor = myInfo.getAnchor(); @@ -1023,12 +1037,13 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi private final WindowInfoImpl myInfo; private final boolean myDirtyMode; - public RemoveDockedComponentCmd(final WindowInfoImpl info, final boolean dirtyMode, final Runnable finishCallBack) { + public RemoveDockedComponentCmd(@NotNull WindowInfoImpl info, final boolean dirtyMode, @NotNull Runnable finishCallBack) { super(finishCallBack); myInfo = info; myDirtyMode = dirtyMode; } + @Override public final void run() { try { setComponent(null, myInfo.getAnchor(), 0); @@ -1047,14 +1062,15 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi private final WindowInfoImpl myInfo; private final boolean myDirtyMode; - private RemoveSplitAndDockedComponentCmd(final WindowInfoImpl info, + private RemoveSplitAndDockedComponentCmd(@NotNull WindowInfoImpl info, boolean dirtyMode, - final Runnable finishCallBack) { + @NotNull Runnable finishCallBack) { super(finishCallBack); myInfo = info; myDirtyMode = dirtyMode; } + @Override public void run() { try { ToolWindowAnchor anchor = myInfo.getAnchor(); @@ -1086,12 +1102,13 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi private final WindowInfoImpl myInfo; private final boolean myDirtyMode; - public RemoveSlidingComponentCmd(Component component, WindowInfoImpl info, boolean dirtyMode, Runnable finishCallBack) { + public RemoveSlidingComponentCmd(Component component, @NotNull WindowInfoImpl info, boolean dirtyMode, @NotNull Runnable finishCallBack) { super(finishCallBack); myComponent = component; myInfo = info; myDirtyMode = dirtyMode; } + @Override public final void run() { try { final UISettings uiSettings = UISettings.getInstance(); @@ -1147,11 +1164,12 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi private final class SetEditorComponentCmd extends FinalizableCommand { private final JComponent myComponent; - public SetEditorComponentCmd(final JComponent component, final Runnable finishCallBack) { + public SetEditorComponentCmd(final JComponent component, @NotNull Runnable finishCallBack) { super(finishCallBack); myComponent = component; } + @Override public void run() { try { setDocumentComponent(myComponent); @@ -1167,11 +1185,12 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi private final class UpdateButtonPositionCmd extends FinalizableCommand { private final String myId; - private UpdateButtonPositionCmd(String id, final Runnable finishCallBack) { + private UpdateButtonPositionCmd(@NotNull String id, @NotNull Runnable finishCallBack) { super(finishCallBack); myId = id; } + @Override public void run() { try { StripeButton stripeButton = getButtonById(myId); @@ -1209,35 +1228,31 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi * These images are used to perform animated showing and hiding of components. * They are the member for performance reason. */ - private SoftReference myBottomImageRef; - private SoftReference myTopImageRef; + private Reference myBottomImageRef; + private Reference myTopImageRef; - public MyLayeredPane(final JComponent splitter) { - myBottomImageRef = new SoftReference(null); - myTopImageRef = new SoftReference(null); + public MyLayeredPane(@NotNull JComponent splitter) { setOpaque(false); add(splitter, JLayeredPane.DEFAULT_LAYER); } - public final Image getBottomImage() { - Pair> result = getImage(myBottomImageRef); + final Image getBottomImage() { + Pair> result = getImage(myBottomImageRef); myBottomImageRef = result.second; return result.first; } - public final Image getTopImage() { - Pair> result = getImage(myTopImageRef); + final Image getTopImage() { + Pair> result = getImage(myTopImageRef); myTopImageRef = result.second; return result.first; } - private Pair> getImage(SoftReference imageRef) { + @NotNull + private Pair> getImage(@Nullable Reference imageRef) { LOG.assertTrue(UISettings.getInstance().ANIMATE_WINDOWS); - BufferedImage image = imageRef.get(); - if ( - image == null || - image.getWidth(null) < getWidth() || image.getHeight(null) < getHeight() - ) { + BufferedImage image = SoftReference.dereference(imageRef); + if (image == null || image.getWidth(null) < getWidth() || image.getHeight(null) < getHeight()) { final int width = Math.max(Math.max(1, getWidth()), myFrame.getWidth()); final int height = Math.max(Math.max(1, getHeight()), myFrame.getHeight()); if (SystemInfo.isWindows) { @@ -1251,7 +1266,7 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi image = UIUtil.createImage(width, height, BufferedImage.TYPE_INT_RGB); } - imageRef = new SoftReference(image); + imageRef = new SoftReference<>(image); } return Pair.create(image, imageRef); } @@ -1259,6 +1274,7 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi /** * When component size becomes larger then bottom and top images should be enlarged. */ + @Override public void doLayout() { final int width = getWidth(); final int height = getHeight(); @@ -1295,7 +1311,7 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi } } - public final void setBoundsInPaletteLayer(final Component component, final ToolWindowAnchor anchor, float weight) { + final void setBoundsInPaletteLayer(@NotNull Component component, @NotNull ToolWindowAnchor anchor, float weight) { if (weight < .0f) { weight = WindowInfoImpl.DEFAULT_WEIGHT; } @@ -1322,7 +1338,7 @@ public final class ToolWindowsPane extends JBLayeredPane implements UISettingsLi } } - public void setStripesOverlayed(boolean stripesOverlayed) { + void setStripesOverlayed(boolean stripesOverlayed) { myStripesOverlayed = stripesOverlayed; updateToolStripesVisibility(); } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowInfoImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowInfoImpl.java index 22558914ce43..ff006a1156e2 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowInfoImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowInfoImpl.java @@ -32,16 +32,16 @@ public final class WindowInfoImpl implements Cloneable,JDOMExternalizable, Windo /** * XML tag. */ - @NonNls static final String TAG="window_info"; + @NonNls static final String TAG = "window_info"; /** * Default window weight. */ - static final float DEFAULT_WEIGHT= 0.33f; - static final float DEFAULT_SIDE_WEIGHT = 0.5f; + static final float DEFAULT_WEIGHT = 0.33f; + private static final float DEFAULT_SIDE_WEIGHT = 0.5f; private boolean myActive; @NotNull - private ToolWindowAnchor myAnchor; + private ToolWindowAnchor myAnchor = ToolWindowAnchor.LEFT; private boolean myAutoHide; /** * Bounds of window in "floating" mode. It equals to null if @@ -52,9 +52,9 @@ public final class WindowInfoImpl implements Cloneable,JDOMExternalizable, Windo private ToolWindowType myInternalType; private ToolWindowType myType; private boolean myVisible; - private boolean myShowStripeButton; - private float myWeight; - private float mySideWeight; + private boolean myShowStripeButton = true; + private float myWeight = DEFAULT_WEIGHT; + private float mySideWeight = DEFAULT_SIDE_WEIGHT; private boolean mySplitMode; @NotNull private ToolWindowContentUiType myContentUiType = ToolWindowContentUiType.TABBED; @@ -62,24 +62,24 @@ public final class WindowInfoImpl implements Cloneable,JDOMExternalizable, Windo * Defines order of tool window button inside the stripe. * The default value is -1. */ - private int myOrder; - @NonNls static final String ID_ATTR = "id"; - @NonNls static final String ACTIVE_ATTR = "active"; - @NonNls static final String ANCHOR_ATTR = "anchor"; - @NonNls static final String AUTOHIDE_ATTR = "auto_hide"; - @NonNls static final String INTERNAL_TYPE_ATTR = "internal_type"; - @NonNls static final String TYPE_ATTR = "type"; - @NonNls static final String VISIBLE_ATTR = "visible"; - @NonNls static final String WEIGHT_ATTR = "weight"; - @NonNls static final String SIDE_WEIGHT_ATTR = "sideWeight"; - @NonNls static final String ORDER_ATTR = "order"; - @NonNls static final String X_ATTR = "x"; - @NonNls static final String Y_ATTR = "y"; - @NonNls static final String WIDTH_ATTR = "width"; - @NonNls static final String HEIGHT_ATTR = "height"; - @NonNls static final String SIDE_TOOL_ATTR = "side_tool"; - @NonNls static final String CONTENT_UI_ATTR = "content_ui"; - @NonNls static final String SHOW_STRIPE_BUTTON = "show_stripe_button"; + private int myOrder = -1; + @NonNls private static final String ID_ATTR = "id"; + @NonNls private static final String ACTIVE_ATTR = "active"; + @NonNls private static final String ANCHOR_ATTR = "anchor"; + @NonNls private static final String AUTOHIDE_ATTR = "auto_hide"; + @NonNls private static final String INTERNAL_TYPE_ATTR = "internal_type"; + @NonNls private static final String TYPE_ATTR = "type"; + @NonNls private static final String VISIBLE_ATTR = "visible"; + @NonNls private static final String WEIGHT_ATTR = "weight"; + @NonNls private static final String SIDE_WEIGHT_ATTR = "sideWeight"; + @NonNls private static final String ORDER_ATTR = "order"; + @NonNls private static final String X_ATTR = "x"; + @NonNls private static final String Y_ATTR = "y"; + @NonNls private static final String WIDTH_ATTR = "width"; + @NonNls private static final String HEIGHT_ATTR = "height"; + @NonNls private static final String SIDE_TOOL_ATTR = "side_tool"; + @NonNls private static final String CONTENT_UI_ATTR = "content_ui"; + @NonNls private static final String SHOW_STRIPE_BUTTON = "show_stripe_button"; private boolean myWasRead; @@ -88,18 +88,8 @@ public final class WindowInfoImpl implements Cloneable,JDOMExternalizable, Windo * Creates WindowInfo for tool window with specified ID. */ WindowInfoImpl(@NotNull String id) { - myActive = false; - myAnchor = ToolWindowAnchor.LEFT; - myAutoHide = false; - myFloatingBounds = null; myId = id; setType(ToolWindowType.DOCKED); - myVisible = false; - myShowStripeButton = true; - myWeight = DEFAULT_WEIGHT; - mySideWeight = DEFAULT_SIDE_WEIGHT; - myOrder = -1; - mySplitMode = false; } /** @@ -122,7 +112,7 @@ public final class WindowInfoImpl implements Cloneable,JDOMExternalizable, Windo /** * Copies all data from the passed WindowInfo into itself. */ - void copyFrom(final WindowInfoImpl info){ + void copyFrom(@NotNull WindowInfoImpl info){ myActive = info.myActive; myAnchor = info.myAnchor; myAutoHide = info.myAutoHide; @@ -178,15 +168,16 @@ public final class WindowInfoImpl implements Cloneable,JDOMExternalizable, Windo * window can be in floating mode, but this method has sense if you want to know what type * tool window had when it was internal one. The method never returns null. */ + @NotNull ToolWindowType getInternalType(){ return myInternalType; } /** * @return current type of tool window. - * @see com.intellij.openapi.wm.ToolWindowType#DOCKED - * @see com.intellij.openapi.wm.ToolWindowType#FLOATING - * @see com.intellij.openapi.wm.ToolWindowType#SLIDING + * @see ToolWindowType#DOCKED + * @see ToolWindowType#FLOATING + * @see ToolWindowType#SLIDING */ @Override public ToolWindowType getType(){ @@ -248,11 +239,12 @@ public final class WindowInfoImpl implements Cloneable,JDOMExternalizable, Windo return myVisible; } + @Override public boolean isShowStripeButton() { return myShowStripeButton; } - public void setShowStripeButton(boolean showStripeButton) { + void setShowStripeButton(boolean showStripeButton) { myShowStripeButton = showStripeButton; } @@ -266,7 +258,7 @@ public final class WindowInfoImpl implements Cloneable,JDOMExternalizable, Windo } @Override - @SuppressWarnings({"EmptyCatchBlock"}) + @SuppressWarnings("EmptyCatchBlock") public void readExternal(final Element element) { myId = element.getAttributeValue(ID_ATTR); myWasRead = true; @@ -353,7 +345,7 @@ public final class WindowInfoImpl implements Cloneable,JDOMExternalizable, Windo setTypeAndCheck(type); } //Hardcoded to avoid single-usage-API - private void setTypeAndCheck(ToolWindowType type) { + private void setTypeAndCheck(@NotNull ToolWindowType type) { myType = ToolWindowId.PREVIEW == myId && type == ToolWindowType.DOCKED ? ToolWindowType.SLIDING : type; } @@ -420,7 +412,7 @@ public final class WindowInfoImpl implements Cloneable,JDOMExternalizable, Windo return myAnchor.hashCode()+myId.hashCode()+myType.hashCode()+myOrder; } - @SuppressWarnings({"HardCodedStringLiteral"}) + @SuppressWarnings("HardCodedStringLiteral") public String toString(){ return getClass().getName() + "[myId=" + myId + "; myVisible=" + myVisible @@ -439,7 +431,7 @@ public final class WindowInfoImpl implements Cloneable,JDOMExternalizable, Windo ']'; } - public boolean wasRead() { + boolean wasRead() { return myWasRead; } } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowedDecorator.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowedDecorator.java index 53e29a1a8749..0d1b997aff80 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowedDecorator.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowedDecorator.java @@ -15,14 +15,11 @@ */ package com.intellij.openapi.wm.impl; -import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.FrameWrapper; import org.jetbrains.annotations.NotNull; -public final class WindowedDecorator extends FrameWrapper { - private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.wm.impl.WindowedDecorator"); - +final class WindowedDecorator extends FrameWrapper { private final Project myProject; WindowedDecorator(@NotNull Project project, @NotNull WindowInfoImpl info, @NotNull InternalDecorator internalDecorator) { diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/commands/FinalizableCommand.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/commands/FinalizableCommand.java index 249391cc253f..b11387bdb1dd 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/commands/FinalizableCommand.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/commands/FinalizableCommand.java @@ -17,6 +17,7 @@ package com.intellij.openapi.wm.impl.commands; import com.intellij.openapi.util.Condition; import com.intellij.openapi.wm.ToolWindowManager; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; /** @@ -27,15 +28,15 @@ public abstract class FinalizableCommand implements Runnable{ protected ToolWindowManager myManager; - public FinalizableCommand(final Runnable finishCallBack){ - myFinishCallBack=finishCallBack; + public FinalizableCommand(Runnable finishCallBack){ + myFinishCallBack = finishCallBack; } public final void finish(){ myFinishCallBack.run(); } - public void beforeExecute(final ToolWindowManager toolWindowManager) { + public void beforeExecute(@NotNull ToolWindowManager toolWindowManager) { myManager = toolWindowManager; } diff --git a/platform/testFramework/src/com/intellij/mock/Mock.java b/platform/testFramework/src/com/intellij/mock/Mock.java index d6d960f5bd17..89a0106fff6a 100644 --- a/platform/testFramework/src/com/intellij/mock/Mock.java +++ b/platform/testFramework/src/com/intellij/mock/Mock.java @@ -562,7 +562,7 @@ public class Mock { public ToolWindow registerToolWindow(@NotNull String id, @NotNull JComponent component, @NotNull ToolWindowAnchor anchor, - Disposable parentDisposable, + @NotNull Disposable parentDisposable, boolean canWorkInDumbMode, boolean canCloseContents) { throw new RuntimeException(); } @@ -572,7 +572,7 @@ public class Mock { public ToolWindow registerToolWindow(@NotNull String id, @NotNull JComponent component, @NotNull ToolWindowAnchor anchor, - Disposable parentDisposable, + @NotNull Disposable parentDisposable, boolean canWorkInDumbMode) { throw new RuntimeException(); } @@ -592,7 +592,7 @@ public class Mock { @NotNull @Override public ToolWindow registerToolWindow(@NotNull final String id, final boolean canCloseContent, @NotNull final ToolWindowAnchor anchor, - final Disposable parentDisposable, final boolean dumbAware) { + @NotNull final Disposable parentDisposable, final boolean dumbAware) { throw new RuntimeException(); } @@ -601,7 +601,7 @@ public class Mock { public ToolWindow registerToolWindow(@NotNull String id, boolean canCloseContent, @NotNull ToolWindowAnchor anchor, - Disposable parentDisposable, + @NotNull Disposable parentDisposable, boolean canWorkInDumbMode, boolean secondary) { throw new RuntimeException(); diff --git a/platform/util/src/com/intellij/util/RetinaImage.java b/platform/util/src/com/intellij/util/RetinaImage.java index c9e0eda32c19..590b78241a4d 100644 --- a/platform/util/src/com/intellij/util/RetinaImage.java +++ b/platform/util/src/com/intellij/util/RetinaImage.java @@ -17,6 +17,7 @@ package com.intellij.util; import com.intellij.openapi.util.SystemInfo; import com.intellij.util.ui.UIUtil; +import org.jetbrains.annotations.NotNull; import java.awt.*; import java.awt.image.BufferedImage; @@ -50,6 +51,7 @@ public class RetinaImage { * @param observer the raw image observer * @return the Retina-aware wrapper */ + @NotNull public static Image createFrom(Image image, final int scale, ImageObserver observer) { int w = image.getWidth(observer); int h = image.getHeight(observer); @@ -65,11 +67,13 @@ public class RetinaImage { return hidpi; } + @NotNull public static BufferedImage create(final int width, int height, int type) { return create(null, width, height, type); } + @NotNull private static BufferedImage create(Image image, final int width, int height, int type) { if (SystemInfo.isAppleJvm) { return AppleHiDPIScaledImage.create(width, height, type); diff --git a/platform/util/src/com/intellij/util/ui/UIUtil.java b/platform/util/src/com/intellij/util/ui/UIUtil.java index a5ef76f881ef..ec24c55d3434 100644 --- a/platform/util/src/com/intellij/util/ui/UIUtil.java +++ b/platform/util/src/com/intellij/util/ui/UIUtil.java @@ -1779,6 +1779,7 @@ public class UIUtil { } } + @NotNull public static BufferedImage createImage(int width, int height, int type) { if (isRetina()) { return RetinaImage.create(width, height, type); @@ -1787,6 +1788,7 @@ public class UIUtil { return new BufferedImage(width, height, type); } + @NotNull public static BufferedImage createImageForGraphics(Graphics2D g, int width, int height, int type) { if (isRetina(g)) { return RetinaImage.create(width, height, type); From dc423dedc8b749464d8241fe76fdecbbed52b137 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Fri, 24 Jun 2016 12:06:29 +0300 Subject: [PATCH 055/107] cancel background VCS initialization on project close start --- .../vcs/impl/ProjectLevelVcsManagerImpl.java | 21 +++++++++++++++---- .../openapi/vcs/impl/VcsInitialization.java | 7 ++++++- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ProjectLevelVcsManagerImpl.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ProjectLevelVcsManagerImpl.java index b158bf52d26e..fc1252f72e40 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ProjectLevelVcsManagerImpl.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/ProjectLevelVcsManagerImpl.java @@ -33,6 +33,8 @@ import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; +import com.intellij.openapi.project.ProjectManager; +import com.intellij.openapi.project.ProjectManagerAdapter; import com.intellij.openapi.roots.FileIndexFacade; import com.intellij.openapi.util.*; import com.intellij.openapi.util.io.FileUtil; @@ -128,24 +130,35 @@ public class ProjectLevelVcsManagerImpl extends ProjectLevelVcsManagerEx impleme private final VcsFileListenerContextHelper myVcsFileListenerContextHelper; private final VcsAnnotationLocalChangesListenerImpl myAnnotationLocalChangesListener; - public ProjectLevelVcsManagerImpl(Project project, final FileStatusManager manager, MessageBus messageBus, - final FileIndexFacade excludedFileIndex) { + public ProjectLevelVcsManagerImpl(Project project, + final FileStatusManager manager, + MessageBus messageBus, + final FileIndexFacade excludedFileIndex, + ProjectManager projectManager, + DefaultVcsRootPolicy defaultVcsRootPolicy, + VcsFileListenerContextHelper vcsFileListenerContextHelper) { myProject = project; myMessageBus = messageBus; mySerialization = new ProjectLevelVcsManagerSerialization(); myOptionsAndConfirmations = new OptionsAndConfirmations(); - myDefaultVcsRootPolicy = DefaultVcsRootPolicy.getInstance(project); + myDefaultVcsRootPolicy = defaultVcsRootPolicy; myInitialization = new VcsInitialization(myProject); Disposer.register(project, myInitialization); // wait for the thread spawned in VcsInitialization to terminate + projectManager.addProjectManagerListener(project, new ProjectManagerAdapter() { + @Override + public void projectClosing(Project project) { + Disposer.dispose(myInitialization); + } + }); myMappings = new NewMappings(myProject, myMessageBus, this, manager); myMappingsToRoots = new MappingsToRoots(myMappings, myProject); myVcsHistoryCache = new VcsHistoryCache(); myContentRevisionCache = new ContentRevisionCache(); myConnect = myMessageBus.connect(); - myVcsFileListenerContextHelper = VcsFileListenerContextHelper.getInstance(myProject); + myVcsFileListenerContextHelper = vcsFileListenerContextHelper; VcsListener vcsListener = new VcsListener() { @Override public void directoryMappingChanged() { diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/VcsInitialization.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/VcsInitialization.java index 83498737c18b..b6ee4ff05886 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/VcsInitialization.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/VcsInitialization.java @@ -76,7 +76,7 @@ public class VcsInitialization implements Disposable { } } - public void execute() { + private void execute() { final List> list; synchronized (myLock) { list = myList; @@ -103,6 +103,11 @@ public class VcsInitialization implements Disposable { @Override public void dispose() { myIndicator.cancel(); + cancelBackgroundInitialization(); + } + + private void cancelBackgroundInitialization() { + // do not leave VCS initialization run in background when the project is closed Future future = myFuture; if (future != null) { future.cancel(false); From 1fa4a785b3f37693832c228fd8d75d544ad0230a Mon Sep 17 00:00:00 2001 From: Liana Bakradze Date: Fri, 24 Jun 2016 12:38:17 +0300 Subject: [PATCH 056/107] EDU-608 "Execute "tests.py" action doesn't create Run Study Tests configuration --- .../coursecreator/run/PyCCRunTestsConfigurationProducer.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/python/educational-python/course-creator-python/src/com/jetbrains/edu/coursecreator/run/PyCCRunTestsConfigurationProducer.java b/python/educational-python/course-creator-python/src/com/jetbrains/edu/coursecreator/run/PyCCRunTestsConfigurationProducer.java index 617345600d30..80f40044bca7 100644 --- a/python/educational-python/course-creator-python/src/com/jetbrains/edu/coursecreator/run/PyCCRunTestsConfigurationProducer.java +++ b/python/educational-python/course-creator-python/src/com/jetbrains/edu/coursecreator/run/PyCCRunTestsConfigurationProducer.java @@ -81,7 +81,8 @@ public class PyCCRunTestsConfigurationProducer extends RunConfigurationProducer< String testsPath = taskDir.findChild(EduNames.SRC) != null ? FileUtil.join(taskDirPath, EduNames.SRC, EduNames.TESTS_FILE) : FileUtil.join(taskDirPath, EduNames.TESTS_FILE); - return file.getPath().equals(testsPath) ? testsPath : null; + String filePath = FileUtil.toSystemDependentName(file.getPath()); + return filePath.equals(testsPath) ? testsPath : null; } @Override From 9e9eaac4f1e1d63ed2347e89ebd6621d2db8c87a Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 24 Jun 2016 11:49:44 +0200 Subject: [PATCH 057/107] IDEA-157840 Save Document action doesn't work during indexing --- .../src/com/intellij/ide/actions/SaveDocumentAction.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/actions/SaveDocumentAction.java b/platform/platform-impl/src/com/intellij/ide/actions/SaveDocumentAction.java index 5ad331ae5a67..d63683f09f28 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/SaveDocumentAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/SaveDocumentAction.java @@ -1,17 +1,16 @@ package com.intellij.ide.actions; -import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.CommonDataKeys; -import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.fileEditor.FileDocumentManager; +import com.intellij.openapi.project.DumbAwareAction; /** * @author yole */ -public class SaveDocumentAction extends AnAction { +public class SaveDocumentAction extends DumbAwareAction { @Override public void actionPerformed(AnActionEvent e) { Document doc = getDocument(e); From 7c3cd4327bdbf2eeba47d03c0312bab156b91ca8 Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 24 Jun 2016 11:59:44 +0200 Subject: [PATCH 058/107] fail when accessing invalid offsets in completion insert handlers --- .../completion/ConstructorInsertHandler.java | 2 +- .../intellij/codeInsight/completion/OffsetMap.java | 13 +++++++++---- .../completion/CodeCompletionHandlerBase.java | 7 +++---- .../completion/CompletionLookupArranger.java | 8 +++++++- 4 files changed, 20 insertions(+), 10 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/ConstructorInsertHandler.java b/java/java-impl/src/com/intellij/codeInsight/completion/ConstructorInsertHandler.java index 88d14aa13d77..c2ce494ab957 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/ConstructorInsertHandler.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/ConstructorInsertHandler.java @@ -58,7 +58,7 @@ public class ConstructorInsertHandler implements InsertHandler= 0 && plEnd >= 0) { diff --git a/platform/lang-api/src/com/intellij/codeInsight/completion/OffsetMap.java b/platform/lang-api/src/com/intellij/codeInsight/completion/OffsetMap.java index 90a9b12292e9..8f28dffa0dcb 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/completion/OffsetMap.java +++ b/platform/lang-api/src/com/intellij/codeInsight/completion/OffsetMap.java @@ -19,10 +19,10 @@ import com.intellij.openapi.Disposable; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.RangeMarker; import com.intellij.openapi.progress.ProgressManager; +import com.intellij.util.containers.ContainerUtil; import gnu.trove.THashMap; import gnu.trove.THashSet; -import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; @@ -48,10 +48,10 @@ public class OffsetMap implements Disposable { public int getOffset(OffsetKey key) { synchronized (myMap) { final RangeMarker marker = myMap.get(key); - if (marker == null) return -1; + if (marker == null) throw new IllegalArgumentException("Offset " + key + " is not registered"); if (!marker.isValid()) { removeOffset(key); - return -1; + throw new IllegalStateException("Offset " + key + " is invalid: " + marker); } final int endOffset = marker.getEndOffset(); @@ -62,6 +62,11 @@ public class OffsetMap implements Disposable { } } + public boolean containsOffset(OffsetKey key) { + final RangeMarker marker = myMap.get(key); + return marker != null && marker.isValid(); + } + /** * Register key-offset binding. Offset will change together with {@link Document} editing operations * unless an operation replaces completely the offset vicinity. @@ -108,7 +113,7 @@ public class OffsetMap implements Disposable { synchronized (myMap) { ProgressManager.checkCanceled(); assert !myDisposed; - return new ArrayList(myMap.keySet()); + return ContainerUtil.filter(myMap.keySet(), this::containsOffset); } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java index 34a67a149b82..bb8e159880e0 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java @@ -566,10 +566,9 @@ public class CodeCompletionHandlerBase { final Editor editor = indicator.getEditor(); final int caretOffset = indicator.getCaret().getOffset(); - int idEndOffset = indicator.getIdentifierEndOffset(); - if (idEndOffset < 0) { - idEndOffset = CompletionInitializationContext.calcDefaultIdentifierEnd(editor, caretOffset); - } + final int idEndOffset = indicator.getOffsetMap().containsOffset(CompletionInitializationContext.IDENTIFIER_END_OFFSET) ? + indicator.getIdentifierEndOffset() : + CompletionInitializationContext.calcDefaultIdentifierEnd(editor, caretOffset); final int idEndOffsetDelta = idEndOffset - caretOffset; CompletionAssertions.WatchingInsertionContext context; 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 1a4be6bf4c56..20a099c0dfb9 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionLookupArranger.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionLookupArranger.java @@ -462,6 +462,10 @@ public class CompletionLookupArranger extends LookupArranger { return; } + if (!context.getOffsetMap().containsOffset(CompletionInitializationContext.START_OFFSET)) { + return; + } + final Document document = context.getDocument(); int startOffset = context.getStartOffset(); int tailOffset = context.getEditor().getCaretModel().getOffset(); @@ -550,7 +554,9 @@ public class CompletionLookupArranger extends LookupArranger { public void addSparedChars(CompletionProgressIndicator indicator, LookupElement item, InsertionContext context, char completionChar) { String textInserted; - if (context.getStartOffset() >= 0 && context.getTailOffset() >= context.getStartOffset()) { + if (context.getOffsetMap().containsOffset(CompletionInitializationContext.START_OFFSET) && + context.getOffsetMap().containsOffset(InsertionContext.TAIL_OFFSET) && + context.getTailOffset() >= context.getStartOffset()) { textInserted = context.getDocument().getImmutableCharSequence().subSequence(context.getStartOffset(), context.getTailOffset()).toString(); } else { textInserted = item.getLookupString(); From f6c3c7be8a5b0d4e2a7bcc634d0b51be146f93d1 Mon Sep 17 00:00:00 2001 From: peter Date: Thu, 23 Jun 2016 19:06:09 +0200 Subject: [PATCH 059/107] update CompletionContributor javadoc --- .../codeInsight/completion/CompletionContributor.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionContributor.java b/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionContributor.java index b6485d6c5432..ac368eae64bd 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionContributor.java +++ b/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionContributor.java @@ -54,9 +54,7 @@ import java.util.Set; * A: There are two ways. The easier and preferred one is to provide constructor in your contributor and register completion providers there: * {@link #extend(CompletionType, ElementPattern, CompletionProvider)}.
* A more generic way is to override default {@link #fillCompletionVariants(CompletionParameters, CompletionResultSet)} implementation - * and provide your own. It's easier to debug, but harder to write. Remember, that completion variant collection is done in a dedicated thread - * WITHOUT read action, so you'll have to manually invoke {@link com.intellij.openapi.application.Application#runReadAction(Runnable)} each time - * you access PSI. Don't spend long time inside read action, since this will prevent user from selecting lookup element or cancelling completion.

+ * and provide your own. It's easier to debug, but harder to write.

* * Q: What does the {@link CompletionParameters#getPosition()} return?
* A: When completion is invoked, the file being edited is first copied (the original file can be accessed from {@link com.intellij.psi.PsiFile#getOriginalFile()} From 2f92ba525c4e499e31cbab0f4ae3989c40eb7f80 Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 24 Jun 2016 12:11:15 +0200 Subject: [PATCH 060/107] O(1) smart pointer removal --- .../SmartPsiElementPointersTest.java | 21 ++- .../SmartPointerManagerImpl.java | 138 +++++++++--------- .../SmartPsiElementPointerImpl.java | 1 + 3 files changed, 86 insertions(+), 74 deletions(-) diff --git a/java/java-tests/testSrc/com/intellij/psi/impl/smartPointers/SmartPsiElementPointersTest.java b/java/java-tests/testSrc/com/intellij/psi/impl/smartPointers/SmartPsiElementPointersTest.java index 37ea37f6c233..b9d84f386d96 100644 --- a/java/java-tests/testSrc/com/intellij/psi/impl/smartPointers/SmartPsiElementPointersTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/impl/smartPointers/SmartPsiElementPointersTest.java @@ -58,10 +58,7 @@ import org.junit.Assert; import java.io.IOException; import java.lang.ref.SoftReference; -import java.util.Collections; -import java.util.List; -import java.util.Random; -import java.util.Set; +import java.util.*; import java.util.stream.Collectors; @PlatformTestCase.WrapInCommand @@ -915,4 +912,20 @@ public class SmartPsiElementPointersTest extends CodeInsightTestCase { assertEquals(psiClass.getNameIdentifier().getTextRange(), TextRange.create(range)); } + public void testManySmartPointersCreationDeletionPerformance() throws Exception { + String text = StringUtil.repeatSymbol(' ', 100000); + PsiFile file = createFile("a.txt", text); + + PlatformTestUtil.startPerformanceTest("", 2000, () -> { + List pointers = new ArrayList<>(); + for (int i = 0; i < text.length() - 1; i++) { + pointers.add(getPointerManager().createSmartPsiFileRangePointer(file, new TextRange(i, i + 1))); + } + Collections.shuffle(pointers); + for (SmartPsiFileRange pointer : pointers) { + getPointerManager().removePointer(pointer); + } + }).cpuBound().assertTiming(); + } + } diff --git a/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SmartPointerManagerImpl.java b/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SmartPointerManagerImpl.java index d18fb3ed192c..28a99999203e 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SmartPointerManagerImpl.java +++ b/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SmartPointerManagerImpl.java @@ -29,7 +29,7 @@ import com.intellij.psi.*; import com.intellij.psi.impl.PsiDocumentManagerBase; import com.intellij.psi.util.PsiUtilCore; import com.intellij.reference.SoftReference; -import com.intellij.util.ArrayUtil; +import com.intellij.util.CommonProcessors; import com.intellij.util.Processor; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; @@ -68,7 +68,7 @@ public class SmartPointerManagerImpl extends SmartPointerManager { FilePointersList pointers = reference.file.getUserData(reference.key); if (pointers != null) { - pointers.remove(reference); + pointers.removeReference(reference); } } } @@ -160,12 +160,13 @@ public class SmartPointerManagerImpl extends SmartPointerManager { SmartPointerElementInfo info = pointer.getElementInfo(); if (!(info instanceof SelfElementInfo)) return; + PointerReference reference = new PointerReference(pointer, containingFile, POINTERS_KEY); while (true) { FilePointersList pointers = getPointers(containingFile); if (pointers == null) { pointers = containingFile.putUserDataIfAbsent(POINTERS_KEY, new FilePointersList()); } - if (pointers.add(new PointerReference(pointer, containingFile, ourQueue, POINTERS_KEY))) { + if (pointers.add(reference)) { if (((SelfElementInfo)info).hasRange()) { pointers.markerCache.rangeChanged(); } @@ -193,8 +194,10 @@ public class SmartPointerManagerImpl extends SmartPointerManager { if (containingFile == null) return; VirtualFile vFile = containingFile.getViewProvider().getVirtualFile(); FilePointersList pointers = getPointers(vFile); - if (pointers == null) return; - pointers.remove(pointer); + PointerReference reference = ((SmartPsiElementPointerImpl)pointer).pointerReference; + if (pointers != null && reference != null) { + pointers.removeReference(reference); + } } } @@ -264,17 +267,18 @@ public class SmartPointerManagerImpl extends SmartPointerManager { return myPsiDocManager; } - private static class PointerReference extends WeakReference { + static class PointerReference extends WeakReference { @NotNull private final VirtualFile file; @NotNull private final Key key; + private int index = -2; private PointerReference(@NotNull SmartPsiElementPointerImpl pointer, @NotNull VirtualFile containingFile, - @NotNull ReferenceQueue queue, @NotNull Key key) { - super(pointer, queue); + super(pointer, ourQueue); file = containingFile; this.key = key; + pointer.pointerReference = this; } } @@ -292,104 +296,98 @@ public class SmartPointerManagerImpl extends SmartPointerManager { } if (nextAvailableIndex >= references.length || nextAvailableIndex > size*2) { // overflow or too many dead refs - int newCapacity = nextAvailableIndex >= references.length ? references.length * 3/2 +1 : size * 3/2+1; - PointerReference[] newReferences = new PointerReference[newCapacity]; + int newCapacity = (nextAvailableIndex >= references.length ? references.length : size) * 3 / 2 + 1; + final PointerReference[] newReferences = new PointerReference[newCapacity]; - int o = 0; - for (PointerReference oldRef : references) { - if (SoftReference.dereference(oldRef) != null) { - newReferences[o++] = oldRef; + final int[] o = {0}; + processAlivePointers(new Processor() { + @Override + public boolean process(SmartPsiElementPointerImpl pointer) { + storePointerReference(newReferences, o[0]++, pointer.pointerReference); + return true; } - } + }); references = newReferences; - size = nextAvailableIndex = o; + size = nextAvailableIndex = o[0]; } - references[nextAvailableIndex++] = reference; + assert references[nextAvailableIndex] == null : references[nextAvailableIndex]; + storePointerReference(references, nextAvailableIndex++, reference); size++; mySorted = false; return true; } - private synchronized void remove(@NotNull PointerReference reference) { - int index = ArrayUtil.indexOf(references, reference, 0, nextAvailableIndex); - if (index != -1) { - removeReference(reference, index); - } - } + private synchronized void removeReference(@NotNull PointerReference reference) { + int index = reference.index; + if (index < 0) return; - private synchronized void remove(@NotNull SmartPsiElementPointer smartPointer) { - for (int i = 0; i < nextAvailableIndex; i++) { - PointerReference reference = references[i]; - if (reference != null && reference.get() == smartPointer) { - removeReference(reference, i); - return; - } - } - } - - private void removeReference(@NotNull PointerReference reference, int index) { + assert references[index] == reference : "At " + index + " expected " + reference + ", found " + references[index]; + references[index].index = -1; references[index] = null; if (--size == 0) { reference.file.replace(reference.key, this, null); } } - boolean processAlivePointers(@NotNull Processor processor) { + synchronized boolean processAlivePointers(@NotNull Processor processor) { for (int i = 0; i < nextAvailableIndex; i++) { - SmartPsiElementPointerImpl pointer = SoftReference.dereference(references[i]); - if (pointer != null && !processor.process(pointer)) { + PointerReference ref = references[i]; + if (ref == null) continue; + + SmartPsiElementPointerImpl pointer = ref.get(); + if (pointer == null) { + removeReference(ref); + continue; + } + + if (!processor.process(pointer)) { return false; } } return true; } - synchronized List getSortedInfos() { + private void ensureSorted() { if (!mySorted) { - List hardRefs = ContainerUtil.newArrayListWithCapacity(size); - for (int i = 0; i < nextAvailableIndex; i++) { - PointerReference reference = references[i]; - if (reference == null) continue; + List pointers = new ArrayList(); + processAlivePointers(new CommonProcessors.CollectProcessor(pointers)); + assert size == pointers.size(); - SmartPsiElementPointerImpl pointer = reference.get(); - if (pointer != null) { - hardRefs.add(pointer); - } - else { - removeReference(reference, i); - if (size == 0) { - return Collections.emptyList(); - } - } - } - assert size == hardRefs.size(); - - Arrays.sort(references, 0, nextAvailableIndex, new Comparator() { + Collections.sort(pointers, new Comparator() { @Override - public int compare(PointerReference o1, PointerReference o2) { - SmartPsiElementPointerImpl p1 = SoftReference.dereference(o1); - SmartPsiElementPointerImpl p2 = SoftReference.dereference(o2); - if (p1 == null || p2 == null) { - return p1 != null ? -1 : p2 != null ? 1 : 0; // null references to the end - } + public int compare(SmartPsiElementPointerImpl p1, SmartPsiElementPointerImpl p2) { return MarkerCache.INFO_COMPARATOR.compare((SelfElementInfo)p1.getElementInfo(), (SelfElementInfo)p2.getElementInfo()); } }); - nextAvailableIndex = hardRefs.size(); + + for (int i = 0; i < pointers.size(); i++) { + storePointerReference(references, i, pointers.get(i).pointerReference); + } + Arrays.fill(references, pointers.size(), nextAvailableIndex, null); + nextAvailableIndex = pointers.size(); mySorted = true; } + } - List infos = ContainerUtil.newArrayListWithCapacity(size); - for (int i = 0; i < nextAvailableIndex; i++) { - Reference reference = references[i]; - SmartPsiElementPointerImpl pointer = SoftReference.dereference(reference); - if (pointer != null) { + private static void storePointerReference(PointerReference[] references, int index, PointerReference ref) { + references[index] = ref; + ref.index = index; + } + + synchronized List getSortedInfos() { + ensureSorted(); + + final List infos = ContainerUtil.newArrayListWithCapacity(size); + processAlivePointers(new Processor() { + @Override + public boolean process(SmartPsiElementPointerImpl pointer) { SelfElementInfo info = (SelfElementInfo)pointer.getElementInfo(); - if (!info.hasRange()) break; + if (!info.hasRange()) return false; infos.add(info); + return true; } - } + }); return infos; } diff --git a/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SmartPsiElementPointerImpl.java b/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SmartPsiElementPointerImpl.java index ee7c4c9c249a..01e43e3b8d35 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SmartPsiElementPointerImpl.java +++ b/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SmartPsiElementPointerImpl.java @@ -46,6 +46,7 @@ class SmartPsiElementPointerImpl implements SmartPointerEx private final SmartPointerElementInfo myElementInfo; private final Class myElementClass; private byte myReferenceCount = 1; + @Nullable SmartPointerManagerImpl.PointerReference pointerReference; SmartPsiElementPointerImpl(@NotNull Project project, @NotNull E element, @Nullable PsiFile containingFile, boolean forInjected) { this(element, createElementInfo(project, element, containingFile, forInjected), element.getClass()); From aa7feafa829d32856f33fb8b81f98d3f77231ab8 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Fri, 24 Jun 2016 12:59:12 +0200 Subject: [PATCH 061/107] simplier / faster duplicates removal / sorting for small fileId array --- .../util/indexing/ValueContainerImpl.java | 8 +-- .../containers/ChangeBufferingList.java | 71 +++++++++++++------ 2 files changed, 52 insertions(+), 27 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/util/indexing/ValueContainerImpl.java b/platform/lang-impl/src/com/intellij/util/indexing/ValueContainerImpl.java index beda46464af9..8e779cb70315 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/ValueContainerImpl.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/ValueContainerImpl.java @@ -21,7 +21,6 @@ import com.intellij.util.SmartList; import com.intellij.util.containers.EmptyIterator; import com.intellij.util.indexing.containers.ChangeBufferingList; import com.intellij.util.indexing.containers.IdSet; -import com.intellij.util.indexing.containers.SortedFileIdSetIterator; import com.intellij.util.io.DataExternalizer; import com.intellij.util.io.DataInputOutputUtil; import gnu.trove.THashMap; @@ -447,11 +446,8 @@ class ValueContainerImpl extends UpdatableValueContainer implement } else { // serialize positive file ids with delta encoding ChangeBufferingList originalInput = (ChangeBufferingList)fileSetObject; - IntIterator intIterator = originalInput.rawIntIterator(); - if (!intIterator.hasAscendingOrder()) { - // remove possible dupes - intIterator = SortedFileIdSetIterator.getTransientIterator(intIterator); - } + IntIterator intIterator = originalInput.sortedIntIterator(); + if (DebugAssertions.DEBUG) DebugAssertions.assertTrue(intIterator.hasAscendingOrder()); if (intIterator.size() == 1) { DataInputOutputUtil.writeINT(out, intIterator.next()); diff --git a/platform/lang-impl/src/com/intellij/util/indexing/containers/ChangeBufferingList.java b/platform/lang-impl/src/com/intellij/util/indexing/containers/ChangeBufferingList.java index d1a7b6734fdd..57512fb4fd4d 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/containers/ChangeBufferingList.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/containers/ChangeBufferingList.java @@ -19,6 +19,8 @@ import com.intellij.util.indexing.DebugAssertions; import com.intellij.util.indexing.ValueContainer; import gnu.trove.TIntProcedure; +import java.util.Arrays; + import static com.intellij.util.indexing.DebugAssertions.EXTRA_SANITY_CHECKS; /** @@ -122,7 +124,6 @@ public class ChangeBufferingList implements Cloneable { if (randomAccessContainer == null) { int someElementsNumberEstimation = length; - int[] minMax = calcMinMax(changes, length); // todo we can check these lengths instead of only relying upon reaching MAX_FILES //int lengthOfBitSet = IdBitSet.sizeInBytes(minMax[1], minMax[0]); @@ -131,7 +132,7 @@ public class ChangeBufferingList implements Cloneable { if (someElementsNumberEstimation < MAX_FILES) { if (!hasRemovals) { if (mayHaveDupes) { - mergeChangesRemovingDupes(); + removingDupesAndSort(); } idSet = new SortedIdSet(currentChanges, length); @@ -144,7 +145,7 @@ public class ChangeBufferingList implements Cloneable { idSet = new IdBitSet(changes, length, 0); copyChanges = false; } else { - idSet = new IdBitSet(minMax, 0); + idSet = new IdBitSet(calcMinMax(changes, length), 0); } } else if (checkSet != null) { idSet = (RandomAccessIntContainer)randomAccessContainer.clone(); @@ -186,15 +187,40 @@ public class ChangeBufferingList implements Cloneable { } } - private void mergeChangesRemovingDupes() { // duplicated ids can be present for some index due to cancellation of indexing for next index - int[] currentChanges = changes; - ValueContainer.IntIterator sorted = SortedFileIdSetIterator.getTransientIterator(new ChangesIterator(currentChanges, length)); - int lastIndex = 0; - while(sorted.hasNext()) { - currentChanges[lastIndex++] = sorted.next(); - } + private void removingDupesAndSort() { // duplicated ids can be present for some index due to cancellation of indexing for next index + final int[] currentChanges = changes; + final int intLength = length; - length = (short)lastIndex; + if (intLength < 250) { // Plain sorting in Arrays works without allocations for small number of elements (see DualPivotQuicksort.QUICKSORT_THRESHOLD) + Arrays.sort(currentChanges, 0, intLength); + boolean hasDupes = false; + + for(int i = 0, max = intLength - 1; i < max; ++i) { + if (currentChanges[i] == currentChanges[i + 1]) { + hasDupes = true; + break; + } + } + + if (hasDupes) { + int ptr = 0; + for(int i = 1; i < intLength; ++i) { + if (currentChanges[i] != currentChanges[ptr]) { + currentChanges[++ptr] = currentChanges[i]; + } + } + length = (short)(ptr + 1); + } + } else { + ValueContainer.IntIterator sorted = + SortedFileIdSetIterator.getTransientIterator(new ChangesIterator(currentChanges, length, false)); + int lastIndex = 0; + while (sorted.hasNext()) { + currentChanges[lastIndex++] = sorted.next(); + } + + length = (short)lastIndex; + } mayHaveDupes = false; } @@ -262,21 +288,22 @@ public class ChangeBufferingList implements Cloneable { if (currentChanges != null) { if (mayHaveDupes) { synchronized (currentChanges) { - if (mayHaveDupes) mergeChangesRemovingDupes(); + if (mayHaveDupes) removingDupesAndSort(); } } - return new ChangesIterator(currentChanges, length); + return new ChangesIterator(currentChanges, length, true); } } return getRandomAccessContainer().intIterator(); } - public ValueContainer.IntIterator rawIntIterator() { - RandomAccessIntContainer intContainer = randomAccessContainer; - if (intContainer == null && !hasRemovals) { - return new ChangesIterator(changes, length); // dupes are possible + public ValueContainer.IntIterator sortedIntIterator() { + ValueContainer.IntIterator intIterator = intIterator(); + + if (!intIterator.hasAscendingOrder()) { + intIterator = SortedFileIdSetIterator.getTransientIterator(intIterator); } - return getRandomAccessContainer().intIterator(); + return intIterator; } public IdSet getCheckSet() { @@ -287,10 +314,12 @@ public class ChangeBufferingList implements Cloneable { private int cursor; private final int length; private final int[] changes; + private final boolean sorted; - ChangesIterator(int[] _changes, int _length) { + ChangesIterator(int[] _changes, int _length, boolean _sorted) { changes = _changes; length = _length; + sorted = _sorted; } @Override @@ -312,12 +341,12 @@ public class ChangeBufferingList implements Cloneable { @Override public boolean hasAscendingOrder() { - return false; + return sorted; } @Override public ValueContainer.IntIterator createCopyInInitialState() { - return new ChangesIterator(changes, length); + return new ChangesIterator(changes, length, sorted); } } } From 5e380e75266b0caa1b452ca813211cd5579f8aa6 Mon Sep 17 00:00:00 2001 From: Pavel Dolgov Date: Thu, 23 Jun 2016 18:03:59 +0300 Subject: [PATCH 062/107] Java inspection: convert the intention for "Remove redundant lambda parameter types" into an INFORMATION-level inspection (IDEA-156028, IDEA-157727) --- ...dundantLambdaParameterTypeInspection.java} | 81 ++++++++----- .../Assignment.java} | 0 .../AssignmentNoParams.java} | 0 .../AssignmentNoTypes.java} | 0 .../Assignment_after.java} | 0 .../AtVarargPlace.java} | 0 .../CallNoTypeArgs.java} | 0 .../CallNoTypeArgs1.java} | 0 .../CallWithTypeArgs.java} | 0 .../CallWithTypeArgs_after.java} | 0 .../redundantLambdaParameterType/InChain.java | 7 ++ .../InChain_after.java | 7 ++ .../InferredFromOtherArgs.java} | 0 .../InferredFromOtherArgs_after.java} | 0 .../NoSelfTypeParam.java} | 0 .../NoSelfTypeParam_after.java} | 0 .../TypeParam.java} | 0 ...ndantLambdaParameterTypeIntentionTest.java | 33 ------ ...dantLambdaParameterTypeInspectionTest.java | 112 ++++++++++++++++++ .../RedundantLambdaParameterType.html | 5 + .../after.java.template | 5 - .../before.java.template | 5 - .../description.html | 5 - resources/src/META-INF/IdeaPlugin.xml | 9 +- 24 files changed, 185 insertions(+), 84 deletions(-) rename java/java-impl/src/com/intellij/{codeInsight/daemon/quickFix/RedundantLambdaParameterTypeIntention.java => codeInspection/lambda/RedundantLambdaParameterTypeInspection.java} (73%) rename java/java-tests/testData/{codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeAssignment.java => codeInspection/redundantLambdaParameterType/Assignment.java} (100%) rename java/java-tests/testData/{codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeAssignmentNoParams.java => codeInspection/redundantLambdaParameterType/AssignmentNoParams.java} (100%) rename java/java-tests/testData/{codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeAssignmentNoTypes.java => codeInspection/redundantLambdaParameterType/AssignmentNoTypes.java} (100%) rename java/java-tests/testData/{codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/afterAssignment.java => codeInspection/redundantLambdaParameterType/Assignment_after.java} (100%) rename java/java-tests/testData/{codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeAtVarargPlace.java => codeInspection/redundantLambdaParameterType/AtVarargPlace.java} (100%) rename java/java-tests/testData/{codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeCallNoTypeArgs.java => codeInspection/redundantLambdaParameterType/CallNoTypeArgs.java} (100%) rename java/java-tests/testData/{codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeCallNoTypeArgs1.java => codeInspection/redundantLambdaParameterType/CallNoTypeArgs1.java} (100%) rename java/java-tests/testData/{codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeCallWithTypeArgs.java => codeInspection/redundantLambdaParameterType/CallWithTypeArgs.java} (100%) rename java/java-tests/testData/{codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/afterCallWithTypeArgs.java => codeInspection/redundantLambdaParameterType/CallWithTypeArgs_after.java} (100%) create mode 100644 java/java-tests/testData/codeInspection/redundantLambdaParameterType/InChain.java create mode 100644 java/java-tests/testData/codeInspection/redundantLambdaParameterType/InChain_after.java rename java/java-tests/testData/{codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeInferredFromOtherArgs.java => codeInspection/redundantLambdaParameterType/InferredFromOtherArgs.java} (100%) rename java/java-tests/testData/{codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/afterInferredFromOtherArgs.java => codeInspection/redundantLambdaParameterType/InferredFromOtherArgs_after.java} (100%) rename java/java-tests/testData/{codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeNoSelfTypeParam.java => codeInspection/redundantLambdaParameterType/NoSelfTypeParam.java} (100%) rename java/java-tests/testData/{codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/afterNoSelfTypeParam.java => codeInspection/redundantLambdaParameterType/NoSelfTypeParam_after.java} (100%) rename java/java-tests/testData/{codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeTypeParam.java => codeInspection/redundantLambdaParameterType/TypeParam.java} (100%) delete mode 100644 java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RedundantLambdaParameterTypeIntentionTest.java create mode 100644 java/java-tests/testSrc/com/intellij/codeInspection/RedundantLambdaParameterTypeInspectionTest.java create mode 100644 resources-en/src/inspectionDescriptions/RedundantLambdaParameterType.html delete mode 100644 resources-en/src/intentionDescriptions/RedundantLambdaParameterTypeIntention/after.java.template delete mode 100644 resources-en/src/intentionDescriptions/RedundantLambdaParameterTypeIntention/before.java.template delete mode 100644 resources-en/src/intentionDescriptions/RedundantLambdaParameterTypeIntention/description.html diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/quickFix/RedundantLambdaParameterTypeIntention.java b/java/java-impl/src/com/intellij/codeInspection/lambda/RedundantLambdaParameterTypeInspection.java similarity index 73% rename from java/java-impl/src/com/intellij/codeInsight/daemon/quickFix/RedundantLambdaParameterTypeIntention.java rename to java/java-impl/src/com/intellij/codeInspection/lambda/RedundantLambdaParameterTypeInspection.java index 38eacc30395a..4e2445fbaee9 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/quickFix/RedundantLambdaParameterTypeIntention.java +++ b/java/java-impl/src/com/intellij/codeInspection/lambda/RedundantLambdaParameterTypeInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,44 +13,43 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.codeInsight.daemon.quickFix; +package com.intellij.codeInspection.lambda; -import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction; +import com.intellij.codeInspection.BaseJavaBatchLocalInspectionTool; +import com.intellij.codeInspection.LocalQuickFix; +import com.intellij.codeInspection.ProblemDescriptor; +import com.intellij.codeInspection.ProblemsHolder; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.impl.source.resolve.DefaultParameterTypeInferencePolicy; import com.intellij.psi.infos.MethodCandidateInfo; -import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; -import com.intellij.util.Function; -import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; /** * User: anna */ -public class RedundantLambdaParameterTypeIntention extends PsiElementBaseIntentionAction { - public static final Logger LOG = Logger.getInstance("#" + RedundantLambdaParameterTypeIntention.class.getName()); +public class RedundantLambdaParameterTypeInspection extends BaseJavaBatchLocalInspectionTool { + public static final Logger LOG = Logger.getInstance("#" + RedundantLambdaParameterTypeInspection.class.getName()); @NotNull @Override - public String getFamilyName() { - return "Remove redundant types"; + public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) { + return new JavaElementVisitor() { + @Override + public void visitParameterList(PsiParameterList parameterList) { + super.visitParameterList(parameterList); + if (isApplicable(parameterList)) { + holder.registerProblem(parameterList, "Remove redundant types", new LambdaParametersFix()); + } + } + }; } - @NotNull - @Override - public String getText() { - return getFamilyName(); - } - - @Override - public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element) { - final PsiParameterList parameterList = PsiTreeUtil.getParentOfType(element, PsiParameterList.class); - if (parameterList == null) return false; + private static boolean isApplicable(@NotNull PsiParameterList parameterList) { final PsiElement parent = parameterList.getParent(); if (!(parent instanceof PsiLambdaExpression)) return false; final PsiLambdaExpression expression = (PsiLambdaExpression)parent; @@ -73,9 +72,9 @@ public class RedundantLambdaParameterTypeIntention extends PsiElementBaseIntenti final PsiTypeParameter[] typeParameters = method.getTypeParameters(); final PsiExpression[] arguments = ((PsiExpressionList)lambdaParent).getExpressions(); - final JavaPsiFacade javaPsiFacade = JavaPsiFacade.getInstance(project); + final JavaPsiFacade javaPsiFacade = JavaPsiFacade.getInstance(parameterList.getProject()); arguments[idx] = javaPsiFacade.getElementFactory().createExpressionFromText( - "(" + StringUtil.join(expression.getParameterList().getParameters(), parameter -> parameter.getName(), ", ") + ") -> {}", expression); + "(" + StringUtil.join(expression.getParameterList().getParameters(), PsiParameter::getName, ", ") + ") -> {}", expression); final PsiParameter[] methodParams = method.getParameterList().getParameters(); final PsiSubstitutor substitutor = javaPsiFacade.getResolveHelper() .inferTypeArguments(typeParameters, methodParams, arguments, ((MethodCandidateInfo)resolveResult).getSiteSubstitutor(), @@ -85,8 +84,7 @@ public class RedundantLambdaParameterTypeIntention extends PsiElementBaseIntenti final PsiType psiType = substitutor.substitute(parameter); if (psiType == null || dependsOnTypeParams(psiType, expression, parameter)) return false; } - - + final PsiType paramType; if (idx < methodParams.length) { paramType = methodParams[idx].getType(); @@ -107,12 +105,6 @@ public class RedundantLambdaParameterTypeIntention extends PsiElementBaseIntenti return false; } - @Override - public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException { - final PsiLambdaExpression lambdaExpression = PsiTreeUtil.getParentOfType(element, PsiLambdaExpression.class); - removeTypes(lambdaExpression); - } - private static void removeTypes(PsiLambdaExpression lambdaExpression) { if (lambdaExpression != null) { final PsiParameter[] parameters = lambdaExpression.getParameterList().getParameters(); @@ -121,7 +113,7 @@ public class RedundantLambdaParameterTypeIntention extends PsiElementBaseIntenti text = parameters[0].getName(); } else { - text = "(" + StringUtil.join(parameters, parameter -> parameter.getName(), ", ") + ")"; + text = "(" + StringUtil.join(parameters, PsiParameter::getName, ", ") + ")"; } final PsiLambdaExpression expression = (PsiLambdaExpression)JavaPsiFacade.getElementFactory(lambdaExpression.getProject()) .createExpressionFromText(text + "->{}", lambdaExpression); @@ -135,4 +127,29 @@ public class RedundantLambdaParameterTypeIntention extends PsiElementBaseIntenti return LambdaUtil.depends(type, new LambdaUtil.TypeParamsChecker(expr, PsiUtil .resolveGenericsClassInType(LambdaUtil.getFunctionalInterfaceType(expr, false)).getElement()), param2Check); } + + private static class LambdaParametersFix implements LocalQuickFix { + @Nls + @NotNull + @Override + public String getName() { + return getFamilyName(); + } + + @Nls + @NotNull + @Override + public String getFamilyName() { + return "Remove redundant types"; + } + + @Override + public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { + final PsiElement element = descriptor.getPsiElement(); + final PsiElement parent = element.getParent(); + if (parent instanceof PsiLambdaExpression) { + removeTypes((PsiLambdaExpression)parent); + } + } + } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeAssignment.java b/java/java-tests/testData/codeInspection/redundantLambdaParameterType/Assignment.java similarity index 100% rename from java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeAssignment.java rename to java/java-tests/testData/codeInspection/redundantLambdaParameterType/Assignment.java diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeAssignmentNoParams.java b/java/java-tests/testData/codeInspection/redundantLambdaParameterType/AssignmentNoParams.java similarity index 100% rename from java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeAssignmentNoParams.java rename to java/java-tests/testData/codeInspection/redundantLambdaParameterType/AssignmentNoParams.java diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeAssignmentNoTypes.java b/java/java-tests/testData/codeInspection/redundantLambdaParameterType/AssignmentNoTypes.java similarity index 100% rename from java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeAssignmentNoTypes.java rename to java/java-tests/testData/codeInspection/redundantLambdaParameterType/AssignmentNoTypes.java diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/afterAssignment.java b/java/java-tests/testData/codeInspection/redundantLambdaParameterType/Assignment_after.java similarity index 100% rename from java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/afterAssignment.java rename to java/java-tests/testData/codeInspection/redundantLambdaParameterType/Assignment_after.java diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeAtVarargPlace.java b/java/java-tests/testData/codeInspection/redundantLambdaParameterType/AtVarargPlace.java similarity index 100% rename from java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeAtVarargPlace.java rename to java/java-tests/testData/codeInspection/redundantLambdaParameterType/AtVarargPlace.java diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeCallNoTypeArgs.java b/java/java-tests/testData/codeInspection/redundantLambdaParameterType/CallNoTypeArgs.java similarity index 100% rename from java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeCallNoTypeArgs.java rename to java/java-tests/testData/codeInspection/redundantLambdaParameterType/CallNoTypeArgs.java diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeCallNoTypeArgs1.java b/java/java-tests/testData/codeInspection/redundantLambdaParameterType/CallNoTypeArgs1.java similarity index 100% rename from java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeCallNoTypeArgs1.java rename to java/java-tests/testData/codeInspection/redundantLambdaParameterType/CallNoTypeArgs1.java diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeCallWithTypeArgs.java b/java/java-tests/testData/codeInspection/redundantLambdaParameterType/CallWithTypeArgs.java similarity index 100% rename from java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeCallWithTypeArgs.java rename to java/java-tests/testData/codeInspection/redundantLambdaParameterType/CallWithTypeArgs.java diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/afterCallWithTypeArgs.java b/java/java-tests/testData/codeInspection/redundantLambdaParameterType/CallWithTypeArgs_after.java similarity index 100% rename from java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/afterCallWithTypeArgs.java rename to java/java-tests/testData/codeInspection/redundantLambdaParameterType/CallWithTypeArgs_after.java diff --git a/java/java-tests/testData/codeInspection/redundantLambdaParameterType/InChain.java b/java/java-tests/testData/codeInspection/redundantLambdaParameterType/InChain.java new file mode 100644 index 000000000000..7262e3bbca40 --- /dev/null +++ b/java/java-tests/testData/codeInspection/redundantLambdaParameterType/InChain.java @@ -0,0 +1,7 @@ +import java.util.stream.Stream; + +class InChain { + public static void main(String[] args) { + Stream.of("a").map((String s) -> s + "1").forEach(System.out::println); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInspection/redundantLambdaParameterType/InChain_after.java b/java/java-tests/testData/codeInspection/redundantLambdaParameterType/InChain_after.java new file mode 100644 index 000000000000..857e423db1eb --- /dev/null +++ b/java/java-tests/testData/codeInspection/redundantLambdaParameterType/InChain_after.java @@ -0,0 +1,7 @@ +import java.util.stream.Stream; + +class InChain { + public static void main(String[] args) { + Stream.of("a").map(s -> s + "1").forEach(System.out::println); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeInferredFromOtherArgs.java b/java/java-tests/testData/codeInspection/redundantLambdaParameterType/InferredFromOtherArgs.java similarity index 100% rename from java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeInferredFromOtherArgs.java rename to java/java-tests/testData/codeInspection/redundantLambdaParameterType/InferredFromOtherArgs.java diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/afterInferredFromOtherArgs.java b/java/java-tests/testData/codeInspection/redundantLambdaParameterType/InferredFromOtherArgs_after.java similarity index 100% rename from java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/afterInferredFromOtherArgs.java rename to java/java-tests/testData/codeInspection/redundantLambdaParameterType/InferredFromOtherArgs_after.java diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeNoSelfTypeParam.java b/java/java-tests/testData/codeInspection/redundantLambdaParameterType/NoSelfTypeParam.java similarity index 100% rename from java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeNoSelfTypeParam.java rename to java/java-tests/testData/codeInspection/redundantLambdaParameterType/NoSelfTypeParam.java diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/afterNoSelfTypeParam.java b/java/java-tests/testData/codeInspection/redundantLambdaParameterType/NoSelfTypeParam_after.java similarity index 100% rename from java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/afterNoSelfTypeParam.java rename to java/java-tests/testData/codeInspection/redundantLambdaParameterType/NoSelfTypeParam_after.java diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeTypeParam.java b/java/java-tests/testData/codeInspection/redundantLambdaParameterType/TypeParam.java similarity index 100% rename from java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType/beforeTypeParam.java rename to java/java-tests/testData/codeInspection/redundantLambdaParameterType/TypeParam.java diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RedundantLambdaParameterTypeIntentionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RedundantLambdaParameterTypeIntentionTest.java deleted file mode 100644 index 4f85962f0a62..000000000000 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RedundantLambdaParameterTypeIntentionTest.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2000-2012 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.daemon.quickFix; - -import com.intellij.openapi.projectRoots.Sdk; -import com.intellij.testFramework.IdeaTestUtil; - -public class RedundantLambdaParameterTypeIntentionTest extends LightQuickFixParameterizedTestCase { - public void test() throws Exception { doAllTests(); } - - @Override - protected String getBasePath() { - return "/codeInsight/daemonCodeAnalyzer/quickFix/redundantLambdaParameterType"; - } - - @Override - protected Sdk getProjectJDK() { - return IdeaTestUtil.getMockJdk18(); - } -} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/RedundantLambdaParameterTypeInspectionTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/RedundantLambdaParameterTypeInspectionTest.java new file mode 100644 index 000000000000..3e610fcbcf04 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/codeInspection/RedundantLambdaParameterTypeInspectionTest.java @@ -0,0 +1,112 @@ +/* + * Copyright 2000-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http:public void testwww() {}.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.codeInspection; + +import com.intellij.JavaTestUtil; +import com.intellij.codeInsight.intention.IntentionAction; +import com.intellij.codeInspection.lambda.RedundantLambdaParameterTypeInspection; +import com.intellij.idea.Bombed; +import com.intellij.openapi.roots.ModuleRootModificationUtil; +import com.intellij.testFramework.IdeaTestUtil; +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; + +import java.util.Calendar; +import java.util.List; + +public class RedundantLambdaParameterTypeInspectionTest extends LightCodeInsightFixtureTestCase { + private RedundantLambdaParameterTypeInspection myInspection = new RedundantLambdaParameterTypeInspection(); + private String myIntentionName = "Remove redundant types"; + + @Override + protected String getBasePath() { + return JavaTestUtil.getRelativeJavaTestDataPath() + "/codeInspection/redundantLambdaParameterType"; + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + ModuleRootModificationUtil.setModuleSdk(myModule, IdeaTestUtil.getMockJdk18()); + myFixture.enableInspections(myInspection); + } + + @Override + protected void tearDown() throws Exception { + try { + myFixture.disableInspections(myInspection); + } + finally { + super.tearDown(); + } + } + + public void testAssignment() { + doTest(); + } + + public void testAssignmentNoParams() { + assertIntentionNotAvailable(); + } + + public void testAssignmentNoTypes() { + assertIntentionNotAvailable(); + } + + public void testAtVarargPlace() { + assertIntentionNotAvailable(); + } + + public void testCallNoTypeArgs() { + assertIntentionNotAvailable(); + } + + public void testCallNoTypeArgs1() { + assertIntentionNotAvailable(); + } + + public void testCallWithTypeArgs() { + doTest(); + } + + public void testInferredFromOtherArgs() { + doTest(); + } + + public void testNoSelfTypeParam() { + doTest(); + } + + public void testTypeParam() { + assertIntentionNotAvailable(); + } + + @Bombed(month = Calendar.AUGUST, day = 1, user = "Pavel Dolgov") + public void testInChain() { + doTest(); + } + + private void doTest() { + myFixture.configureByFiles(getTestName(false) + ".java"); + final IntentionAction singleIntention = myFixture.findSingleIntention(myIntentionName); + myFixture.launchAction(singleIntention); + myFixture.checkResultByFile(getTestName(false) + ".java", getTestName(false) + "_after.java", true); + } + + private void assertIntentionNotAvailable() { + myFixture.configureByFiles(getTestName(false) + ".java"); + final List intentionActions = myFixture.filterAvailableIntentions(myIntentionName); + assertEmpty(myIntentionName + " is not expected", intentionActions); + } +} \ No newline at end of file diff --git a/resources-en/src/inspectionDescriptions/RedundantLambdaParameterType.html b/resources-en/src/inspectionDescriptions/RedundantLambdaParameterType.html new file mode 100644 index 000000000000..ea49461e2613 --- /dev/null +++ b/resources-en/src/inspectionDescriptions/RedundantLambdaParameterType.html @@ -0,0 +1,5 @@ + + +This inspection removes lambda formal parameter types when they can be inferred from context. + + \ No newline at end of file diff --git a/resources-en/src/intentionDescriptions/RedundantLambdaParameterTypeIntention/after.java.template b/resources-en/src/intentionDescriptions/RedundantLambdaParameterTypeIntention/after.java.template deleted file mode 100644 index 925e26bf3039..000000000000 --- a/resources-en/src/intentionDescriptions/RedundantLambdaParameterTypeIntention/after.java.template +++ /dev/null @@ -1,5 +0,0 @@ -class X { - { - Comparable c = o -> 0; - } -} \ No newline at end of file diff --git a/resources-en/src/intentionDescriptions/RedundantLambdaParameterTypeIntention/before.java.template b/resources-en/src/intentionDescriptions/RedundantLambdaParameterTypeIntention/before.java.template deleted file mode 100644 index 84da2abb9213..000000000000 --- a/resources-en/src/intentionDescriptions/RedundantLambdaParameterTypeIntention/before.java.template +++ /dev/null @@ -1,5 +0,0 @@ -class X { - { - Comparable c = (String o) -> 0; - } -} \ No newline at end of file diff --git a/resources-en/src/intentionDescriptions/RedundantLambdaParameterTypeIntention/description.html b/resources-en/src/intentionDescriptions/RedundantLambdaParameterTypeIntention/description.html deleted file mode 100644 index 7e47e9314b11..000000000000 --- a/resources-en/src/intentionDescriptions/RedundantLambdaParameterTypeIntention/description.html +++ /dev/null @@ -1,5 +0,0 @@ - - -This intention removes lambda formal parameter types when they can be inferred from context. - - \ No newline at end of file diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml index 29201b0565b2..4be169a82fed 100644 --- a/resources/src/META-INF/IdeaPlugin.xml +++ b/resources/src/META-INF/IdeaPlugin.xml @@ -800,11 +800,12 @@ groupKey="group.names.declaration.redundancy" enabledByDefault="true" level="WARNING" implementationClass="com.intellij.codeInspection.SimplifyStreamApiCallChainsInspection" displayName="Simplify stream API call chains"/> + - - com.intellij.codeInsight.daemon.quickFix.RedundantLambdaParameterTypeIntention - Java/Declaration - com.intellij.codeInsight.intention.impl.SplitIfAction Java/Control Flow From 92838f48bcf6d205ea12c667bb01e9205e2c3735 Mon Sep 17 00:00:00 2001 From: Pavel Dolgov Date: Fri, 24 Jun 2016 13:59:42 +0300 Subject: [PATCH 063/107] Java inspection: Get rid of RemoveRedundantElseAction, as it's totally inferior to DataFlowInspection (IDEA-157727) --- .../quickfix/RemoveRedundantElseAction.java | 109 ------------------ .../quickFix/removeRedundantElse/after1.java | 13 --- .../quickFix/removeRedundantElse/before1.java | 14 --- .../beforeCanThrowException.java | 15 --- .../beforeIfElseChain.java | 17 --- .../RemoveRedundantElseActionTest.java | 32 ----- .../after.java.template | 8 -- .../before.java.template | 10 -- .../description.html | 7 -- resources/src/META-INF/IdeaPlugin.xml | 4 - 10 files changed, 229 deletions(-) delete mode 100644 java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/RemoveRedundantElseAction.java delete mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/removeRedundantElse/after1.java delete mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/removeRedundantElse/before1.java delete mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/removeRedundantElse/beforeCanThrowException.java delete mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/removeRedundantElse/beforeIfElseChain.java delete mode 100644 java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RemoveRedundantElseActionTest.java delete mode 100644 resources-en/src/intentionDescriptions/RemoveRedundantElseAction/after.java.template delete mode 100644 resources-en/src/intentionDescriptions/RemoveRedundantElseAction/before.java.template delete mode 100644 resources-en/src/intentionDescriptions/RemoveRedundantElseAction/description.html diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/RemoveRedundantElseAction.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/RemoveRedundantElseAction.java deleted file mode 100644 index 28db235e1e1b..000000000000 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/RemoveRedundantElseAction.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright 2000-2009 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.daemon.impl.quickfix; - -import com.intellij.codeInsight.FileModificationService; -import com.intellij.codeInsight.daemon.QuickFixBundle; -import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.project.Project; -import com.intellij.psi.*; -import com.intellij.psi.controlFlow.*; -import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.util.BitUtil; -import com.intellij.util.IncorrectOperationException; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -/** - * @author ven - */ -public class RemoveRedundantElseAction extends PsiElementBaseIntentionAction { - private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.quickfix.RemoveRedundantElseAction"); - - @Override - @NotNull - public String getText() { - return QuickFixBundle.message("remove.redundant.else.fix"); - } - - @Override - @NotNull - public String getFamilyName() { - return QuickFixBundle.message("remove.redundant.else.fix"); - } - - @Override - public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element) { - if (element instanceof PsiKeyword && - element.getParent() instanceof PsiIfStatement && - PsiKeyword.ELSE.equals(element.getText())) { - PsiIfStatement ifStatement = (PsiIfStatement)element.getParent(); - if (ifStatement.getElseBranch() == null) return false; - PsiStatement thenBranch = ifStatement.getThenBranch(); - if (thenBranch == null) return false; - PsiElement block = PsiTreeUtil.getParentOfType(ifStatement, PsiCodeBlock.class); - if (block != null) { - while (cantCompleteNormally(thenBranch, block)) { - thenBranch = getPrevThenBranch(thenBranch); - if (thenBranch == null) return true; - } - return false; - } - } - return false; - } - - @Nullable - private static PsiStatement getPrevThenBranch(@NotNull PsiElement thenBranch) { - final PsiElement ifStatement = thenBranch.getParent(); - final PsiElement parent = ifStatement.getParent(); - if (parent instanceof PsiIfStatement && ((PsiIfStatement)parent).getElseBranch() == ifStatement) { - return ((PsiIfStatement)parent).getThenBranch(); - } - return null; - } - - private static boolean cantCompleteNormally(@NotNull PsiStatement thenBranch, PsiElement block) { - try { - ControlFlow controlFlow = ControlFlowFactory.getInstance(thenBranch.getProject()).getControlFlow(block, LocalsOrMyInstanceFieldsControlFlowPolicy.getInstance()); - int startOffset = controlFlow.getStartOffset(thenBranch); - int endOffset = controlFlow.getEndOffset(thenBranch); - return startOffset != -1 && endOffset != -1 && !BitUtil.isSet(ControlFlowUtil.getCompletionReasons(controlFlow, startOffset, endOffset), ControlFlowUtil.NORMAL_COMPLETION_REASON); - } - catch (AnalysisCanceledException e) { - return false; - } - } - - @Override - public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException { - if (!FileModificationService.getInstance().preparePsiElementForWrite(element)) return; - PsiIfStatement ifStatement = (PsiIfStatement)element.getParent(); - LOG.assertTrue(ifStatement != null && ifStatement.getElseBranch() != null); - PsiStatement elseBranch = ifStatement.getElseBranch(); - if (elseBranch instanceof PsiBlockStatement) { - PsiElement[] statements = ((PsiBlockStatement)elseBranch).getCodeBlock().getStatements(); - if (statements.length > 0) { - ifStatement.getParent().addRangeAfter(statements[0], statements[statements.length-1], ifStatement); - } - } else { - ifStatement.getParent().addAfter(elseBranch, ifStatement); - } - ifStatement.getElseBranch().delete(); - } -} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/removeRedundantElse/after1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/removeRedundantElse/after1.java deleted file mode 100644 index d0d55761f11b..000000000000 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/removeRedundantElse/after1.java +++ /dev/null @@ -1,13 +0,0 @@ -// "Remove redundant 'else'" "true" -class a { - void foo() { - int a = 0; - int b = 0; - if (a != b) { - return; - } - a = b; - a++; - } -} - diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/removeRedundantElse/before1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/removeRedundantElse/before1.java deleted file mode 100644 index ea4609835464..000000000000 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/removeRedundantElse/before1.java +++ /dev/null @@ -1,14 +0,0 @@ -// "Remove redundant 'else'" "true" -class a { - void foo() { - int a = 0; - int b = 0; - if (a != b) { - return; - } else { - a = b; - } - a++; - } -} - diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/removeRedundantElse/beforeCanThrowException.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/removeRedundantElse/beforeCanThrowException.java deleted file mode 100644 index 8fd59ef094f3..000000000000 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/removeRedundantElse/beforeCanThrowException.java +++ /dev/null @@ -1,15 +0,0 @@ -// "Remove redundant 'else'" "false" -import java.io.IOException; -class a { - void foo(boolean condition) throws IOException{ - if (condition) { - tMethod(); - } - else { - System.out.println("else"); - } - } - - void tMethod() throws IOException {} -} - diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/removeRedundantElse/beforeIfElseChain.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/removeRedundantElse/beforeIfElseChain.java deleted file mode 100644 index f702178d781f..000000000000 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/removeRedundantElse/beforeIfElseChain.java +++ /dev/null @@ -1,17 +0,0 @@ -// "Remove redundant 'else'" "false" -class a { - void foo() { - int a = 0; - int b = 0; - if (a != b) { - a = 10; - } else if (a + 1 == b) { - return; - } - else { - a = b; - } - a++; - } -} - diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RemoveRedundantElseActionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RemoveRedundantElseActionTest.java deleted file mode 100644 index 0a33ada748f8..000000000000 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RemoveRedundantElseActionTest.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2000-2010 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.daemon.quickFix; - -/** - * User: anna - * Date: Aug 30, 2010 - */ -public class RemoveRedundantElseActionTest extends LightQuickFixParameterizedTestCase { - - public void test() throws Exception { doAllTests(); } - - @Override - protected String getBasePath() { - return "/codeInsight/daemonCodeAnalyzer/quickFix/removeRedundantElse"; - } - -} - diff --git a/resources-en/src/intentionDescriptions/RemoveRedundantElseAction/after.java.template b/resources-en/src/intentionDescriptions/RemoveRedundantElseAction/after.java.template deleted file mode 100644 index 6bbd9d56135a..000000000000 --- a/resources-en/src/intentionDescriptions/RemoveRedundantElseAction/after.java.template +++ /dev/null @@ -1,8 +0,0 @@ -public class X { - void f(int i) { - if (i==0) { - return; - } - int j = 0; - } -} \ No newline at end of file diff --git a/resources-en/src/intentionDescriptions/RemoveRedundantElseAction/before.java.template b/resources-en/src/intentionDescriptions/RemoveRedundantElseAction/before.java.template deleted file mode 100644 index edad99d14f45..000000000000 --- a/resources-en/src/intentionDescriptions/RemoveRedundantElseAction/before.java.template +++ /dev/null @@ -1,10 +0,0 @@ -public class X { - void f(int i) { - if (i==0) { - return; - } - else { - int j = 0; - } - } -} \ No newline at end of file diff --git a/resources-en/src/intentionDescriptions/RemoveRedundantElseAction/description.html b/resources-en/src/intentionDescriptions/RemoveRedundantElseAction/description.html deleted file mode 100644 index 8992a7b29b2c..000000000000 --- a/resources-en/src/intentionDescriptions/RemoveRedundantElseAction/description.html +++ /dev/null @@ -1,7 +0,0 @@ - - -This intention detaches else clause from the if statement, -if corresponding then clause never completes normally. - - - diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml index 4be169a82fed..ca43d4c44eda 100644 --- a/resources/src/META-INF/IdeaPlugin.xml +++ b/resources/src/META-INF/IdeaPlugin.xml @@ -826,10 +826,6 @@ com.intellij.codeInsight.intention.impl.ExtractIfConditionAction Java/Control Flow - - com.intellij.codeInsight.daemon.impl.quickfix.RemoveRedundantElseAction - Java/Control Flow - com.intellij.codeInsight.intention.impl.AddNotNullAnnotationIntention Java/Annotations From 9a9cfcdbfa6ce71f3ad391df01447588a864fe43 Mon Sep 17 00:00:00 2001 From: Elizaveta Shashkova Date: Tue, 21 Jun 2016 13:03:06 +0300 Subject: [PATCH 064/107] Cannot do keyboard input in debug mode with interactive console turned on (PY-16825 ) In debug console we should handle input calls on Python side and notify Java side, like we do it in Interactive Python Console. After handling input we should send it back to Python process. --- .../_pydev_bundle/pydev_console_utils.py | 25 ++++++++ .../pydev/_pydevd_bundle/pydevd_comm.py | 9 +++ python/helpers/pydev/pydevd.py | 8 +++ .../python/debugger/IPyDebugProcess.java | 2 + .../debugger/pydev/AbstractCommand.java | 5 ++ .../python/debugger/pydev/RemoteDebugger.java | 3 + .../python/console/PythonConsoleView.java | 9 +++ .../PythonDebugConsoleCommunication.java | 57 +++++++++++++------ .../python/debugger/PyDebugProcess.java | 7 +++ 9 files changed, 109 insertions(+), 16 deletions(-) diff --git a/python/helpers/pydev/_pydev_bundle/pydev_console_utils.py b/python/helpers/pydev/_pydev_bundle/pydev_console_utils.py index 19be9971bda1..112d0ae36de9 100644 --- a/python/helpers/pydev/_pydev_bundle/pydev_console_utils.py +++ b/python/helpers/pydev/_pydev_bundle/pydev_console_utils.py @@ -114,6 +114,31 @@ class StdIn(BaseStdIn): return '\n' +#======================================================================================================================= +# DebugConsoleStdIn +#======================================================================================================================= +class DebugConsoleStdIn(BaseStdIn): + ''' + Object to be added to stdin (to emulate it as non-blocking while the next line arrives) + ''' + + def __init__(self, dbg, original_stdin): + BaseStdIn.__init__(self) + self.debugger = dbg + self.original_stdin = original_stdin + + def readline(self, *args, **kwargs): + # Notify Java side about input and call original function + try: + cmd = self.debugger.cmd_factory.make_input_requested_message() + self.debugger.writer.add_command(cmd) + return self.original_stdin.readline(*args, **kwargs) + except Exception: + import traceback + traceback.print_exc() + return '\n' + + class CodeFragment: def __init__(self, text, is_single_line=True): self.text = text diff --git a/python/helpers/pydev/_pydevd_bundle/pydevd_comm.py b/python/helpers/pydev/_pydevd_bundle/pydevd_comm.py index babdc3571d0a..ec0c13d692b5 100644 --- a/python/helpers/pydev/_pydevd_bundle/pydevd_comm.py +++ b/python/helpers/pydev/_pydevd_bundle/pydevd_comm.py @@ -138,6 +138,7 @@ CMD_GET_ARRAY = 143 CMD_STEP_INTO_MY_CODE = 144 CMD_GET_CONCURRENCY_EVENT = 145 CMD_SHOW_RETURN_VALUES = 146 +CMD_INPUT_REQUESTED = 147 CMD_VERSION = 501 CMD_RETURN = 502 @@ -191,6 +192,7 @@ ID_TO_MEANING = { '144': 'CMD_STEP_INTO_MY_CODE', '145': 'CMD_GET_CONCURRENCY_EVENT', '146': 'CMD_SHOW_RETURN_VALUES', + '147': 'CMD_INPUT_REQUESTED', '501': 'CMD_VERSION', '502': 'CMD_RETURN', @@ -779,6 +781,13 @@ class NetCommandFactory: except: return self.make_error_message(0, get_exception_traceback_str()) + def make_input_requested_message(self): + try: + return NetCommand(CMD_INPUT_REQUESTED, 0, '') + except: + return self.make_error_message(0, get_exception_traceback_str()) + + def make_exit_message(self): try: net = NetCommand(CMD_EXIT, 0, '') diff --git a/python/helpers/pydev/pydevd.py b/python/helpers/pydev/pydevd.py index b27daef92c57..e333f90df1c7 100644 --- a/python/helpers/pydev/pydevd.py +++ b/python/helpers/pydev/pydevd.py @@ -1180,6 +1180,7 @@ def _locked_settrace( if bufferStdErrToServer: init_stderr_redirect() + patch_stdin(debugger) debugger.set_trace_for_frame_and_parents(get_frame(), False, overwrite_prev_trace=overwrite_prev_trace) @@ -1382,6 +1383,12 @@ def apply_debugger_options(setup_options): enable_qt_support() +def patch_stdin(debugger): + from _pydev_bundle.pydev_console_utils import DebugConsoleStdIn + orig_stdin = sys.stdin + sys.stdin = DebugConsoleStdIn(debugger, orig_stdin) + + #======================================================================================================================= # main #======================================================================================================================= @@ -1512,6 +1519,7 @@ if __name__ == '__main__': pass # It's ok not having stackless there... is_module = setup['module'] + patch_stdin(debugger) if fix_app_engine_debug: sys.stderr.write("pydev debugger: google app engine integration enabled\n") diff --git a/python/pydevSrc/com/jetbrains/python/debugger/IPyDebugProcess.java b/python/pydevSrc/com/jetbrains/python/debugger/IPyDebugProcess.java index 82155bacd88f..ce55d8e87e83 100644 --- a/python/pydevSrc/com/jetbrains/python/debugger/IPyDebugProcess.java +++ b/python/pydevSrc/com/jetbrains/python/debugger/IPyDebugProcess.java @@ -37,5 +37,7 @@ public interface IPyDebugProcess extends PyFrameAccessor { boolean isSuspendedOnAllThreadsPolicy(); + void consoleInputRequested(); + XDebugSession getSession(); } diff --git a/python/pydevSrc/com/jetbrains/python/debugger/pydev/AbstractCommand.java b/python/pydevSrc/com/jetbrains/python/debugger/pydev/AbstractCommand.java index 4ed466cacbc6..941e39343ba4 100644 --- a/python/pydevSrc/com/jetbrains/python/debugger/pydev/AbstractCommand.java +++ b/python/pydevSrc/com/jetbrains/python/debugger/pydev/AbstractCommand.java @@ -50,6 +50,7 @@ public abstract class AbstractCommand { public static final int STEP_INTO_MY_CODE = 144; public static final int LOG_CONCURRENCY_EVENT = 145; public static final int SHOW_RETURN_VALUES = 146; + public static final int INPUT_REQUESTED = 147; public static final int ERROR = 901; @@ -197,6 +198,10 @@ public abstract class AbstractCommand { return command == WRITE_TO_CONSOLE; } + public static boolean isInputRequested(final int command) { + return command == INPUT_REQUESTED; + } + public static boolean isExitEvent(final int command) { return command == EXIT; } diff --git a/python/pydevSrc/com/jetbrains/python/debugger/pydev/RemoteDebugger.java b/python/pydevSrc/com/jetbrains/python/debugger/pydev/RemoteDebugger.java index 7b15821aef8b..08b93e8fbfa1 100644 --- a/python/pydevSrc/com/jetbrains/python/debugger/pydev/RemoteDebugger.java +++ b/python/pydevSrc/com/jetbrains/python/debugger/pydev/RemoteDebugger.java @@ -547,6 +547,9 @@ public class RemoteDebugger implements ProcessDebugger { else if (AbstractCommand.isConcurrencyEvent(frame.getCommand())) { recordConcurrencyEvent(ProtocolParser.parseConcurrencyEvent(frame.getPayload(), myDebugProcess.getPositionConverter())); } + else if (AbstractCommand.isInputRequested(frame.getCommand())) { + myDebugProcess.consoleInputRequested(); + } else { placeResponse(frame.getSequence(), frame); } diff --git a/python/src/com/jetbrains/python/console/PythonConsoleView.java b/python/src/com/jetbrains/python/console/PythonConsoleView.java index e3e17b295f02..d6f4f63f0834 100644 --- a/python/src/com/jetbrains/python/console/PythonConsoleView.java +++ b/python/src/com/jetbrains/python/console/PythonConsoleView.java @@ -95,6 +95,15 @@ public class PythonConsoleView extends LanguageConsoleImpl implements Observable myExecuteActionHandler = consoleExecuteActionHandler; } + public void inputRequested() { + final ConsoleCommunication consoleCommunication = myExecuteActionHandler.getConsoleCommunication(); + if (consoleCommunication instanceof PythonDebugConsoleCommunication) { + ((PythonDebugConsoleCommunication)consoleCommunication).waitingForInput = true; + myExecuteActionHandler.inputRequested(); + myExecuteActionHandler.setEnabled(true); + } + } + @Override public void requestFocus() { IdeFocusManager.findInstance().requestFocus(getConsoleEditor().getContentComponent(), true); diff --git a/python/src/com/jetbrains/python/console/PythonDebugConsoleCommunication.java b/python/src/com/jetbrains/python/console/PythonDebugConsoleCommunication.java index 25eb30cc0552..e357c4dd89ab 100644 --- a/python/src/com/jetbrains/python/console/PythonDebugConsoleCommunication.java +++ b/python/src/com/jetbrains/python/console/PythonDebugConsoleCommunication.java @@ -15,8 +15,10 @@ */ package com.jetbrains.python.console; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Pair; +import com.intellij.openapi.vfs.encoding.EncodingProjectManager; import com.intellij.util.Function; import com.jetbrains.python.console.pydev.AbstractConsoleCommunication; import com.jetbrains.python.console.pydev.InterpreterResponse; @@ -26,12 +28,16 @@ import com.jetbrains.python.debugger.PyDebuggerException; import com.jetbrains.python.debugger.pydev.PyDebugCallback; import org.jetbrains.annotations.NotNull; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.charset.Charset; import java.util.List; /** * @author traff */ public class PythonDebugConsoleCommunication extends AbstractConsoleCommunication { + private static final Logger LOG = Logger.getInstance("#com.jetbrains.python.console.pydev.PythonDebugConsoleCommunication"); private final PyDebugProcess myDebugProcess; private final StringBuilder myExpression = new StringBuilder(); @@ -55,7 +61,7 @@ public class PythonDebugConsoleCommunication extends AbstractConsoleCommunicatio @Override public boolean isWaitingForInput() { - return false; + return waitingForInput; } @Override @@ -78,24 +84,43 @@ public class PythonDebugConsoleCommunication extends AbstractConsoleCommunicatio } public void execInterpreter(ConsoleCodeFragment code, final Function callback) { - myExpression.append(code.getText()); - exec(new ConsoleCodeFragment(myExpression.toString(), false), new PyDebugCallback>() { - @Override - public void ok(Pair executed) { - boolean more = executed.second; - - if (!more) { - myExpression.setLength(0); + if (waitingForInput) { + final OutputStream processInput = myDebugProcess.getProcessHandler().getProcessInput(); + if (processInput != null) { + try { + final Charset defaultCharset = EncodingProjectManager.getInstance(myDebugProcess.getProject()).getDefaultCharset(); + String text = code.getText(); + // we save previous command text!!! + processInput.write((text + "\n").getBytes(defaultCharset)); + processInput.flush(); + } + catch (IOException e) { + LOG.error(e.getMessage()); } - callback.fun(new InterpreterResponse(more, isWaitingForInput())); } + waitingForInput = false; + } + else { - @Override - public void error(PyDebuggerException exception) { - myExpression.setLength(0); - callback.fun(new InterpreterResponse(false, isWaitingForInput())); - } - }); + myExpression.append(code.getText()); + exec(new ConsoleCodeFragment(myExpression.toString(), false), new PyDebugCallback>() { + @Override + public void ok(Pair executed) { + boolean more = executed.second; + + if (!more) { + myExpression.setLength(0); + } + callback.fun(new InterpreterResponse(more, isWaitingForInput())); + } + + @Override + public void error(PyDebuggerException exception) { + myExpression.setLength(0); + callback.fun(new InterpreterResponse(false, isWaitingForInput())); + } + }); + } } @Override diff --git a/python/src/com/jetbrains/python/debugger/PyDebugProcess.java b/python/src/com/jetbrains/python/debugger/PyDebugProcess.java index ea7c3afccd9c..3ab7886b6237 100644 --- a/python/src/com/jetbrains/python/debugger/PyDebugProcess.java +++ b/python/src/com/jetbrains/python/debugger/PyDebugProcess.java @@ -346,6 +346,13 @@ public class PyDebugProcess extends XDebugProcess implements IPyDebugProcess, Pr } } + @Override + public void consoleInputRequested() { + if (myExecutionConsole instanceof PythonDebugLanguageConsoleView) { + ((PythonDebugLanguageConsoleView)myExecutionConsole).getPydevConsoleView().inputRequested(); + } + } + protected void afterConnect() { } From d3f57ad6cbdd0d9f1e03bcd357eb7a0123cb4d8c Mon Sep 17 00:00:00 2001 From: Elizaveta Shashkova Date: Tue, 21 Jun 2016 13:58:29 +0300 Subject: [PATCH 065/107] Input doesn't work in Debug Console (PY-19853) Clear input buffer before waiting for input --- .../python/console/PydevConsoleExecuteActionHandler.java | 4 ++++ .../src/com/jetbrains/python/console/PythonConsoleView.java | 1 + 2 files changed, 5 insertions(+) diff --git a/python/src/com/jetbrains/python/console/PydevConsoleExecuteActionHandler.java b/python/src/com/jetbrains/python/console/PydevConsoleExecuteActionHandler.java index 4f1b10b78692..67f52844bfe9 100644 --- a/python/src/com/jetbrains/python/console/PydevConsoleExecuteActionHandler.java +++ b/python/src/com/jetbrains/python/console/PydevConsoleExecuteActionHandler.java @@ -100,6 +100,10 @@ public class PydevConsoleExecuteActionHandler extends ProcessBackedConsoleExecut sendLineToConsole(new ConsoleCommunication.ConsoleCodeFragment(myInputBuffer.toString(), false)); } + public void clearInputBuffer() { + myInputBuffer = null; + } + private void processOneLine(String line) { int indentSize = IndentHelperImpl.getIndent(getProject(), PythonFileType.INSTANCE, line, false); line = StringUtil.trimTrailing(line); diff --git a/python/src/com/jetbrains/python/console/PythonConsoleView.java b/python/src/com/jetbrains/python/console/PythonConsoleView.java index d6f4f63f0834..32b4dc981093 100644 --- a/python/src/com/jetbrains/python/console/PythonConsoleView.java +++ b/python/src/com/jetbrains/python/console/PythonConsoleView.java @@ -101,6 +101,7 @@ public class PythonConsoleView extends LanguageConsoleImpl implements Observable ((PythonDebugConsoleCommunication)consoleCommunication).waitingForInput = true; myExecuteActionHandler.inputRequested(); myExecuteActionHandler.setEnabled(true); + myExecuteActionHandler.clearInputBuffer(); } } From d0960c95eb238da5e886fba1ca978cfacb6f996b Mon Sep 17 00:00:00 2001 From: Elizaveta Shashkova Date: Wed, 22 Jun 2016 12:55:14 +0300 Subject: [PATCH 066/107] Fixes after review --- python/helpers/pydev/_pydev_bundle/pydev_console_utils.py | 2 +- .../python/console/PythonDebugConsoleCommunication.java | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/python/helpers/pydev/_pydev_bundle/pydev_console_utils.py b/python/helpers/pydev/_pydev_bundle/pydev_console_utils.py index 112d0ae36de9..c9078e14457d 100644 --- a/python/helpers/pydev/_pydev_bundle/pydev_console_utils.py +++ b/python/helpers/pydev/_pydev_bundle/pydev_console_utils.py @@ -132,11 +132,11 @@ class DebugConsoleStdIn(BaseStdIn): try: cmd = self.debugger.cmd_factory.make_input_requested_message() self.debugger.writer.add_command(cmd) - return self.original_stdin.readline(*args, **kwargs) except Exception: import traceback traceback.print_exc() return '\n' + return self.original_stdin.readline(*args, **kwargs) class CodeFragment: diff --git a/python/src/com/jetbrains/python/console/PythonDebugConsoleCommunication.java b/python/src/com/jetbrains/python/console/PythonDebugConsoleCommunication.java index e357c4dd89ab..ccf185786ece 100644 --- a/python/src/com/jetbrains/python/console/PythonDebugConsoleCommunication.java +++ b/python/src/com/jetbrains/python/console/PythonDebugConsoleCommunication.java @@ -89,9 +89,7 @@ public class PythonDebugConsoleCommunication extends AbstractConsoleCommunicatio if (processInput != null) { try { final Charset defaultCharset = EncodingProjectManager.getInstance(myDebugProcess.getProject()).getDefaultCharset(); - String text = code.getText(); - // we save previous command text!!! - processInput.write((text + "\n").getBytes(defaultCharset)); + processInput.write((code.getText() + "\n").getBytes(defaultCharset)); processInput.flush(); } catch (IOException e) { From 6adafab3647db23e1d2526190f4a580c3fe9a629 Mon Sep 17 00:00:00 2001 From: Elizaveta Shashkova Date: Wed, 22 Jun 2016 12:55:55 +0300 Subject: [PATCH 067/107] We shouldn't add new line character here --- .../python/console/PythonDebugConsoleCommunication.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/src/com/jetbrains/python/console/PythonDebugConsoleCommunication.java b/python/src/com/jetbrains/python/console/PythonDebugConsoleCommunication.java index ccf185786ece..78ecbf99578b 100644 --- a/python/src/com/jetbrains/python/console/PythonDebugConsoleCommunication.java +++ b/python/src/com/jetbrains/python/console/PythonDebugConsoleCommunication.java @@ -89,7 +89,7 @@ public class PythonDebugConsoleCommunication extends AbstractConsoleCommunicatio if (processInput != null) { try { final Charset defaultCharset = EncodingProjectManager.getInstance(myDebugProcess.getProject()).getDefaultCharset(); - processInput.write((code.getText() + "\n").getBytes(defaultCharset)); + processInput.write((code.getText()).getBytes(defaultCharset)); processInput.flush(); } catch (IOException e) { From f27aae5d8817448e404f18f57a3326174fbbdef0 Mon Sep 17 00:00:00 2001 From: Liana Bakradze Date: Fri, 24 Jun 2016 14:15:31 +0300 Subject: [PATCH 068/107] EDU-537 Empty task text with opened task files --- .../jetbrains/edu/learning/StudyBasePluginConfigurator.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/StudyBasePluginConfigurator.java b/python/educational-core/student/src/com/jetbrains/edu/learning/StudyBasePluginConfigurator.java index 99163eea7916..35ecc643f5bf 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/StudyBasePluginConfigurator.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/StudyBasePluginConfigurator.java @@ -56,6 +56,11 @@ public abstract class StudyBasePluginConfigurator implements StudyPluginConfigur @Override public void fileClosed(@NotNull FileEditorManager source, @NotNull VirtualFile file) { + for (VirtualFile openedFile : source.getOpenFiles()) { + if (StudyUtils.getTaskFile(project, openedFile) != null) { + return; + } + } toolWindow.setEmptyText(project); } From 76df9978039e5e8eeaf9d7faf00fcabe45eb4c54 Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Fri, 24 Jun 2016 14:06:36 +0300 Subject: [PATCH 069/107] EDU-644 Main toolwindow: hint for navigation between placeholders is lost --- .../src/com/jetbrains/edu/learning/StudyProjectComponent.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/StudyProjectComponent.java b/python/educational-core/student/src/com/jetbrains/edu/learning/StudyProjectComponent.java index cfb8faa2bbb0..5a505d0bb7f3 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/StudyProjectComponent.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/StudyProjectComponent.java @@ -26,6 +26,8 @@ import com.intellij.openapi.wm.ToolWindowAnchor; import com.intellij.openapi.wm.ToolWindowManager; import com.intellij.util.containers.hash.HashMap; import com.jetbrains.edu.learning.actions.StudyActionWithShortcut; +import com.jetbrains.edu.learning.actions.StudyNextWindowAction; +import com.jetbrains.edu.learning.actions.StudyPrevWindowAction; import com.jetbrains.edu.learning.core.EduNames; import com.jetbrains.edu.learning.core.EduUtils; import com.jetbrains.edu.learning.courseFormat.Course; @@ -113,6 +115,8 @@ public class StudyProjectComponent implements ProjectComponent { } } } + addShortcut(StudyNextWindowAction.ACTION_ID, new String[]{StudyNextWindowAction.SHORTCUT, StudyNextWindowAction.SHORTCUT2}); + addShortcut(StudyPrevWindowAction.ACTION_ID, new String[]{StudyPrevWindowAction.SHORTCUT}); } else { LOG.warn("Actions on toolbar are nulls"); From ba2c8bedea62e71f3cd751f9bd3ef71dd1f0c348 Mon Sep 17 00:00:00 2001 From: Liana Bakradze Date: Fri, 24 Jun 2016 15:00:17 +0300 Subject: [PATCH 070/107] EDU-322 Next Task: unnecessary jumping from Project Root to actual task position in a tree --- .../actions/StudyTaskNavigationAction.java | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/actions/StudyTaskNavigationAction.java b/python/educational-core/student/src/com/jetbrains/edu/learning/actions/StudyTaskNavigationAction.java index 363e73e37018..efc81bc33be7 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/actions/StudyTaskNavigationAction.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/actions/StudyTaskNavigationAction.java @@ -8,7 +8,6 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.wm.ToolWindow; import com.intellij.openapi.wm.ToolWindowId; import com.intellij.openapi.wm.ToolWindowManager; -import com.intellij.util.ui.tree.TreeUtil; import com.jetbrains.edu.learning.StudyState; import com.jetbrains.edu.learning.StudyUtils; import com.jetbrains.edu.learning.core.EduNames; @@ -44,9 +43,6 @@ abstract public class StudyTaskNavigationAction extends StudyActionWithShortcut int nextTaskIndex = nextTask.getIndex(); int lessonIndex = nextTask.getLesson().getIndex(); Map nextTaskFiles = nextTask.getTaskFiles(); - if (nextTaskFiles.isEmpty()) { - return; - } VirtualFile projectDir = project.getBaseDir(); String lessonDirName = EduNames.LESSON + String.valueOf(lessonIndex); if (projectDir == null) { @@ -61,15 +57,26 @@ abstract public class StudyTaskNavigationAction extends StudyActionWithShortcut if (taskDir == null) { return; } + if (nextTaskFiles.isEmpty()) { + ProjectView.getInstance(project).select(taskDir, taskDir, false); + return; + } VirtualFile shouldBeActive = getFileToActivate(project, nextTaskFiles, taskDir); JTree tree = ProjectView.getInstance(project).getCurrentProjectViewPane().getTree(); - TreePath path = TreeUtil.getFirstNodePath(tree); - tree.collapsePath(path); + TreePath path = tree.getSelectionPath(); + if (path != null) { + TreePath oldSelectionPath = path.getParentPath(); + if (oldSelectionPath != null) { + tree.collapsePath(oldSelectionPath); + tree.fireTreeCollapsed(oldSelectionPath); + } + } if (shouldBeActive != null) { ProjectView.getInstance(project).select(shouldBeActive, shouldBeActive, false); FileEditorManager.getInstance(project).openFile(shouldBeActive, true); } + ToolWindow runToolWindow = ToolWindowManager.getInstance(project).getToolWindow(ToolWindowId.RUN); if (runToolWindow != null) { runToolWindow.hide(null); @@ -82,7 +89,7 @@ abstract public class StudyTaskNavigationAction extends StudyActionWithShortcut for (Map.Entry entry : nextTaskFiles.entrySet()) { String name = entry.getKey(); TaskFile taskFile = entry.getValue(); - VirtualFile srcDir = taskDir.findChild("src"); + VirtualFile srcDir = taskDir.findChild(EduNames.SRC); VirtualFile vf = srcDir == null ? taskDir.findChild(name) : srcDir.findChild(name); if (vf != null) { FileEditorManager.getInstance(project).openFile(vf, true); From 343aa6cab9ee3bc67c511db206045fdfef882bc8 Mon Sep 17 00:00:00 2001 From: Liana Bakradze Date: Fri, 24 Jun 2016 15:08:11 +0300 Subject: [PATCH 071/107] EDU-536 Open task file with placeholders when new task opened --- .../edu/learning/actions/StudyTaskNavigationAction.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/python/educational-core/student/src/com/jetbrains/edu/learning/actions/StudyTaskNavigationAction.java b/python/educational-core/student/src/com/jetbrains/edu/learning/actions/StudyTaskNavigationAction.java index efc81bc33be7..97495aad8f0d 100644 --- a/python/educational-core/student/src/com/jetbrains/edu/learning/actions/StudyTaskNavigationAction.java +++ b/python/educational-core/student/src/com/jetbrains/edu/learning/actions/StudyTaskNavigationAction.java @@ -92,8 +92,10 @@ abstract public class StudyTaskNavigationAction extends StudyActionWithShortcut VirtualFile srcDir = taskDir.findChild(EduNames.SRC); VirtualFile vf = srcDir == null ? taskDir.findChild(name) : srcDir.findChild(name); if (vf != null) { - FileEditorManager.getInstance(project).openFile(vf, true); - if (!taskFile.getAnswerPlaceholders().isEmpty()) { + if (shouldBeActive != null) { + FileEditorManager.getInstance(project).openFile(vf, true); + } + if (shouldBeActive == null && !taskFile.getAnswerPlaceholders().isEmpty()) { shouldBeActive = vf; } } From b16891ee2d7fd221c270368eb3b36c20870f0677 Mon Sep 17 00:00:00 2001 From: Nadya Zabrodina Date: Tue, 21 Jun 2016 12:28:25 +0300 Subject: [PATCH 072/107] [vcs]: refactor NewEditChangelist panel to be able provide more complex component for names; * provide inner wrapper for future usages; * style: use DocumentAdapter; * cleanup; --- .../changes/ui/NewEditChangelistPanel.java | 48 +++++++++++++------ 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/NewEditChangelistPanel.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/NewEditChangelistPanel.java index e9a1fa117556..c3f502c3e0c9 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/NewEditChangelistPanel.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/NewEditChangelistPanel.java @@ -17,8 +17,8 @@ package com.intellij.openapi.vcs.changes.ui; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.editor.SpellCheckingEditorCustomizationProvider; +import com.intellij.openapi.editor.event.DocumentAdapter; import com.intellij.openapi.editor.event.DocumentEvent; -import com.intellij.openapi.editor.event.DocumentListener; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.fileTypes.FileTypes; import com.intellij.openapi.project.Project; @@ -30,19 +30,20 @@ import com.intellij.ui.*; import com.intellij.util.Consumer; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.JBUI; +import org.jetbrains.annotations.NotNull; import javax.swing.*; import java.awt.*; import java.util.Set; public abstract class NewEditChangelistPanel extends JPanel { - private EditorTextField myNameTextField; - private EditorTextField myDescriptionTextArea; - private JPanel myAdditionalControlsPanel; - private JCheckBox myMakeActiveCheckBox; + private final EditorTextField myNameTextField; + private final EditorTextField myDescriptionTextArea; + private final JPanel myAdditionalControlsPanel; + private final JCheckBox myMakeActiveCheckBox; private Consumer myConsumer; - private final Project myProject; + protected final Project myProject; public NewEditChangelistPanel(final Project project) { super(new GridBagLayout()); @@ -52,14 +53,15 @@ public abstract class NewEditChangelistPanel extends JPanel { final JLabel nameLabel = new JLabel(VcsBundle.message("edit.changelist.name")); add(nameLabel, gb); - ++ gb.gridx; + ++gb.gridx; gb.fill = GridBagConstraints.HORIZONTAL; gb.weightx = 1; - myNameTextField = createEditorField(project, 1); + ComponentWithTextFieldWrapper componentWithTextField = createComponentWithTextField(project); + myNameTextField = componentWithTextField.getEditorTextField(); myNameTextField.setOneLineMode(true); myNameTextField.setText("New changelist"); myNameTextField.selectAll(); - add(myNameTextField, gb); + add(componentWithTextField.myComponent, gb); nameLabel.setLabelFor(myNameTextField); ++ gb.gridy; @@ -100,11 +102,7 @@ public abstract class NewEditChangelistPanel extends JPanel { support.installSearch(myNameTextField, myDescriptionTextArea); myConsumer = support.addControls(myAdditionalControlsPanel, initial); } - myNameTextField.getDocument().addDocumentListener(new DocumentListener() { - @Override - public void beforeDocumentChange(DocumentEvent event) { - } - + myNameTextField.getDocument().addDocumentListener(new DocumentAdapter() { @Override public void documentChanged(DocumentEvent event) { nameChangedImpl(myProject, initial); @@ -160,6 +158,17 @@ public abstract class NewEditChangelistPanel extends JPanel { protected abstract void nameChanged(String errorMessage); + protected ComponentWithTextFieldWrapper createComponentWithTextField(Project project) { + final EditorTextField editorTextField = createEditorField(project, 1); + return new ComponentWithTextFieldWrapper(editorTextField) { + @NotNull + @Override + public EditorTextField getEditorTextField() { + return editorTextField; + } + }; + } + private static EditorTextField createEditorField(final Project project, final int defaultLines) { final EditorTextFieldProvider service = ServiceManager.getService(project, EditorTextFieldProvider.class); final EditorTextField editorField; @@ -178,4 +187,15 @@ public abstract class NewEditChangelistPanel extends JPanel { editorField.getComponent().setMinimumSize(new Dimension(100, (int)(height * 1.3))); return editorField; } + + protected abstract static class ComponentWithTextFieldWrapper { + @NotNull private final Component myComponent; + + public ComponentWithTextFieldWrapper(@NotNull Component component) { + myComponent = component; + } + + @NotNull + abstract EditorTextField getEditorTextField(); + } } From 873214c889caf37a003a16ad08d006e041e80b16 Mon Sep 17 00:00:00 2001 From: Nadya Zabrodina Date: Tue, 21 Jun 2016 12:59:32 +0300 Subject: [PATCH 073/107] [vcs]: change ui/ux for ChangeListChooser (IDEA-153163, IDEA-150818) * get rid of radio button, use editable combobox instead; * update description if exist; * change combobox model from local changelist to string; remove linkRenderer bacause links are not clickable anyway; --- .../changes/ui/ChangeListChooserPanel.form | 50 ---- .../changes/ui/ChangeListChooserPanel.java | 220 ++++++++---------- 2 files changed, 103 insertions(+), 167 deletions(-) delete mode 100644 platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooserPanel.form diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooserPanel.form b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooserPanel.form deleted file mode 100644 index 7228db028df1..000000000000 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooserPanel.form +++ /dev/null @@ -1,50 +0,0 @@ - -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooserPanel.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooserPanel.java index 363d5f1e319f..11b9be18052e 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooserPanel.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooserPanel.java @@ -15,161 +15,144 @@ */ package com.intellij.openapi.vcs.changes.ui; +import com.intellij.openapi.fileTypes.FileTypes; import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.ui.ComboBox; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.vcs.VcsBundle; import com.intellij.openapi.vcs.VcsConfiguration; import com.intellij.openapi.vcs.changes.ChangeList; import com.intellij.openapi.vcs.changes.ChangeListManager; import com.intellij.openapi.vcs.changes.LocalChangeList; import com.intellij.openapi.vcs.changes.committed.CommittedChangeListRenderer; -import com.intellij.openapi.vcs.changes.issueLinks.IssueLinkRenderer; -import com.intellij.openapi.wm.IdeFocusManager; import com.intellij.ui.*; import com.intellij.util.NullableConsumer; -import com.intellij.util.ui.UIUtil; +import com.intellij.util.ObjectUtils; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; -import java.awt.event.FocusAdapter; -import java.awt.event.FocusEvent; -import java.awt.event.ItemEvent; -import java.awt.event.ItemListener; -import java.util.*; +import java.util.Collection; +import java.util.Collections; import java.util.List; -/** - * @author yole - */ public class ChangeListChooserPanel extends JPanel { - private static final Comparator CHANGE_LIST_COMPARATOR = new Comparator() { - @Override - public int compare(ChangeList o1, ChangeList o2) { - return o1.getName().compareToIgnoreCase(o2.getName()); - } - }; - private JPanel myPanel; - private JRadioButton myRbExisting; - private JRadioButton myRbNew; - private JComboBox myExistingListsCombo; - private NewEditChangelistPanel myNewListPanel; + private final MyEditorComboBox myExistingListsCombo; + private final NewEditChangelistPanel myListPanel; private final NullableConsumer myOkEnabledListener; - private Project myProject; + private final Project myProject; public ChangeListChooserPanel(final Project project, @NotNull final NullableConsumer okEnabledListener) { super(new BorderLayout()); myProject = project; - myOkEnabledListener = okEnabledListener; - add(myPanel, BorderLayout.CENTER); - - myRbExisting.addItemListener(new ItemListener() { - public void itemStateChanged(ItemEvent e) { - updateEnabledItems(); - } - }); - } - - public void init() { - myExistingListsCombo.setRenderer(new ColoredListCellRendererWrapper() { - private final IssueLinkRenderer myLinkRenderer = new IssueLinkRenderer(myProject, this); - + myExistingListsCombo = new MyEditorComboBox(project); + myExistingListsCombo.setEditable(true); + myExistingListsCombo.setRenderer(new ColoredListCellRenderer() { @Override - protected void doCustomize(JList list, Object value, int index, boolean selected, boolean hasFocus) { - if (value instanceof LocalChangeList) { - String name = ((LocalChangeList) value).getName(); - - if (myExistingListsCombo.getWidth() == 0) { + protected void customizeCellRenderer(@NotNull JList list, + String value, + int index, + boolean selected, + boolean hasFocus) { + if (value != null) { + String name = value; + LocalChangeList changeList = ChangeListManager.getInstance(myProject).findChangeList(name); + int visibleWidth = myExistingListsCombo.getEditorTextField().getVisibleRect().width; + if (visibleWidth == 0) { name = name.length() > 10 ? name.substring(0, 7) + " .." : name; } else { final FontMetrics fm = list.getFontMetrics(list.getFont()); final int width = fm.stringWidth(name); - final int listWidth = myExistingListsCombo.getWidth(); - if ((listWidth > 0) && (width > listWidth)) { - final String truncated = CommittedChangeListRenderer.truncateDescription(name, fm, listWidth - fm.stringWidth(" ..") - 7); + if ((visibleWidth > 0) && (width > visibleWidth)) { + final String truncated = CommittedChangeListRenderer + .truncateDescription(name, fm, visibleWidth - fm.stringWidth(" ..") - 7); if (truncated.length() > 5) { name = truncated + " .."; } } } - myLinkRenderer.appendTextWithLinks(name, ((LocalChangeList)value).isDefault() - ? SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES : SimpleTextAttributes.REGULAR_ATTRIBUTES); + append(name, changeList != null && changeList.isDefault() + ? SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES + : SimpleTextAttributes.REGULAR_ATTRIBUTES); } } }); - myNewListPanel.init(null); - myRbNew.addFocusListener(new FocusAdapter() { + myListPanel = new NewEditChangelistPanel(myProject) { + @Override - public void focusGained(FocusEvent e) { - if (myRbNew.isSelected()) { - IdeFocusManager.getInstance(myProject).requestFocus(myNewListPanel.getPreferredFocusedComponent(), true); - } + protected NewEditChangelistPanel.ComponentWithTextFieldWrapper createComponentWithTextField(Project project) { + return new ComponentWithTextFieldWrapper(myExistingListsCombo) { + @NotNull + @Override + public EditorTextField getEditorTextField() { + return myExistingListsCombo.getEditorTextField(); + } + }; } - }); - final ComboboxSpeedSearch search = new ComboboxSpeedSearch(myExistingListsCombo); - search.setComparator(new SpeedSearchComparator(true, false)); + + @Override + protected void nameChanged(String errorMessage) { + LocalChangeList list = getExistingChangelist(); + setDescription(list != null ? list.getComment() : ""); + myOkEnabledListener.consume(errorMessage); + } + + @Override + protected void nameChangedImpl(Project project, LocalChangeList initial) { + nameChanged(StringUtil.isEmptyOrSpaces(getChangeListName()) ? "Cannot create new changelist with empty name." : null); + } + }; + myOkEnabledListener = okEnabledListener; + add(myListPanel, BorderLayout.CENTER); + } + + public void init() { + myListPanel.init(null); } public void setChangeLists(Collection changeLists) { - List list = new ArrayList(changeLists); - Collections.sort(list, CHANGE_LIST_COMPARATOR); - myExistingListsCombo.setModel(new CollectionComboBoxModel(list, null)); + List changelistNames = ContainerUtil.map(changeLists, ChangeList::getName); + Collections.sort(changelistNames); + myExistingListsCombo.setModel(new CollectionComboBoxModel(changelistNames)); } public void setDefaultName(String name) { - if (! StringUtil.isEmptyOrSpaces(name)) { - myNewListPanel.setChangeListName(name); + if (!StringUtil.isEmptyOrSpaces(name)) { + myListPanel.setChangeListName(name); } } private void updateEnabledItems() { - if (myRbExisting.isSelected()) { - myExistingListsCombo.setEnabled(true); - UIUtil.setEnabled(myNewListPanel, false, true); - myExistingListsCombo.requestFocus(); - } - else { - myExistingListsCombo.setEnabled(false); - UIUtil.setEnabled(myNewListPanel, true, true); - myNewListPanel.requestFocus(); - } if (myProject != null) { - myNewListPanel.nameChangedImpl(myProject, null); + myListPanel.nameChangedImpl(myProject, null); } } + /** + * Method used as getResult, usually invoked inside doOkAction + */ @Nullable public LocalChangeList getSelectedList(Project project) { ChangeListManager manager = ChangeListManager.getInstance(project); - if (myRbNew.isSelected()) { - String newText = myNewListPanel.getChangeListName(); - if (manager.findChangeList(newText) != null) { - Messages.showErrorDialog(project, - VcsBundle.message("changes.newchangelist.warning.already.exists.text", newText), - VcsBundle.message("changes.newchangelist.warning.already.exists.title")); - return null; - } - } - final boolean existingSelected = myRbExisting.isSelected(); - VcsConfiguration.getInstance(myProject).PRESELECT_EXISTING_CHANGELIST = existingSelected; + String changeListName = myListPanel.getChangeListName(); + LocalChangeList localChangeList = manager.findChangeList(changeListName); - if (existingSelected) { - return (LocalChangeList)myExistingListsCombo.getSelectedItem(); + if (localChangeList == null) { + localChangeList = manager.addChangeList(changeListName, myListPanel.getDescription()); + myListPanel.changelistCreatedOrChanged(localChangeList); } else { - LocalChangeList changeList = manager.addChangeList(myNewListPanel.getChangeListName(), myNewListPanel.getDescription()); - myNewListPanel.changelistCreatedOrChanged(changeList); - if (myNewListPanel.getMakeActiveCheckBox().isSelected()) { - manager.setDefaultChangeList(changeList); - } - VcsConfiguration.getInstance(project).MAKE_NEW_CHANGELIST_ACTIVE = myNewListPanel.getMakeActiveCheckBox().isSelected(); - - return changeList; + //update description if changed + localChangeList.setComment(myListPanel.getDescription()); } + if (myListPanel.getMakeActiveCheckBox().isSelected()) { + manager.setDefaultChangeList(localChangeList); + } + VcsConfiguration.getInstance(project).MAKE_NEW_CHANGELIST_ACTIVE = myListPanel.getMakeActiveCheckBox().isSelected(); + return localChangeList; } public void setDefaultSelection(final ChangeList defaultSelection) { @@ -177,34 +160,37 @@ public class ChangeListChooserPanel extends JPanel { myExistingListsCombo.setSelectedIndex(0); } else { - myExistingListsCombo.setSelectedItem(defaultSelection); + myExistingListsCombo.setSelectedItem(defaultSelection.getName()); } - //if defaultSelection was predefined as null then it means we could not use existing is this context - if (defaultSelection != null && VcsConfiguration.getInstance(myProject).PRESELECT_EXISTING_CHANGELIST) { - myRbExisting.setSelected(true); - } - else { - myRbNew.setSelected(true); - } - + updateDescription(); updateEnabledItems(); } - public JComponent getPreferredFocusedComponent() { - return myRbExisting.isSelected() ? myExistingListsCombo : myNewListPanel.getPreferredFocusedComponent(); + private void updateDescription() { + LocalChangeList list = getExistingChangelist(); + myListPanel.setDescription(list != null ? list.getComment() : ""); } - private void createUIComponents() { - myNewListPanel = new NewEditChangelistPanel(myProject) { + private LocalChangeList getExistingChangelist() { + ChangeListManager manager = ChangeListManager.getInstance(myProject); + String changeListName = myListPanel.getChangeListName(); + return manager.findChangeList(changeListName); + } - @Override - protected void nameChanged(String errorMessage) { - if (myRbExisting.isSelected()) { - myOkEnabledListener.consume(null); - } else { - myOkEnabledListener.consume(errorMessage); - } - } - }; + public JComponent getPreferredFocusedComponent() { + return myExistingListsCombo; + } + + private static class MyEditorComboBox extends ComboBox { + + public MyEditorComboBox(Project project) { + super(); + setEditor(new StringComboboxEditor(project, FileTypes.PLAIN_TEXT, this)); + } + + @NotNull + private EditorTextField getEditorTextField() { + return ObjectUtils.assertNotNull((EditorTextField)getEditor().getEditorComponent()); + } } } From 8900f469e1ca86a6935b8924a54d95c28d174d0a Mon Sep 17 00:00:00 2001 From: Nadya Zabrodina Date: Tue, 21 Jun 2016 13:45:53 +0300 Subject: [PATCH 074/107] [vcs]: provide full completion for move to another changelist panel including combobox model and tasks from task plugin --- .../completion/ComboEditorCompletionContributor.java | 7 ++++++- .../vcs/changes/ui/ChangeListChooserPanel.java | 11 ++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/ComboEditorCompletionContributor.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/ComboEditorCompletionContributor.java index 59159a84a440..0246e779a10a 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/ComboEditorCompletionContributor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/ComboEditorCompletionContributor.java @@ -18,6 +18,7 @@ package com.intellij.codeInsight.completion; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupElementBuilder; import com.intellij.openapi.editor.Document; +import com.intellij.openapi.util.Key; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; import com.intellij.ui.StringComboboxEditor; @@ -30,6 +31,8 @@ import javax.swing.*; */ public class ComboEditorCompletionContributor extends CompletionContributor{ + public static final Key CONTINUE_RUN_COMPLETION = Key.create("CONTINUE_RUN_COMPLETION"); + @Override public void fillCompletionVariants(@NotNull final CompletionParameters parameters, @NotNull final CompletionResultSet result) { if (parameters.getInvocationCount() == 0) { @@ -60,7 +63,9 @@ public class ComboEditorCompletionContributor extends CompletionContributor{ }), count-i)); } } - result.stopHere(); + if (!Boolean.TRUE.equals(document.getUserData(CONTINUE_RUN_COMPLETION))) { + result.stopHere(); + } } } } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooserPanel.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooserPanel.java index 11b9be18052e..bf679b26b99c 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooserPanel.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooserPanel.java @@ -15,6 +15,7 @@ */ package com.intellij.openapi.vcs.changes.ui; +import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.fileTypes.FileTypes; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.ComboBox; @@ -37,6 +38,8 @@ import java.util.Collection; import java.util.Collections; import java.util.List; +import static com.intellij.codeInsight.completion.ComboEditorCompletionContributor.CONTINUE_RUN_COMPLETION; + public class ChangeListChooserPanel extends JPanel { private final MyEditorComboBox myExistingListsCombo; @@ -185,7 +188,13 @@ public class ChangeListChooserPanel extends JPanel { public MyEditorComboBox(Project project) { super(); - setEditor(new StringComboboxEditor(project, FileTypes.PLAIN_TEXT, this)); + setEditor(new StringComboboxEditor(project, FileTypes.PLAIN_TEXT, this) { + @Override + protected void onEditorCreate(EditorEx editor) { + super.onEditorCreate(editor); + getDocument().putUserData(CONTINUE_RUN_COMPLETION, true); + } + }); } @NotNull From 55da3bcd9a0acb9cf9e7d61c5de15d5522869e9a Mon Sep 17 00:00:00 2001 From: Nadya Zabrodina Date: Tue, 21 Jun 2016 17:29:21 +0300 Subject: [PATCH 075/107] [vcs]: support undo * without invokeLater undo changelist name may lead to unable undo action for description: error message will be shown; --- .../openapi/vcs/changes/ui/ChangeListChooserPanel.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooserPanel.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooserPanel.java index bf679b26b99c..842e79e66848 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooserPanel.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooserPanel.java @@ -15,6 +15,8 @@ */ package com.intellij.openapi.vcs.changes.ui; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.fileTypes.FileTypes; import com.intellij.openapi.project.Project; @@ -29,6 +31,7 @@ import com.intellij.ui.*; import com.intellij.util.NullableConsumer; import com.intellij.util.ObjectUtils; import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.CalledInAwt; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -97,9 +100,10 @@ public class ChangeListChooserPanel extends JPanel { } @Override + @CalledInAwt protected void nameChanged(String errorMessage) { - LocalChangeList list = getExistingChangelist(); - setDescription(list != null ? list.getComment() : ""); + //invoke later because of undo manager problem: when you try to undo changelist after description was already changed manually + ApplicationManager.getApplication().invokeLater(() -> updateDescription(), ModalityState.current()); myOkEnabledListener.consume(errorMessage); } From e9bcb80a3938dc5598279545ad5e6e09ebf9102c Mon Sep 17 00:00:00 2001 From: Nadya Zabrodina Date: Fri, 17 Jun 2016 15:27:37 +0300 Subject: [PATCH 076/107] [vcs]: IDEA-154192 improve ok action enabled status for Unshelve Changes dialog; cleanUp; --- .../patch/ApplyPatchDifferentiatedDialog.java | 17 ++++++++++++----- .../vcs/changes/ui/ChangeListChooserPanel.java | 4 ++-- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchDifferentiatedDialog.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchDifferentiatedDialog.java index 3a4f74e753e6..6d234ea67fd7 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchDifferentiatedDialog.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/ApplyPatchDifferentiatedDialog.java @@ -60,7 +60,6 @@ import com.intellij.ui.*; import com.intellij.util.Alarm; import com.intellij.util.Consumer; import com.intellij.util.containers.ContainerUtil; -import com.intellij.util.containers.Convertor; import com.intellij.util.containers.MultiMap; import com.intellij.util.ui.JBUI; import com.intellij.util.ui.UIUtil; @@ -196,7 +195,7 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper { myReset = myCanChangePatchFile ? this::reset : EmptyRunnable.getInstance(); myChangeListChooser = new ChangeListChooserPanel(project, errorMessage -> { - setOKActionEnabled(errorMessage == null); + setOKActionEnabled(errorMessage == null && isChangeTreeEnabled()); setErrorText(errorMessage); }); ChangeListManager changeListManager = ChangeListManager.getInstance(project); @@ -244,7 +243,15 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper { } private void updateOkActions() { - setOKActionEnabled(!myChangesTreeList.getIncludedChanges().isEmpty()); + boolean changeTreeEnabled = isChangeTreeEnabled(); + setOKActionEnabled(changeTreeEnabled); + if (changeTreeEnabled) { + myChangeListChooser.updateEnabled(); + } + } + + private boolean isChangeTreeEnabled() { + return !myChangesTreeList.getIncludedChanges().isEmpty(); } private void queueRequest() { @@ -371,6 +378,7 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper { myReader = patchReader; updateTree(true); paintBusy(false); + updateOkActions(); }, ModalityState.stateForComponent(myCenterPanel)); } } @@ -519,8 +527,7 @@ public class ApplyPatchDifferentiatedDialog extends DialogWrapper { protected DefaultTreeModel buildTreeModel(List changes, ChangeNodeDecorator changeNodeDecorator) { TreeModelBuilder builder = new TreeModelBuilder(myProject, isShowFlatten()); - return builder.buildModel(ObjectsConvertor.convert(changes, - (Convertor)o -> o), changeNodeDecorator); + return builder.buildModel(ObjectsConvertor.convert(changes, o -> o), changeNodeDecorator); } @Override diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooserPanel.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooserPanel.java index 842e79e66848..7d4a4c21d50e 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooserPanel.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooserPanel.java @@ -132,7 +132,7 @@ public class ChangeListChooserPanel extends JPanel { } } - private void updateEnabledItems() { + public void updateEnabled() { if (myProject != null) { myListPanel.nameChangedImpl(myProject, null); } @@ -170,7 +170,7 @@ public class ChangeListChooserPanel extends JPanel { myExistingListsCombo.setSelectedItem(defaultSelection.getName()); } updateDescription(); - updateEnabledItems(); + updateEnabled(); } private void updateDescription() { From 193e9df1b225d3e3f39edb7fa9fefb468323a912 Mon Sep 17 00:00:00 2001 From: Nadya Zabrodina Date: Wed, 22 Jun 2016 12:28:53 +0300 Subject: [PATCH 077/107] [completion]: make editorComboBox completion for String ComboBoxes available during dumb mode --- .../completion/ComboEditorCompletionContributor.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/ComboEditorCompletionContributor.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/ComboEditorCompletionContributor.java index 0246e779a10a..10994f07e85b 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/ComboEditorCompletionContributor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/ComboEditorCompletionContributor.java @@ -18,6 +18,7 @@ package com.intellij.codeInsight.completion; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupElementBuilder; import com.intellij.openapi.editor.Document; +import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.util.Key; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiFile; @@ -29,7 +30,7 @@ import javax.swing.*; /** * @author peter */ -public class ComboEditorCompletionContributor extends CompletionContributor{ +public class ComboEditorCompletionContributor extends CompletionContributor implements DumbAware { public static final Key CONTINUE_RUN_COMPLETION = Key.create("CONTINUE_RUN_COMPLETION"); From 619176bba75d528485fbe62ee746573a093cf087 Mon Sep 17 00:00:00 2001 From: Nadya Zabrodina Date: Thu, 23 Jun 2016 17:01:13 +0300 Subject: [PATCH 078/107] [vcs]: use last typed description for new changelist instead of empty one --- .../changes/ui/ChangeListChooserPanel.java | 22 ++++++++++++++++++- .../changes/ui/NewEditChangelistPanel.java | 4 ++-- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooserPanel.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooserPanel.java index 7d4a4c21d50e..1c93f351669a 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooserPanel.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangeListChooserPanel.java @@ -37,6 +37,8 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; import java.util.Collection; import java.util.Collections; import java.util.List; @@ -49,6 +51,7 @@ public class ChangeListChooserPanel extends JPanel { private final NewEditChangelistPanel myListPanel; private final NullableConsumer myOkEnabledListener; private final Project myProject; + private String myLastTypedDescription; public ChangeListChooserPanel(final Project project, @NotNull final NullableConsumer okEnabledListener) { super(new BorderLayout()); @@ -107,6 +110,20 @@ public class ChangeListChooserPanel extends JPanel { myOkEnabledListener.consume(errorMessage); } + @Override + public void init(LocalChangeList initial) { + super.init(initial); + myDescriptionTextArea.addFocusListener(new FocusAdapter() { + @Override + public void focusLost(FocusEvent e) { + super.focusLost(e); + if (getExistingChangelist() == null) { + myLastTypedDescription = myListPanel.getDescription(); + } + } + }); + } + @Override protected void nameChangedImpl(Project project, LocalChangeList initial) { nameChanged(StringUtil.isEmptyOrSpaces(getChangeListName()) ? "Cannot create new changelist with empty name." : null); @@ -175,7 +192,10 @@ public class ChangeListChooserPanel extends JPanel { private void updateDescription() { LocalChangeList list = getExistingChangelist(); - myListPanel.setDescription(list != null ? list.getComment() : ""); + String newText = list != null ? list.getComment() : myLastTypedDescription; + if (!StringUtil.equals(myListPanel.getDescription(), newText)) { + myListPanel.setDescription(newText); + } } private LocalChangeList getExistingChangelist() { diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/NewEditChangelistPanel.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/NewEditChangelistPanel.java index c3f502c3e0c9..98260d3f6a08 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/NewEditChangelistPanel.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/NewEditChangelistPanel.java @@ -37,8 +37,8 @@ import java.awt.*; import java.util.Set; public abstract class NewEditChangelistPanel extends JPanel { - private final EditorTextField myNameTextField; - private final EditorTextField myDescriptionTextArea; + protected final EditorTextField myNameTextField; + protected final EditorTextField myDescriptionTextArea; private final JPanel myAdditionalControlsPanel; private final JCheckBox myMakeActiveCheckBox; From 3d1ce692151a3b4758d6a3bff828ee3637997d31 Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Fri, 24 Jun 2016 14:54:48 +0300 Subject: [PATCH 079/107] brought back error label listener --- .../python/newProject/actions/ProjectSpecificSettingsStep.java | 1 + 1 file changed, 1 insertion(+) diff --git a/python/ide/src/com/jetbrains/python/newProject/actions/ProjectSpecificSettingsStep.java b/python/ide/src/com/jetbrains/python/newProject/actions/ProjectSpecificSettingsStep.java index 1bdc5359402e..6952315028b8 100644 --- a/python/ide/src/com/jetbrains/python/newProject/actions/ProjectSpecificSettingsStep.java +++ b/python/ide/src/com/jetbrains/python/newProject/actions/ProjectSpecificSettingsStep.java @@ -139,6 +139,7 @@ public class ProjectSpecificSettingsStep extends ProjectSettingsStepBase impleme super.initGeneratorListeners(); if (myProjectGenerator instanceof PythonProjectGenerator) { ((PythonProjectGenerator)myProjectGenerator).addSettingsStateListener(this::checkValid); + myErrorLabel.addMouseListener(((PythonProjectGenerator)myProjectGenerator).getErrorLabelMouseListener()); } } From bb7d889d9c1921e391eeddae12da4c19fca48552 Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Fri, 24 Jun 2016 15:17:56 +0300 Subject: [PATCH 080/107] EDU-621, EDU-623 Disable PEP8 new line warning for python tasks Disable "too long line" from PEP8 by default --- .../edu/PyCharmEduInitialConfigurator.java | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/python/educational-python/src/com/jetbrains/python/edu/PyCharmEduInitialConfigurator.java b/python/educational-python/src/com/jetbrains/python/edu/PyCharmEduInitialConfigurator.java index 49d301b1c327..d479b31c6893 100644 --- a/python/educational-python/src/com/jetbrains/python/edu/PyCharmEduInitialConfigurator.java +++ b/python/educational-python/src/com/jetbrains/python/edu/PyCharmEduInitialConfigurator.java @@ -56,10 +56,15 @@ import com.intellij.openapi.project.ProjectManagerAdapter; import com.intellij.openapi.project.ex.ProjectManagerEx; import com.intellij.openapi.startup.StartupManager; import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.util.Key; import com.intellij.openapi.vfs.VfsUtil; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.wm.*; import com.intellij.platform.DirectoryProjectConfigurator; import com.intellij.platform.PlatformProjectViewOpener; +import com.intellij.profile.codeInspection.InspectionProjectProfileManager; +import com.intellij.psi.PsiDirectory; +import com.intellij.psi.PsiManager; import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.codeStyle.CodeStyleSettingsManager; import com.intellij.ui.treeStructure.Tree; @@ -68,6 +73,7 @@ import com.intellij.util.messages.MessageBus; import com.intellij.util.ui.tree.TreeUtil; import com.jetbrains.python.PythonLanguage; import com.jetbrains.python.codeInsight.PyCodeInsightSettings; +import com.jetbrains.python.inspections.PyPep8Inspection; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -77,6 +83,7 @@ import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.DefaultTreeModel; import javax.swing.tree.TreeNode; import javax.swing.tree.TreePath; +import java.util.Collections; import java.util.HashSet; import java.util.Set; @@ -201,7 +208,11 @@ public class PyCharmEduInitialConfigurator { @Override public void run() { if (project.isDisposed()) return; + updateInspectionsProfile(); + openProjectStructure(); + } + private void openProjectStructure() { ToolWindowManager.getInstance(project).invokeLater(new Runnable() { int count = 0; @@ -212,12 +223,24 @@ public class PyCharmEduInitialConfigurator { return; } ToolWindow toolWindow = ToolWindowManager.getInstance(project).getToolWindow("Project"); - if (toolWindow !=null && toolWindow.getType() != ToolWindowType.SLIDING) { + if (toolWindow != null && toolWindow.getType() != ToolWindowType.SLIDING) { toolWindow.activate(null); } } }); } + + private void updateInspectionsProfile() { + final String[] codes = new String[]{"W29", "E501"}; + final VirtualFile baseDir = project.getBaseDir(); + final PsiDirectory directory = PsiManager.getInstance(project).findDirectory(baseDir); + if (directory != null) { + InspectionProjectProfileManager.getInstance(project).getInspectionProfile().modifyToolSettings( + Key.create(PyPep8Inspection.INSPECTION_SHORT_NAME), directory, + inspection -> Collections.addAll(inspection.ignoredErrors, codes) + ); + } + } }); } }); From 951cdba7658d3a14469a4b93a6c771215002d2fe Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 24 Jun 2016 14:43:04 +0300 Subject: [PATCH 081/107] revert optimization: parameter types are compared for language level < 1.8 --- .../impl/source/tree/java/PsiMethodCallExpressionImpl.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodCallExpressionImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodCallExpressionImpl.java index 50b49e3b29b1..18ed26bd5e43 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodCallExpressionImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiMethodCallExpressionImpl.java @@ -237,9 +237,7 @@ public class PsiMethodCallExpressionImpl extends ExpressionPsiElement implements PsiType ret, JavaResolveResult result, LanguageLevel languageLevel) { - PsiSubstitutor substitutor = result instanceof MethodCandidateInfo && !PsiPolyExpressionUtil.isMethodCallTypeDependsOnInference(call, method) - ? ((MethodCandidateInfo)result).getSiteSubstitutor() - : result.getSubstitutor(); + PsiSubstitutor substitutor = result.getSubstitutor(); PsiType substitutedReturnType = substitutor.substitute(ret); if (substitutedReturnType == null) { return TypeConversionUtil.erasure(ret); From 3ee8b6d1e86cf888f3379e332811adae1a47189c Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 24 Jun 2016 15:31:03 +0300 Subject: [PATCH 082/107] unrelated defaults: correct type if super classes come from different jdks (both 1.8 but of different versions) --- .../intellij/psi/util/PsiSuperMethodUtil.java | 37 ++++++++++++++++++- .../com/intellij/psi/impl/TypeCorrector.java | 32 ++-------------- .../codeInsight/multipleJdks/java7/p/I.java | 4 ++ ...latedDefaultsFromDifferentJdkVersions.java | 3 ++ .../codeInsight/multipleJdks/java8/p/I.java | 4 ++ ...latedDefaultsFromDifferentJdkVersions.java | 8 ++++ .../MultipleJdksHighlightingTest.java | 12 +++++- 7 files changed, 67 insertions(+), 33 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/multipleJdks/java7/p/I.java create mode 100644 java/java-tests/testData/codeInsight/multipleJdks/java7/p/UnrelatedDefaultsFromDifferentJdkVersions.java create mode 100644 java/java-tests/testData/codeInsight/multipleJdks/java8/p/I.java create mode 100644 java/java-tests/testData/codeInsight/multipleJdks/java8/p/UnrelatedDefaultsFromDifferentJdkVersions.java diff --git a/java/java-psi-api/src/com/intellij/psi/util/PsiSuperMethodUtil.java b/java/java-psi-api/src/com/intellij/psi/util/PsiSuperMethodUtil.java index 2148bd45b3cb..641cb6e7ee88 100644 --- a/java/java-psi-api/src/com/intellij/psi/util/PsiSuperMethodUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/util/PsiSuperMethodUtil.java @@ -15,11 +15,15 @@ */ package com.intellij.psi.util; +import com.intellij.openapi.roots.FileIndexFacade; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; +import com.intellij.psi.search.GlobalSearchScope; import com.intellij.util.containers.HashSet; import gnu.trove.THashMap; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.LinkedHashSet; import java.util.List; @@ -111,6 +115,7 @@ public class PsiSuperMethodUtil { public static Map> collectOverrideEquivalents(@NotNull PsiClass aClass) { final Map> overrideEquivalent = new THashMap>(MethodSignatureUtil.METHOD_PARAMETERS_ERASURE_EQUALITY); + final GlobalSearchScope resolveScope = aClass.getResolveScope(); PsiClass[] supers = aClass.getSupers(); for (int i = 0; i < supers.length; i++) { PsiClass superClass = supers[i]; @@ -122,10 +127,12 @@ public class PsiSuperMethodUtil { if (subType) continue; final PsiSubstitutor superClassSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(superClass, aClass, PsiSubstitutor.EMPTY); for (HierarchicalMethodSignature hms : superClass.getVisibleSignatures()) { - final PsiMethod method = hms.getMethod(); + PsiMethod method = hms.getMethod(); if (MethodSignatureUtil.findMethodBySignature(aClass, method.getSignature(superClassSubstitutor), false) != null) continue; - final PsiClass containingClass = method.getContainingClass(); + final PsiClass containingClass = mapClass(method.getContainingClass(), resolveScope); if (containingClass == null) continue; + method = containingClass.findMethodBySignature(method, false); + if (method == null) continue; final PsiSubstitutor containingClassSubstitutor = TypeConversionUtil.getClassSubstitutor(containingClass, aClass, PsiSubstitutor.EMPTY); if (containingClassSubstitutor == null) continue; final PsiSubstitutor finalSubstitutor = @@ -141,4 +148,30 @@ public class PsiSuperMethodUtil { } return overrideEquivalent; } + + @Nullable + public static PsiClass mapClass(PsiClass psiClass, final GlobalSearchScope resolveScope) { + if (psiClass == null) return null; + String qualifiedName = psiClass.getQualifiedName(); + if (qualifiedName == null) { + return psiClass; + } + + PsiFile file = psiClass.getContainingFile(); + if (file == null || !file.getViewProvider().isPhysical()) { + return psiClass; + } + + final VirtualFile vFile = file.getVirtualFile(); + if (vFile == null) { + return psiClass; + } + + final FileIndexFacade index = FileIndexFacade.getInstance(file.getProject()); + if (!index.isInSource(vFile) && !index.isInLibrarySource(vFile) && !index.isInLibraryClasses(vFile)) { + return psiClass; + } + + return JavaPsiFacade.getInstance(psiClass.getProject()).findClass(qualifiedName, resolveScope); + } } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/TypeCorrector.java b/java/java-psi-impl/src/com/intellij/psi/impl/TypeCorrector.java index f6521658c6dc..d9fcf6bc3c50 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/TypeCorrector.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/TypeCorrector.java @@ -15,11 +15,10 @@ */ package com.intellij.psi.impl; -import com.intellij.openapi.roots.FileIndexFacade; -import com.intellij.openapi.vfs.VirtualFile; import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.*; import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.util.PsiSuperMethodUtil; import com.intellij.psi.util.PsiUtilCore; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; @@ -56,7 +55,7 @@ class TypeCorrector extends PsiTypeMapper { final PsiClassType.ClassResolveResult classResolveResult = classType.resolveGenerics(); final PsiClass psiClass = classResolveResult.getElement(); if (psiClass != null && classResolveResult.getSubstitutor() == PsiSubstitutor.EMPTY) { - final PsiClass mappedClass = mapClass(psiClass); + final PsiClass mappedClass = PsiSuperMethodUtil.mapClass(psiClass, myResolveScope); if (mappedClass == null || mappedClass == psiClass) return (T) classType; } } @@ -79,7 +78,7 @@ class TypeCorrector extends PsiTypeMapper { PsiUtilCore.ensureValid(psiClass); - final PsiClass mappedClass = mapClass(psiClass); + final PsiClass mappedClass = PsiSuperMethodUtil.mapClass(psiClass, myResolveScope); if (mappedClass == null) return classType; PsiClassType mappedType = new PsiCorrectedClassType(classType.getLanguageLevel(), @@ -89,31 +88,6 @@ class TypeCorrector extends PsiTypeMapper { return mappedType; } - @Nullable - private PsiClass mapClass(@NotNull PsiClass psiClass) { - String qualifiedName = psiClass.getQualifiedName(); - if (qualifiedName == null) { - return psiClass; - } - - PsiFile file = psiClass.getContainingFile(); - if (file == null || !file.getViewProvider().isPhysical()) { - return psiClass; - } - - final VirtualFile vFile = file.getVirtualFile(); - if (vFile == null) { - return psiClass; - } - - final FileIndexFacade index = FileIndexFacade.getInstance(file.getProject()); - if (!index.isInSource(vFile) && !index.isInLibrarySource(vFile) && !index.isInLibraryClasses(vFile)) { - return psiClass; - } - - return JavaPsiFacade.getInstance(psiClass.getProject()).findClass(qualifiedName, myResolveScope); - } - @NotNull private PsiSubstitutor mapSubstitutor(PsiClass originalClass, PsiClass mappedClass, PsiSubstitutor substitutor) { PsiTypeParameter[] typeParameters = mappedClass.getTypeParameters(); diff --git a/java/java-tests/testData/codeInsight/multipleJdks/java7/p/I.java b/java/java-tests/testData/codeInsight/multipleJdks/java7/p/I.java new file mode 100644 index 000000000000..30e62b5249e6 --- /dev/null +++ b/java/java-tests/testData/codeInsight/multipleJdks/java7/p/I.java @@ -0,0 +1,4 @@ +package p; +interface I { + default void foo(); +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/multipleJdks/java7/p/UnrelatedDefaultsFromDifferentJdkVersions.java b/java/java-tests/testData/codeInsight/multipleJdks/java7/p/UnrelatedDefaultsFromDifferentJdkVersions.java new file mode 100644 index 000000000000..52e05186d644 --- /dev/null +++ b/java/java-tests/testData/codeInsight/multipleJdks/java7/p/UnrelatedDefaultsFromDifferentJdkVersions.java @@ -0,0 +1,3 @@ +package p; + +public abstract class A implements I {} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/multipleJdks/java8/p/I.java b/java/java-tests/testData/codeInsight/multipleJdks/java8/p/I.java new file mode 100644 index 000000000000..30e62b5249e6 --- /dev/null +++ b/java/java-tests/testData/codeInsight/multipleJdks/java8/p/I.java @@ -0,0 +1,4 @@ +package p; +interface I { + default void foo(); +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/multipleJdks/java8/p/UnrelatedDefaultsFromDifferentJdkVersions.java b/java/java-tests/testData/codeInsight/multipleJdks/java8/p/UnrelatedDefaultsFromDifferentJdkVersions.java new file mode 100644 index 000000000000..ab93746c9c7d --- /dev/null +++ b/java/java-tests/testData/codeInsight/multipleJdks/java8/p/UnrelatedDefaultsFromDifferentJdkVersions.java @@ -0,0 +1,8 @@ +package p; + +class EmptyValueIterator extends A implements ValueIterator { + +} + +interface ValueIterator extends I {} + diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/MultipleJdksHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/MultipleJdksHighlightingTest.java index 874522ec38f7..4c6c21761f55 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/MultipleJdksHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/MultipleJdksHighlightingTest.java @@ -18,7 +18,6 @@ package com.intellij.codeInsight; import com.intellij.openapi.application.ex.PathManagerEx; import com.intellij.openapi.module.Module; -import com.intellij.openapi.roots.ModifiableRootModel; import com.intellij.openapi.roots.ModuleRootModificationUtil; import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.pom.java.LanguageLevel; @@ -26,7 +25,6 @@ import com.intellij.testFramework.IdeaTestUtil; import com.intellij.testFramework.UsefulTestCase; import com.intellij.testFramework.builders.JavaModuleFixtureBuilder; import com.intellij.testFramework.fixtures.*; -import com.intellij.util.Consumer; public class MultipleJdksHighlightingTest extends UsefulTestCase { @@ -197,6 +195,16 @@ public class MultipleJdksHighlightingTest extends UsefulTestCase { myFixture.checkHighlighting(); } + public void testUnrelatedDefaultsFromDifferentJdkVersions() throws Exception { + ModuleRootModificationUtil.addDependency(myJava8Module, myJava7Module); + myFixture.copyFileToProject("java7/p/I.java"); + myFixture.copyFileToProject("java8/p/I.java"); + + final String testName = getTestName(false); + myFixture.configureByFiles("java8/p/" + testName + ".java", "java7/p/" + testName + ".java"); + myFixture.checkHighlighting(); + } + private void doTestWithoutLibrary() { final String name = getTestName(false); myFixture.configureByFiles("java7/p/" + name + ".java", "java8/p/" + name + ".java"); From 94c2a1c3258aaf58b8fbf0f609cc3cd16b8cb162 Mon Sep 17 00:00:00 2001 From: Elizaveta Shashkova Date: Fri, 24 Jun 2016 15:46:46 +0300 Subject: [PATCH 083/107] Fix tests: we should always check if suspend policy "All" is supported for the breakpoint type. Otherwise we break Django template debugging --- python/src/com/jetbrains/python/debugger/PyDebugProcess.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/python/src/com/jetbrains/python/debugger/PyDebugProcess.java b/python/src/com/jetbrains/python/debugger/PyDebugProcess.java index 3ab7886b6237..3570746593d0 100644 --- a/python/src/com/jetbrains/python/debugger/PyDebugProcess.java +++ b/python/src/com/jetbrains/python/debugger/PyDebugProcess.java @@ -533,7 +533,8 @@ public class PyDebugProcess extends XDebugProcess implements IPyDebugProcess, Pr breakpoint = myRegisteredExceptionBreakpoints.get(exceptionName); } } - if ((breakpoint != null) && (breakpoint.getSuspendPolicy() == SuspendPolicy.ALL)) { + if ((breakpoint != null) && (breakpoint.getType().isSuspendThreadSupported()) && + (breakpoint.getSuspendPolicy() == SuspendPolicy.ALL)) { return true; } } @@ -855,7 +856,7 @@ public class PyDebugProcess extends XDebugProcess implements IPyDebugProcess, Pr } } if (breakpoint != null) { - if (breakpoint.getSuspendPolicy() == SuspendPolicy.ALL) { + if ((breakpoint.getType().isSuspendThreadSupported()) && (breakpoint.getSuspendPolicy() == SuspendPolicy.ALL)) { suspendAllOtherThreads(threadInfo); } } From 74276d773abb41c2616dd62a55999c961baf3f76 Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 24 Jun 2016 14:44:45 +0200 Subject: [PATCH 084/107] add FileBasedIndexImpl.processAllValues to iterate over file ids --- .../util/indexing/FileBasedIndexImpl.java | 155 +++++++++++------- 1 file changed, 97 insertions(+), 58 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java index 3ff4aa000ccd..fe96142f26cf 100644 --- a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java +++ b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java @@ -767,13 +767,15 @@ public class FileBasedIndexImpl extends FileBasedIndex { } } - processValuesImpl(indexId, dataKey, true, restrictToFile, new ValueProcessor() { - @Override - public boolean process(final VirtualFile file, final V value) { - values.add(value); - return true; - } - }, filter, null); + ValueProcessor processor = (file, value) -> { + values.add(value); + return true; + }; + if (restrictToFile != null) { + processValuesInOneFile(indexId, dataKey, restrictToFile, processor, filter); + } else { + processValuesInScope(indexId, dataKey, true, filter, null, processor); + } return values; } @@ -783,13 +785,10 @@ public class FileBasedIndexImpl extends FileBasedIndex { @NotNull K dataKey, @NotNull final GlobalSearchScope filter) { final Set files = new THashSet(); - processValuesImpl(indexId, dataKey, false, null, new ValueProcessor() { - @Override - public boolean process(final VirtualFile file, final V value) { - files.add(file); - return true; - } - }, filter, null); + processValuesInScope(indexId, dataKey, false, filter, null, (file, value) -> { + files.add(file); + return true; + }); return files; } @@ -807,7 +806,40 @@ public class FileBasedIndexImpl extends FileBasedIndex { @NotNull ValueProcessor processor, @NotNull GlobalSearchScope filter, @Nullable IdFilter idFilter) { - return processValuesImpl(indexId, dataKey, false, inFile, processor, filter, idFilter); + return inFile != null + ? processValuesInOneFile(indexId, dataKey, inFile, processor, filter) + : processValuesInScope(indexId, dataKey, false, filter, idFilter, processor); + } + + public interface IdValueProcessor { + /** + * @param fileId the id of the file that the value came from + * @param value a value to process + * @return false if no further processing is needed, true otherwise + */ + boolean process(int fileId, V value); + } + + /** + * Process values for a given index key together with their containing file ids. Note that project is supplied + * only to ensure that all the indices in that project are up to date; there's no guarantee that the processed file ids belong + * to this project. + */ + public boolean processAllValues(@NotNull ID indexId, + @NotNull K key, + @NotNull Project project, + @NotNull IdValueProcessor processor) { + return processValueIterator(indexId, key, null, GlobalSearchScope.allScope(project), valueIt -> { + while (valueIt.hasNext()) { + V value = valueIt.next(); + for (ValueContainer.IntIterator inputIdsIterator = valueIt.getInputIdsIterator(); inputIdsIterator.hasNext(); ) { + if (!processor.process(inputIdsIterator.next(), value)) { + return false; + } + } + } + return true; + }); } @Nullable @@ -854,54 +886,61 @@ public class FileBasedIndexImpl extends FileBasedIndex { return null; } - private boolean processValuesImpl(@NotNull final ID indexId, @NotNull final K dataKey, final boolean ensureValueProcessedOnce, - @Nullable final VirtualFile restrictToFile, @NotNull final ValueProcessor processor, - @NotNull final GlobalSearchScope scope, @Nullable final IdFilter idFilter) { - ThrowableConvertor, Boolean, StorageException> keyProcessor = - index -> { - final ValueContainer container = index.getData(dataKey); + private boolean processValuesInOneFile(@NotNull ID indexId, + @NotNull K dataKey, + @NotNull VirtualFile restrictToFile, + @NotNull ValueProcessor processor, @NotNull GlobalSearchScope scope) { + if (!(restrictToFile instanceof VirtualFileWithId)) return true; - boolean shouldContinue = true; + int restrictedFileId = getFileId(restrictToFile); + return processValueIterator(indexId, dataKey, restrictToFile, scope, valueIt -> { + while (valueIt.hasNext()) { + V value = valueIt.next(); + if (valueIt.getValueAssociationPredicate().contains(restrictedFileId) && !processor.process(restrictToFile, value)) { + return false; + } + } + return true; + }); + } - if (restrictToFile != null) { - if (restrictToFile instanceof VirtualFileWithId) { - final int restrictedFileId = getFileId(restrictToFile); - for (final ValueContainer.ValueIterator valueIt = container.getValueIterator(); valueIt.hasNext(); ) { - final V value = valueIt.next(); - if (valueIt.getValueAssociationPredicate().contains(restrictedFileId)) { - shouldContinue = processor.process(restrictToFile, value); - if (!shouldContinue) { - break; - } - } + private boolean processValuesInScope(@NotNull ID indexId, + @NotNull K dataKey, + boolean ensureValueProcessedOnce, + @NotNull GlobalSearchScope scope, + @Nullable IdFilter idFilter, + @NotNull ValueProcessor processor) { + PersistentFS fs = (PersistentFS)ManagingFS.getInstance(); + IdFilter filter = idFilter != null ? idFilter : projectIndexableFiles(scope.getProject()); + + return processValueIterator(indexId, dataKey, null, scope, valueIt -> { + while (valueIt.hasNext()) { + final V value = valueIt.next(); + for (final ValueContainer.IntIterator inputIdsIterator = valueIt.getInputIdsIterator(); inputIdsIterator.hasNext(); ) { + final int id = inputIdsIterator.next(); + if (filter != null && !filter.containsFileId(id)) continue; + VirtualFile file = IndexInfrastructure.findFileByIdIfCached(fs, id); + if (file != null && scope.accept(file)) { + if (!processor.process(file, value)) { + return false; + } + if (ensureValueProcessedOnce) { + break; // continue with the next value } } } - else { - final PersistentFS fs = (PersistentFS)ManagingFS.getInstance(); - final IdFilter filter = idFilter != null ? idFilter : projectIndexableFiles(scope.getProject()); - VALUES_LOOP: - for (final ValueContainer.ValueIterator valueIt = container.getValueIterator(); valueIt.hasNext(); ) { - final V value = valueIt.next(); - for (final ValueContainer.IntIterator inputIdsIterator = valueIt.getInputIdsIterator(); inputIdsIterator.hasNext(); ) { - final int id = inputIdsIterator.next(); - if (filter != null && !filter.containsFileId(id)) continue; - VirtualFile file = IndexInfrastructure.findFileByIdIfCached(fs, id); - if (file != null && scope.accept(file)) { - shouldContinue = processor.process(file, value); - if (!shouldContinue) { - break VALUES_LOOP; - } - if (ensureValueProcessedOnce) { - break; // continue with the next value - } - } - } - } - } - return shouldContinue; - }; - final Boolean result = processExceptions(indexId, restrictToFile, scope, keyProcessor); + } + return true; + }); + } + + private boolean processValueIterator(@NotNull ID indexId, + @NotNull K dataKey, + @Nullable VirtualFile restrictToFile, + @NotNull GlobalSearchScope scope, + @NotNull Processor> valueProcessor) { + final Boolean result = processExceptions(indexId, restrictToFile, scope, + index -> valueProcessor.process(index.getData(dataKey).getValueIterator())); return result == null || result.booleanValue(); } From 95b3d482d95c27dbb065a5d47c1de2133a85e39b Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 24 Jun 2016 14:57:17 +0200 Subject: [PATCH 085/107] more efficient use of indices in stub hierarchy --- .../impl/HierarchyServiceImpl.java | 71 ++++++++++++------- .../stubsHierarchy/impl/JavaStubIndexer.java | 10 +-- .../impl/StubHierarchyIndex.java | 35 ++++----- .../java/stubs/index/JavaUnitDescriptor.java | 4 +- .../stubsHierarchy/StubHierarchyIndexer.java | 5 +- .../impl/java/stubs/hierarchy/IndexTree.java | 18 ++++- .../psi/stubs/hierarchy/GrStubIndexer.java | 12 ++-- 7 files changed, 92 insertions(+), 63 deletions(-) diff --git a/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/HierarchyServiceImpl.java b/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/HierarchyServiceImpl.java index 31fa42faa53a..654729f0d1ba 100644 --- a/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/HierarchyServiceImpl.java +++ b/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/HierarchyServiceImpl.java @@ -19,13 +19,11 @@ import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressIndicatorProvider; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ProjectFileIndex; +import com.intellij.openapi.roots.ProjectRootManager; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.openapi.vfs.VirtualFileWithId; import com.intellij.psi.impl.java.stubs.hierarchy.IndexTree; -import com.intellij.psi.search.DelegatingGlobalSearchScope; -import com.intellij.psi.search.EverythingGlobalScope; -import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.stubsHierarchy.HierarchyService; import com.intellij.psi.util.CachedValue; import com.intellij.psi.util.CachedValueProvider; @@ -33,17 +31,18 @@ import com.intellij.psi.util.CachedValuesManager; import com.intellij.psi.util.PsiModificationTracker; import com.intellij.util.CachedValueBase; import com.intellij.util.indexing.FileBasedIndex; +import com.intellij.util.indexing.FileBasedIndexImpl; import org.jetbrains.annotations.NotNull; +import java.util.BitSet; + public class HierarchyServiceImpl extends HierarchyService { private static final SingleClassHierarchy EMPTY_HIERARCHY = new SingleClassHierarchy(Symbol.ClassSymbol.EMPTY_ARRAY); private final Project myProject; - private final ProjectFileIndex myFileIndex; private final CachedValue myHierarchy; public HierarchyServiceImpl(Project project) { myProject = project; - myFileIndex = ProjectFileIndex.SERVICE.getInstance(project); myHierarchy = CachedValuesManager.getManager(project).createCachedValue( () -> CachedValueProvider.Result.create(buildHierarchy(), PsiModificationTracker.MODIFICATION_COUNT), false); @@ -69,38 +68,56 @@ public class HierarchyServiceImpl extends HierarchyService { private SingleClassHierarchy buildHierarchy() { Symbols symbols = new Symbols(); StubEnter stubEnter = new StubEnter(symbols); + IdSets idSets = IdSets.getIdSets(myProject); - loadUnits(false, symbols.myNameEnvironment, stubEnter); + loadUnits(idSets.libraryFiles, StubHierarchyIndex.BINARY_FILES, symbols.myNameEnvironment, stubEnter); stubEnter.connect1(); - loadUnits(true, symbols.myNameEnvironment, stubEnter); + loadUnits(idSets.sourceFiles, StubHierarchyIndex.SOURCE_FILES, symbols.myNameEnvironment, stubEnter); stubEnter.connect2(); return symbols.createHierarchy(); } - private void loadUnits(boolean sourceMode, NameEnvironment names, StubEnter stubEnter) { - GlobalSearchScope scope = new DelegatingGlobalSearchScope(new EverythingGlobalScope(myProject)) { - @Override - public boolean contains(@NotNull VirtualFile file) { - return sourceMode ? myFileIndex.isInSourceContent(file) : myFileIndex.isInLibraryClasses(file); - } - }; + private void loadUnits(BitSet files, int indexKey, NameEnvironment names, StubEnter stubEnter) { ProgressIndicator indicator = ProgressIndicatorProvider.getGlobalProgressIndicator(); - FileBasedIndex index = FileBasedIndex.getInstance(); - for (String packageName : index.getAllKeys(StubHierarchyIndex.INDEX_ID, myProject)) { - QualifiedName pkg = StringUtil.isEmpty(packageName) ? null : names.fromString(packageName, true); - index.processValues(StubHierarchyIndex.INDEX_ID, packageName, null, new FileBasedIndex.ValueProcessor() { - int count = 0; - @Override - public boolean process(VirtualFile file, IndexTree.Unit unit) { - if (indicator != null && ++count % 128 == 0) indicator.checkCanceled(); - stubEnter.unitEnter(Translator.internNames(names, unit, ((VirtualFileWithId)file).getId(), pkg)); - return true; + FileBasedIndexImpl index = (FileBasedIndexImpl)FileBasedIndex.getInstance(); + index.processAllValues(StubHierarchyIndex.INDEX_ID, indexKey, myProject, new FileBasedIndexImpl.IdValueProcessor() { + int count = 0; + @Override + public boolean process(int fileId, IndexTree.Unit unit) { + if (indicator != null && ++count % 128 == 0) indicator.checkCanceled(); + if (files.get(fileId)) { + QualifiedName pkg = StringUtil.isEmpty(unit.myPackageId) ? null : names.fromString(unit.myPackageId, true); + stubEnter.unitEnter(Translator.internNames(names, unit, fileId, pkg)); } - }, scope); - } + return true; + } + }); } + private static class IdSets { + final BitSet sourceFiles = new BitSet(); + final BitSet libraryFiles = new BitSet(); + + static IdSets getIdSets(@NotNull Project project) { + return CachedValuesManager.getManager(project).getCachedValue(project, () -> { + IdSets answer = new IdSets(); + ProjectFileIndex index = ProjectFileIndex.SERVICE.getInstance(project); + FileBasedIndex.getInstance().iterateIndexableFiles(file -> { + if (!file.isDirectory() && file instanceof VirtualFileWithId) { + if (index.isInSourceContent(file)) { + answer.sourceFiles.set(((VirtualFileWithId) file).getId()); + } + else if (index.isInLibraryClasses(file)) { + answer.libraryFiles.set(((VirtualFileWithId) file).getId()); + } + } + return true; + }, project, ProgressIndicatorProvider.getGlobalProgressIndicator()); + return CachedValueProvider.Result.create(answer, ProjectRootManager.getInstance(project), VirtualFileManager.VFS_STRUCTURE_MODIFICATIONS); + }); + } + } } diff --git a/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/JavaStubIndexer.java b/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/JavaStubIndexer.java index 550c33b9c74e..616ea7213f3c 100644 --- a/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/JavaStubIndexer.java +++ b/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/JavaStubIndexer.java @@ -18,7 +18,6 @@ package com.intellij.psi.stubsHierarchy.impl; import com.intellij.ide.highlighter.JavaClassFileType; import com.intellij.ide.highlighter.JavaFileType; import com.intellij.openapi.fileTypes.FileType; -import com.intellij.openapi.util.Pair; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiModifier; import com.intellij.psi.PsiNameHelper; @@ -39,7 +38,10 @@ import com.intellij.util.indexing.FileContent; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.*; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; public class JavaStubIndexer extends StubHierarchyIndexer { @@ -61,7 +63,7 @@ public class JavaStubIndexer extends StubHierarchyIndexer { @Nullable @Override - public List> indexFile(@NotNull FileContent content) { + public Unit indexFile(@NotNull FileContent content) { Stub stubTree = StubTreeBuilder.buildStubTree(content); if (!(stubTree instanceof PsiJavaFileStub)) return null; @@ -87,7 +89,7 @@ public class JavaStubIndexer extends StubHierarchyIndexer { ClassDecl[] classes = classList.isEmpty() ? ClassDecl.EMPTY_ARRAY : classList.toArray(new ClassDecl[classList.size()]); Import[] imports = importList.isEmpty() ? Import.EMPTY_ARRAY : importList.toArray(new Import[importList.size()]); byte type = javaFileStub.isCompiled() ? IndexTree.BYTECODE : IndexTree.JAVA; - return Collections.singletonList(Pair.create(javaFileStub.getPackageName(), new Unit(type, imports, classes))); + return new Unit(javaFileStub.getPackageName(), type, imports, classes); } @Nullable diff --git a/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/StubHierarchyIndex.java b/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/StubHierarchyIndex.java index 2550e2fb528a..269bf9fa1f1a 100644 --- a/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/StubHierarchyIndex.java +++ b/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/StubHierarchyIndex.java @@ -18,47 +18,42 @@ package com.intellij.psi.stubsHierarchy.impl; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.roots.ProjectFileIndex; -import com.intellij.openapi.util.Pair; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.impl.java.stubs.hierarchy.IndexTree; import com.intellij.psi.impl.java.stubs.index.JavaUnitDescriptor; import com.intellij.psi.stubsHierarchy.StubHierarchyIndexer; import com.intellij.util.indexing.*; import com.intellij.util.io.DataExternalizer; -import com.intellij.util.io.EnumeratorStringDescriptor; +import com.intellij.util.io.EnumeratorIntegerDescriptor; import com.intellij.util.io.KeyDescriptor; import org.jetbrains.annotations.NotNull; -import java.util.*; +import java.util.Arrays; +import java.util.Collections; /** * @author peter */ -public class StubHierarchyIndex extends FileBasedIndexExtension implements PsiDependentIndex { - static final ID INDEX_ID = ID.create("jvm.hierarchy"); +public class StubHierarchyIndex extends FileBasedIndexExtension implements PsiDependentIndex { + public static final int BINARY_FILES = 0; + public static final int SOURCE_FILES = 1; + static final ID INDEX_ID = ID.create("jvm.hierarchy"); private static final StubHierarchyIndexer[] ourIndexers = StubHierarchyIndexer.EP_NAME.getExtensions(); @NotNull @Override - public ID getName() { + public ID getName() { return INDEX_ID; } @NotNull @Override - public DataIndexer getIndexer() { + public DataIndexer getIndexer() { return inputData -> { for (StubHierarchyIndexer indexer : ourIndexers) { - List> pairs = indexer.handlesFile(inputData.getFile()) ? indexer.indexFile(inputData) : null; - if (pairs != null && !pairs.isEmpty()) { - Map answer = new HashMap<>(); - for (Pair entry : pairs) { - if (entry.second.myDecls.length > 0) { - answer.put(StringUtil.notNullize(entry.first), entry.second); - } - } - return answer; + IndexTree.Unit unit = indexer.handlesFile(inputData.getFile()) ? indexer.indexFile(inputData) : null; + if (unit != null && unit.myDecls.length > 0) { + return Collections.singletonMap(inputData.getFile().getFileType().isBinary() ? BINARY_FILES : SOURCE_FILES, unit); } } return Collections.emptyMap(); @@ -67,8 +62,8 @@ public class StubHierarchyIndex extends FileBasedIndexExtension getKeyDescriptor() { - return EnumeratorStringDescriptor.INSTANCE; + public KeyDescriptor getKeyDescriptor() { + return EnumeratorIntegerDescriptor.INSTANCE; } @NotNull @@ -79,7 +74,7 @@ public class StubHierarchyIndex extends FileBasedIndexExtension { @Override public void save(@NotNull DataOutput out, IndexTree.Unit value) throws IOException { + out.writeUTF(value.myPackageId); out.writeByte(value.myUnitType); if (value.myUnitType != IndexTree.BYTECODE) { DataInputOutputUtil.writeINT(out, value.imports.length); @@ -75,6 +76,7 @@ public class JavaUnitDescriptor implements DataExternalizer { @Override public IndexTree.Unit read(@NotNull DataInput in) throws IOException { + String pid = in.readUTF(); byte type = in.readByte(); IndexTree.Import[] imports = IndexTree.Import.EMPTY_ARRAY; if (type != IndexTree.BYTECODE) { @@ -87,7 +89,7 @@ public class JavaUnitDescriptor implements DataExternalizer { for (int i = 0; i < classes.length; i++) { classes[i] = readClassDecl(in); } - return new IndexTree.Unit(type, imports, classes); + return new IndexTree.Unit(pid, type, imports, classes); } private IndexTree.ClassDecl readClassDecl(DataInput in) throws IOException { diff --git a/java/java-indexing-impl/src/com/intellij/psi/stubsHierarchy/StubHierarchyIndexer.java b/java/java-indexing-impl/src/com/intellij/psi/stubsHierarchy/StubHierarchyIndexer.java index ce9d16602224..4e0e8ac260fc 100644 --- a/java/java-indexing-impl/src/com/intellij/psi/stubsHierarchy/StubHierarchyIndexer.java +++ b/java/java-indexing-impl/src/com/intellij/psi/stubsHierarchy/StubHierarchyIndexer.java @@ -16,15 +16,12 @@ package com.intellij.psi.stubsHierarchy; import com.intellij.openapi.extensions.ExtensionPointName; -import com.intellij.openapi.util.Pair; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.impl.java.stubs.hierarchy.IndexTree; import com.intellij.util.indexing.FileContent; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.List; - /** * @author peter */ @@ -37,7 +34,7 @@ public abstract class StubHierarchyIndexer { * @return a list of pairs for a specified file content */ @Nullable - public abstract List> indexFile(@NotNull FileContent content); + public abstract IndexTree.Unit indexFile(@NotNull FileContent content); public abstract boolean handlesFile(@NotNull VirtualFile file); diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/hierarchy/IndexTree.java b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/hierarchy/IndexTree.java index faf27c3a2d7b..fdf452e9af91 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/hierarchy/IndexTree.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/hierarchy/IndexTree.java @@ -17,6 +17,9 @@ package com.intellij.psi.impl.java.stubs.hierarchy; import com.intellij.openapi.util.registry.Registry; +import com.intellij.openapi.util.text.StringUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.Arrays; @@ -37,11 +40,13 @@ public class IndexTree { public static final byte GROOVY = 2; public static class Unit { + @NotNull public final String myPackageId; public final byte myUnitType; public final Import[] imports; public final ClassDecl[] myDecls; - public Unit(byte unitType, Import[] imports, ClassDecl[] decls) { + public Unit(@Nullable String packageId, byte unitType, Import[] imports, ClassDecl[] decls) { + this.myPackageId = StringUtil.notNullize(packageId); this.myUnitType = unitType; this.imports = imports; this.myDecls = decls; @@ -54,6 +59,8 @@ public class IndexTree { Unit unit = (Unit)o; + if (myUnitType != unit.myUnitType) return false; + if (!myPackageId.equals(unit.myPackageId)) return false; if (!Arrays.equals(imports, unit.imports)) return false; if (!Arrays.equals(myDecls, unit.myDecls)) return false; @@ -62,7 +69,14 @@ public class IndexTree { @Override public int hashCode() { - return Arrays.hashCode(myDecls); + int hash = myUnitType * 31 + myPackageId.hashCode(); + for (ClassDecl decl : myDecls) { + String name = decl.myName; + if (name != null) { + return hash * 31 + name.hashCode(); + } + } + return hash; } } diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/stubs/hierarchy/GrStubIndexer.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/stubs/hierarchy/GrStubIndexer.java index 2a9303c09d62..c124aae6cc20 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/stubs/hierarchy/GrStubIndexer.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/stubs/hierarchy/GrStubIndexer.java @@ -15,7 +15,6 @@ */ package org.jetbrains.plugins.groovy.lang.psi.stubs.hierarchy; -import com.intellij.openapi.util.Pair; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiNameHelper; import com.intellij.psi.impl.java.stubs.hierarchy.IndexTree; @@ -33,7 +32,10 @@ import org.jetbrains.plugins.groovy.GroovyFileType; import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes; import org.jetbrains.plugins.groovy.lang.psi.stubs.*; -import java.util.*; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; public class GrStubIndexer extends StubHierarchyIndexer { @Override @@ -48,14 +50,14 @@ public class GrStubIndexer extends StubHierarchyIndexer { @Nullable @Override - public List> indexFile(@NotNull FileContent content) { + public Unit indexFile(@NotNull FileContent content) { Stub stubTree = StubTreeBuilder.buildStubTree(content); if (!(stubTree instanceof GrFileStub)) return null; GrFileStub grFileStub = (GrFileStub)stubTree; new StubTree(grFileStub, false); - String pid = null; + String pid = ""; ArrayList classList = new ArrayList(); Set usedNames = new HashSet(); for (StubElement el : grFileStub.getChildrenStubs()) { @@ -82,7 +84,7 @@ public class GrStubIndexer extends StubHierarchyIndexer { } ClassDecl[] classes = classList.isEmpty() ? ClassDecl.EMPTY_ARRAY : classList.toArray(new ClassDecl[classList.size()]); Import[] imports = importList.isEmpty() ? Import.EMPTY_ARRAY : importList.toArray(new Import[importList.size()]); - return Collections.singletonList(Pair.create(pid, new Unit(IndexTree.GROOVY, imports, classes))); + return new Unit(pid, IndexTree.GROOVY, imports, classes); } @Nullable From daf076085a848aff02008c60808e2fe717474c00 Mon Sep 17 00:00:00 2001 From: Elizaveta Shashkova Date: Fri, 24 Jun 2016 15:59:22 +0300 Subject: [PATCH 086/107] Fix NPE in test (PY-16825) --- .../python/console/PythonConsoleView.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/python/src/com/jetbrains/python/console/PythonConsoleView.java b/python/src/com/jetbrains/python/console/PythonConsoleView.java index 32b4dc981093..98a25946f70b 100644 --- a/python/src/com/jetbrains/python/console/PythonConsoleView.java +++ b/python/src/com/jetbrains/python/console/PythonConsoleView.java @@ -96,12 +96,14 @@ public class PythonConsoleView extends LanguageConsoleImpl implements Observable } public void inputRequested() { - final ConsoleCommunication consoleCommunication = myExecuteActionHandler.getConsoleCommunication(); - if (consoleCommunication instanceof PythonDebugConsoleCommunication) { - ((PythonDebugConsoleCommunication)consoleCommunication).waitingForInput = true; - myExecuteActionHandler.inputRequested(); - myExecuteActionHandler.setEnabled(true); - myExecuteActionHandler.clearInputBuffer(); + if (myExecuteActionHandler != null) { + final ConsoleCommunication consoleCommunication = myExecuteActionHandler.getConsoleCommunication(); + if (consoleCommunication instanceof PythonDebugConsoleCommunication) { + ((PythonDebugConsoleCommunication)consoleCommunication).waitingForInput = true; + myExecuteActionHandler.inputRequested(); + myExecuteActionHandler.setEnabled(true); + myExecuteActionHandler.clearInputBuffer(); + } } } From a63c3e539c29e9673a9c89acfb11792cc5bcb818 Mon Sep 17 00:00:00 2001 From: Alexander Koshevoy Date: Fri, 24 Jun 2016 16:03:24 +0300 Subject: [PATCH 087/107] PY-18843 Remote Python SDKs are not considered as candidates for base SDKs for virtual envs --- python/src/com/jetbrains/python/sdk/PythonSdkType.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/python/src/com/jetbrains/python/sdk/PythonSdkType.java b/python/src/com/jetbrains/python/sdk/PythonSdkType.java index f45a1331e6b7..f4e78a80c7c8 100644 --- a/python/src/com/jetbrains/python/sdk/PythonSdkType.java +++ b/python/src/com/jetbrains/python/sdk/PythonSdkType.java @@ -59,7 +59,6 @@ import com.intellij.remote.ext.LanguageCaseCollector; import com.intellij.util.ArrayUtil; import com.intellij.util.Consumer; import com.intellij.util.ExceptionUtil; -import com.intellij.util.NullableConsumer; import com.intellij.util.containers.ContainerUtil; import com.jetbrains.python.PyBundle; import com.jetbrains.python.PyNames; @@ -322,9 +321,11 @@ public final class PythonSdkType extends SdkType { final String version = getVersionString(sdk); if (flavor != null && version != null) { for (Sdk baseSdk : getAllSdks()) { - final PythonSdkFlavor baseFlavor = PythonSdkFlavor.getFlavor(baseSdk); - if (!isVirtualEnv(baseSdk) && flavor.equals(baseFlavor) && version.equals(getVersionString(baseSdk))) { - return baseSdk; + if (!isRemote(baseSdk)) { + final PythonSdkFlavor baseFlavor = PythonSdkFlavor.getFlavor(baseSdk); + if (!isVirtualEnv(baseSdk) && flavor.equals(baseFlavor) && version.equals(getVersionString(baseSdk))) { + return baseSdk; + } } } } From d5ecf206cd1efd64acecabcd4e23bbeb0ede0508 Mon Sep 17 00:00:00 2001 From: Valentin Fondaratov Date: Fri, 24 Jun 2016 16:44:01 +0300 Subject: [PATCH 088/107] CPP-4692: RIP net.nicoulaj.idea.markdown (blacklisted all versions) --- platform/platform-resources/src/brokenPlugins.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-resources/src/brokenPlugins.txt b/platform/platform-resources/src/brokenPlugins.txt index b0df3bcebde1..91563d77e5bc 100644 --- a/platform/platform-resources/src/brokenPlugins.txt +++ b/platform/platform-resources/src/brokenPlugins.txt @@ -28,7 +28,7 @@ com.jetbrains.plugins.ini4idea 0.3 0.2 0.4 0.5 0.6 0.7 0.8 0.8.1 0.9 0.9.1 1.0 org.jetbrains.plugins.vagrant 0.6.143.80 0.6.143.71 0.6.143.1 0.1 0.2 0.3 0.4 0.5 0.6.143.3 com.intellij.apacheConfig 143.381.48 142.5266 141.388 139.789 138.2502 org.intellij.clojure 0.2.1.178 -net.nicoulaj.idea.markdown 0.9.5 0.9.4 0.9.3 0.9.2 0.9.1 0.8.3 0.8.2 0.8.1 0.8 0.7 0.6.1 0.6 0.5.1 0.5 0.4 0.3 0.2 0.1 +net.nicoulaj.idea.markdown 0.9.7 0.9.6 0.9.5 0.9.4 0.9.3 0.9.2 0.9.1 0.8.3 0.8.2 0.8.1 0.8 0.7 0.6.1 0.6 0.5.1 0.5 0.4 0.3 0.2 0.1 zielu.gittoolbox 13.1.0 13.5.2 mobi.hsz.idea.gitignore 1.2 1.3 com.vladsch.idea.multimarkdown 1.4.2 1.4.7 From 7a7dfe9373ad5c7e6b80b6afd424b80ec1bd16c6 Mon Sep 17 00:00:00 2001 From: Konstantin Ulitin Date: Fri, 24 Jun 2016 16:47:19 +0300 Subject: [PATCH 089/107] WEB-15808 use old untouched JSDoc elements on tree rebuilding --- .../intellij/psi/tree/CustomParsingType.java | 6 +---- .../intellij/psi/tree/ICustomParsingType.java | 23 +++++++++++++++++++ .../intellij/lang/impl/PsiBuilderImpl.java | 6 ++--- 3 files changed, 27 insertions(+), 8 deletions(-) create mode 100644 platform/core-api/src/com/intellij/psi/tree/ICustomParsingType.java diff --git a/platform/core-api/src/com/intellij/psi/tree/CustomParsingType.java b/platform/core-api/src/com/intellij/psi/tree/CustomParsingType.java index 45fb4110211b..d369c892d2ef 100644 --- a/platform/core-api/src/com/intellij/psi/tree/CustomParsingType.java +++ b/platform/core-api/src/com/intellij/psi/tree/CustomParsingType.java @@ -19,17 +19,13 @@ */ package com.intellij.psi.tree; -import com.intellij.lang.ASTNode; import com.intellij.lang.Language; -import com.intellij.util.CharTable; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -public abstract class CustomParsingType extends IElementType { +public abstract class CustomParsingType extends IElementType implements ICustomParsingType { public CustomParsingType(@NotNull @NonNls String debugName, @Nullable Language language) { super(debugName, language); } - - public abstract ASTNode parse(CharSequence text, CharTable table); } diff --git a/platform/core-api/src/com/intellij/psi/tree/ICustomParsingType.java b/platform/core-api/src/com/intellij/psi/tree/ICustomParsingType.java new file mode 100644 index 000000000000..d37106994c61 --- /dev/null +++ b/platform/core-api/src/com/intellij/psi/tree/ICustomParsingType.java @@ -0,0 +1,23 @@ +/* + * Copyright 2000-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.psi.tree; + +import com.intellij.lang.ASTNode; +import com.intellij.util.CharTable; + +public interface ICustomParsingType { + ASTNode parse(CharSequence text, CharTable table); +} diff --git a/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java b/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java index a07f110329e3..0563e613ea61 100644 --- a/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java +++ b/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java @@ -1562,7 +1562,7 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder { } if (oldNode.getElementType() instanceof ILazyParseableElementType && type instanceof ILazyParseableElementType || - oldNode.getElementType() instanceof CustomParsingType && type instanceof CustomParsingType) { + oldNode.getElementType() instanceof ICustomParsingType && type instanceof ICustomParsingType) { return ((TreeElement)oldNode).textMatches(token.getText()) ? ThreeState.YES : ThreeState.NO; @@ -1853,8 +1853,8 @@ public class PsiBuilderImpl extends UserDataHolderBase implements PsiBuilder { return new PsiWhiteSpaceImpl(text); } - if (type instanceof CustomParsingType) { - return (TreeElement)((CustomParsingType)type).parse(text, myCharTable); + if (type instanceof ICustomParsingType) { + return (TreeElement)((ICustomParsingType)type).parse(text, myCharTable); } if (type instanceof ILazyParseableElementType) { From 9c4f7ff53c9b74f7b7c1a25a551a03501446f073 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Fri, 24 Jun 2016 15:20:50 +0200 Subject: [PATCH 090/107] avoid extra logging on not found file (IDEA-157272) --- .../src/com/intellij/openapi/project/FileContentQueue.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/project/FileContentQueue.java b/platform/platform-impl/src/com/intellij/openapi/project/FileContentQueue.java index d8a822ec3bcc..2ca27bfd6f9c 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/FileContentQueue.java +++ b/platform/platform-impl/src/com/intellij/openapi/project/FileContentQueue.java @@ -29,6 +29,7 @@ import com.intellij.util.concurrency.AppExecutorUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.io.FileNotFoundException; import java.io.IOException; import java.util.Collection; import java.util.Deque; @@ -156,7 +157,11 @@ public class FileContentQueue { throw (InterruptedException)e; } else if (e instanceof IOException || e instanceof InvalidVirtualFileAccessException) { - LOG.info(e); + if (e instanceof FileNotFoundException) { + LOG.debug(e); // it is possible to not observe file system change until refresh finish, we handle missed file properly anyway + } else { + LOG.info(e); + } } else if (ApplicationManager.getApplication().isUnitTestMode()) { //noinspection CallToPrintStackTrace From 33c516b5fd762b5ef7d44dcb85b148435c3e4688 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Fri, 24 Jun 2016 16:03:41 +0200 Subject: [PATCH 091/107] blacklist v0.1.9 of com.chrisrm.idea.MaterialThemeUI due to IDEA-157843 --- platform/platform-resources/src/brokenPlugins.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/platform-resources/src/brokenPlugins.txt b/platform/platform-resources/src/brokenPlugins.txt index 91563d77e5bc..1d2302211944 100644 --- a/platform/platform-resources/src/brokenPlugins.txt +++ b/platform/platform-resources/src/brokenPlugins.txt @@ -56,3 +56,4 @@ com.phpuaca 1.3.1 1.2.1 coffeescript-idea 0.1-1-gae5a RESTClient 1.2 krasa.nonProjectFilesUnlocker 1.0 1.1 +com.chrisrm.idea.MaterialThemeUI 0.1.9 From 79445fe5b8f7e835650f5a98681795adac7977a9 Mon Sep 17 00:00:00 2001 From: Rustam Vishnyakov Date: Fri, 24 Jun 2016 16:53:22 +0300 Subject: [PATCH 092/107] Line comments wrapping to take formatter on/off tags into account (WEB-22093 Formatter formats a comment despite (enabled) formatter markers telling it not to) --- .../src/com/intellij/formatting/FormatterTagHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/formatting/FormatterTagHandler.java b/platform/lang-impl/src/com/intellij/formatting/FormatterTagHandler.java index 1bfca618803e..51e607a2acfd 100644 --- a/platform/lang-impl/src/com/intellij/formatting/FormatterTagHandler.java +++ b/platform/lang-impl/src/com/intellij/formatting/FormatterTagHandler.java @@ -58,7 +58,7 @@ public class FormatterTagHandler { return FormatterTag.NONE; } - private FormatterTag getFormatterTag(@NotNull PsiComment comment) { + protected FormatterTag getFormatterTag(@NotNull PsiComment comment) { CharSequence nodeChars = comment.getNode().getChars(); if (mySettings.FORMATTER_TAGS_ACCEPT_REGEXP) { Pattern onPattern = mySettings.getFormatterOnPattern(); From 9b30c776fb6bbb559d2e0b19c5c5e3eed4cde47c Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Fri, 24 Jun 2016 17:07:27 +0300 Subject: [PATCH 093/107] update charref link and make sure curl follows redirects --- xml/relaxng/src/resources/html5charref.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xml/relaxng/src/resources/html5charref.rb b/xml/relaxng/src/resources/html5charref.rb index b5850d6ece72..9d0b8f9b0ef8 100755 --- a/xml/relaxng/src/resources/html5charref.rb +++ b/xml/relaxng/src/resources/html5charref.rb @@ -1,6 +1,6 @@ #! /usr/bin/env ruby -CHAR_REFS_URL = 'http://dev.w3.org/html5/html-author/charref' -refs = `curl #{CHAR_REFS_URL}` +CHAR_REFS_URL = 'https://dev.w3.org/html5/html-author/charref' +refs = `curl -L #{CHAR_REFS_URL}` header = <
Date: Fri, 24 Jun 2016 15:49:43 +0300 Subject: [PATCH 094/107] EDU-607 Change course information dialogue is oversized --- .../edu/coursecreator/actions/CCChangeCourseInfo.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCChangeCourseInfo.java b/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCChangeCourseInfo.java index 3423c822aae8..9b0839dacaa6 100644 --- a/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCChangeCourseInfo.java +++ b/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCChangeCourseInfo.java @@ -9,7 +9,6 @@ import com.intellij.openapi.project.DumbAwareAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogBuilder; import com.intellij.psi.PsiDirectory; -import com.intellij.util.ui.JBUI; import com.jetbrains.edu.coursecreator.CCUtils; import com.jetbrains.edu.coursecreator.ui.CCNewProjectPanel; import com.jetbrains.edu.learning.StudyTaskManager; @@ -17,6 +16,7 @@ import com.jetbrains.edu.learning.courseFormat.Course; import org.jetbrains.annotations.NotNull; import javax.swing.*; +import java.awt.*; public class CCChangeCourseInfo extends DumbAwareAction { @@ -75,7 +75,8 @@ public class CCChangeCourseInfo extends DumbAwareAction { builder.setTitle(ACTION_TEXT); JPanel changeInfoPanel = panel.getMainPanel(); - changeInfoPanel.setMinimumSize(JBUI.size(400, 300)); + changeInfoPanel.setPreferredSize(new Dimension(450, 300)); + changeInfoPanel.setMinimumSize(new Dimension(450, 300)); builder.setCenterPanel(changeInfoPanel); return builder; From 1622c156bd7c8cfc90c593c04bf0a863cb7e0fb8 Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Fri, 24 Jun 2016 17:23:51 +0300 Subject: [PATCH 095/107] EDU-611 Edit Answer Placeholder: dialogue window should remember size changes --- .../ui/CCCreateAnswerPlaceholderPanel.form | 63 ++++++------------- .../ui/CCCreateAnswerPlaceholderPanel.java | 3 + 2 files changed, 23 insertions(+), 43 deletions(-) diff --git a/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/ui/CCCreateAnswerPlaceholderPanel.form b/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/ui/CCCreateAnswerPlaceholderPanel.form index 5e4b17d84c04..de3a7827e3f1 100644 --- a/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/ui/CCCreateAnswerPlaceholderPanel.form +++ b/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/ui/CCCreateAnswerPlaceholderPanel.form @@ -1,6 +1,6 @@
- + @@ -13,62 +13,39 @@ + - - + - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + diff --git a/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/ui/CCCreateAnswerPlaceholderPanel.java b/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/ui/CCCreateAnswerPlaceholderPanel.java index 28cd014d3288..09a6012c5ca7 100644 --- a/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/ui/CCCreateAnswerPlaceholderPanel.java +++ b/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/ui/CCCreateAnswerPlaceholderPanel.java @@ -1,5 +1,7 @@ package com.jetbrains.edu.coursecreator.ui; +import com.intellij.ui.JBColor; + import javax.swing.*; import java.awt.*; @@ -14,6 +16,7 @@ public class CCCreateAnswerPlaceholderPanel extends JPanel { add(myPanel, BorderLayout.CENTER); myHintText.setLineWrap(true); myHintText.setWrapStyleWord(true); + myHintText.setBorder(BorderFactory.createLineBorder(JBColor.border())); myAnswerPlaceholderText.grabFocus(); } From 4013742771406514cb47ad1d431d20beaeaa8e69 Mon Sep 17 00:00:00 2001 From: Konstantin Ulitin Date: Fri, 24 Jun 2016 17:24:31 +0300 Subject: [PATCH 096/107] javadoc and notnull --- .../src/com/intellij/psi/tree/ICustomParsingType.java | 8 +++++++- .../src/com/intellij/psi/xml/XmlElementType.java | 4 +++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/platform/core-api/src/com/intellij/psi/tree/ICustomParsingType.java b/platform/core-api/src/com/intellij/psi/tree/ICustomParsingType.java index d37106994c61..659f24e4c169 100644 --- a/platform/core-api/src/com/intellij/psi/tree/ICustomParsingType.java +++ b/platform/core-api/src/com/intellij/psi/tree/ICustomParsingType.java @@ -17,7 +17,13 @@ package com.intellij.psi.tree; import com.intellij.lang.ASTNode; import com.intellij.util.CharTable; +import org.jetbrains.annotations.NotNull; +/** + * A token which is more convenient to parse separately. Parsing is done when leaf elements are created. + */ public interface ICustomParsingType { - ASTNode parse(CharSequence text, CharTable table); + + @NotNull + ASTNode parse(@NotNull CharSequence text, @NotNull CharTable table); } diff --git a/xml/xml-psi-impl/src/com/intellij/psi/xml/XmlElementType.java b/xml/xml-psi-impl/src/com/intellij/psi/xml/XmlElementType.java index cd2625b33117..dfb434e08053 100644 --- a/xml/xml-psi-impl/src/com/intellij/psi/xml/XmlElementType.java +++ b/xml/xml-psi-impl/src/com/intellij/psi/xml/XmlElementType.java @@ -27,6 +27,7 @@ import com.intellij.psi.tree.*; import com.intellij.psi.tree.xml.IXmlElementType; import com.intellij.util.CharTable; import com.intellij.util.diff.FlyweightCapableTreeStructure; +import org.jetbrains.annotations.NotNull; public interface XmlElementType extends XmlTokenType { @@ -67,8 +68,9 @@ public interface XmlElementType extends XmlTokenType { IFileElementType DTD_FILE = new IFileElementType("DTD_FILE", DTDLanguage.INSTANCE); IElementType XML_MARKUP_DECL = new CustomParsingType("XML_MARKUP_DECL", XMLLanguage.INSTANCE){ + @NotNull @Override - public ASTNode parse(CharSequence text, CharTable table) { + public ASTNode parse(@NotNull CharSequence text, @NotNull CharTable table) { return new DtdParsing(text, XML_MARKUP_DECL, DtdParsing.TYPE_FOR_MARKUP_DECL, null).parse(); } }; From 7f70956afe4305e1101680b64fd4772e750df54b Mon Sep 17 00:00:00 2001 From: Ekaterina Tuzova Date: Fri, 24 Jun 2016 17:35:04 +0300 Subject: [PATCH 097/107] EDU-434 Unable to narrow Add/Edit Answer Plaveholder dialog window --- .../ui/CCCreateAnswerPlaceholderPanel.form | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/ui/CCCreateAnswerPlaceholderPanel.form b/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/ui/CCCreateAnswerPlaceholderPanel.form index de3a7827e3f1..e5ff6da604d1 100644 --- a/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/ui/CCCreateAnswerPlaceholderPanel.form +++ b/python/educational-core/course-creator/src/com/jetbrains/edu/coursecreator/ui/CCCreateAnswerPlaceholderPanel.form @@ -10,7 +10,7 @@ - + @@ -20,8 +20,8 @@ - - + + @@ -30,7 +30,7 @@ - + @@ -39,9 +39,9 @@ - - - + + + From b4a2271239ee7ea84f76175427d7f30a26beb3ea Mon Sep 17 00:00:00 2001 From: peter Date: Fri, 24 Jun 2016 17:02:00 +0200 Subject: [PATCH 098/107] stub hierarchy: serialize hashes instead of names for faster reading, smaller index data and a very unlikely collision probability --- .../impl/HierarchyServiceImpl.java | 3 +- .../stubsHierarchy/impl/NameEnvironment.java | 21 +--- .../stubsHierarchy/impl/NamesEnumerator.java | 61 +--------- .../impl/StubHierarchyIndex.java | 2 +- .../psi/stubsHierarchy/impl/Translator.java | 27 +---- .../java/stubs/index/JavaUnitDescriptor.java | 75 +++++++++--- .../impl/java/stubs/hierarchy/IndexTree.java | 109 +++++++++++++----- 7 files changed, 149 insertions(+), 149 deletions(-) diff --git a/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/HierarchyServiceImpl.java b/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/HierarchyServiceImpl.java index 654729f0d1ba..2583ea48770b 100644 --- a/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/HierarchyServiceImpl.java +++ b/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/HierarchyServiceImpl.java @@ -20,7 +20,6 @@ import com.intellij.openapi.progress.ProgressIndicatorProvider; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ProjectFileIndex; import com.intellij.openapi.roots.ProjectRootManager; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.openapi.vfs.VirtualFileWithId; import com.intellij.psi.impl.java.stubs.hierarchy.IndexTree; @@ -89,7 +88,7 @@ public class HierarchyServiceImpl extends HierarchyService { public boolean process(int fileId, IndexTree.Unit unit) { if (indicator != null && ++count % 128 == 0) indicator.checkCanceled(); if (files.get(fileId)) { - QualifiedName pkg = StringUtil.isEmpty(unit.myPackageId) ? null : names.fromString(unit.myPackageId, true); + QualifiedName pkg = unit.myPackageName.length == 0 ? null : names.myNamesEnumerator.getFullName(unit.myPackageName, true); stubEnter.unitEnter(Translator.internNames(names, unit, fileId, pkg)); } return true; diff --git a/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/NameEnvironment.java b/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/NameEnvironment.java index 4dd87cff7630..e97f18ff7bd4 100644 --- a/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/NameEnvironment.java +++ b/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/NameEnvironment.java @@ -16,14 +16,12 @@ package com.intellij.psi.stubsHierarchy.impl; import com.intellij.openapi.util.UserDataHolderBase; -import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.impl.java.stubs.hierarchy.IndexTree; import org.jetbrains.annotations.Nullable; import java.util.Arrays; -import java.util.List; public class NameEnvironment extends UserDataHolderBase { - public final QualifiedName empty; public final QualifiedName java_lang_Object; public final QualifiedName java_lang_Enum; @@ -40,22 +38,7 @@ public class NameEnvironment extends UserDataHolderBase { @Nullable public QualifiedName fromString(String s, boolean create) { - List comps = StringUtil.split(s, "."); - int[] ids = new int[comps.size()]; - for (int i = 0; i < comps.size(); i++) { - int name = simpleName(comps.get(i), create); - if (name == NamesEnumerator.NO_NAME) { - return null; - } - ids[i] = name; - } - return myNamesEnumerator.getFullName(ids, create); - } - - public int simpleName(String s, boolean create) { - if (s == null) - return NamesEnumerator.NO_NAME; - return myNamesEnumerator.getSimpleName(s, create); + return myNamesEnumerator.getFullName(IndexTree.hashQualifiedName(s), create); } public QualifiedName prefix(QualifiedName name) { diff --git a/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/NamesEnumerator.java b/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/NamesEnumerator.java index 02ee1143574e..cde21cf6ca45 100644 --- a/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/NamesEnumerator.java +++ b/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/NamesEnumerator.java @@ -15,31 +15,15 @@ */ package com.intellij.psi.stubsHierarchy.impl; -import com.intellij.util.ArrayUtil; import gnu.trove.TObjectHashingStrategy; import gnu.trove.TObjectIntHashMap; -import org.jetbrains.annotations.Nullable; import java.util.Arrays; public class NamesEnumerator { final static int NO_NAME = 0; - private TObjectIntHashMap myAsciiMap = new TObjectIntHashMap(new TObjectHashingStrategy() { - @Override - public int computeHashCode(byte[] object) { - return Arrays.hashCode(object); - } - - @Override - public boolean equals(byte[] o1, byte[] o2) { - return Arrays.equals(o1, o2); - } - }); - - private TObjectIntHashMap myNonAsciiMap = new TObjectIntHashMap(); - - TObjectIntHashMap fullNameMap = new TObjectIntHashMap(new TObjectHashingStrategy() { + private final TObjectIntHashMap myFullNameMap = new TObjectIntHashMap(new TObjectHashingStrategy() { @Override public int computeHashCode(int[] object) { return Arrays.hashCode(object); @@ -50,38 +34,17 @@ public class NamesEnumerator { return Arrays.equals(o1, o2); } }); - private QualifiedName[] myQualifiedNames = new QualifiedName[0x8000]; QualifiedName qualifiedName(int id) { return myQualifiedNames[id]; } - public int getSimpleName(String s, boolean create) { - byte[] bytes = convertToBytesIfAsciiString(s); - if (bytes != null) { - int id = myAsciiMap.get(bytes); - if (id == 0 && create) { - id = myAsciiMap.size() + myNonAsciiMap.size() + 1; - myAsciiMap.put(bytes, id); - } - return id; - } - else { - int id = myNonAsciiMap.get(s); - if (id == 0 && create) { - id = myAsciiMap.size() + myNonAsciiMap.size() + 1; - myNonAsciiMap.put(s, id); - } - return id; - } - } - public QualifiedName getFullName(int[] ids, boolean create) { - int id = fullNameMap.get(ids); + int id = myFullNameMap.get(ids); if (id == 0 && create) { - id = fullNameMap.size() + 1; - fullNameMap.put(ids, id); + id = myFullNameMap.size() + 1; + myFullNameMap.put(ids, id); ensureFullCapacity(id); myQualifiedNames[id] = new QualifiedName(id, ids); } @@ -104,20 +67,4 @@ public class NamesEnumerator { return currentLength; } - @Nullable - public static byte[] convertToBytesIfAsciiString(CharSequence name) { - int length = name.length(); - if (length == 0) return ArrayUtil.EMPTY_BYTE_ARRAY; - - byte[] bytes = new byte[length]; - for (int i = 0; i < length; i++) { - char c = name.charAt(i); - if (c >= 128) { - return null; - } - bytes[i] = (byte)c; - } - return bytes; - } - } diff --git a/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/StubHierarchyIndex.java b/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/StubHierarchyIndex.java index 269bf9fa1f1a..e695897cfe8b 100644 --- a/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/StubHierarchyIndex.java +++ b/java/java-impl/src/com/intellij/psi/stubsHierarchy/impl/StubHierarchyIndex.java @@ -74,7 +74,7 @@ public class StubHierarchyIndex extends FileBasedIndexExtension DEFAULT_JAVA_IMPORTS_KEY = Key.create("java_imports"); @@ -91,11 +88,10 @@ public class Translator { } private static ClassDeclaration processClassDecl(NameEnvironment nameEnvironment, int fileId, IndexTree.ClassDecl def) { - String stubName = def.myName; - int name = stubName == null ? 0 : nameEnvironment.simpleName(stubName, true); + int name = def.myName; ArrayList superList = new ArrayList(); - for (String aSuper : def.mySupers) { - superList.add(id(nameEnvironment, aSuper)); + for (int[] aSuper : def.mySupers) { + superList.add(nameEnvironment.concat(aSuper, true)); } if (BitUtil.isSet(def.myMods, IndexTree.ENUM)) { superList.add(nameEnvironment.java_lang_Enum); @@ -130,21 +126,8 @@ public class Translator { } private static long processImport(NameEnvironment nameEnvironment, IndexTree.Import anImport) { - QualifiedName fullname = nameEnvironment.fromString(anImport.myFullname, true); - int aliasName = anImport.myAlias == null ? 0 : nameEnvironment.simpleName(anImport.myAlias, true); - return Import.mkImport(fullname, anImport.myStaticImport, anImport.myOnDemand, aliasName); + QualifiedName fullname = nameEnvironment.myNamesEnumerator.getFullName(anImport.myFullname, true); + return Import.mkImport(fullname, anImport.myStaticImport, anImport.myOnDemand, anImport.myAlias); } - private static QualifiedName id(NameEnvironment nameEnvironment, String s) { - s = PsiNameHelper.getQualifiedClassName(s, true); - List ids = StringUtil.split(s, "."); - int[] comps = new int[ids.size()]; - int i = 0; - for (String id : ids) { - int name = nameEnvironment.simpleName(id, true); - comps[i] = name; - i++; - } - return nameEnvironment.concat(comps, true); - } } diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaUnitDescriptor.java b/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaUnitDescriptor.java index 48a32c06e307..ad2fddadbe36 100644 --- a/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaUnitDescriptor.java +++ b/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaUnitDescriptor.java @@ -16,6 +16,7 @@ package com.intellij.psi.impl.java.stubs.index; import com.intellij.psi.impl.java.stubs.hierarchy.IndexTree; +import com.intellij.util.BitUtil; import com.intellij.util.io.DataExternalizer; import com.intellij.util.io.DataInputOutputUtil; import org.jetbrains.annotations.NotNull; @@ -24,19 +25,34 @@ import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; +import static com.intellij.psi.impl.java.stubs.index.JavaUnitDescriptor.ImportFlags.*; + public class JavaUnitDescriptor implements DataExternalizer { public static final JavaUnitDescriptor INSTANCE = new JavaUnitDescriptor(); + private static void writeIntArray(DataOutput out, int[] array) throws IOException { + DataInputOutputUtil.writeINT(out, array.length); + for (int i : array) { + out.writeInt(i); + } + } + private static int[] readIntArray(DataInput in) throws IOException { + int length = DataInputOutputUtil.readINT(in); + int[] result = new int[length]; + for (int i = 0; i < length; i++) { + result[i] = in.readInt(); + } + return result; + } + @Override public void save(@NotNull DataOutput out, IndexTree.Unit value) throws IOException { - out.writeUTF(value.myPackageId); + writeIntArray(out, value.myPackageName); out.writeByte(value.myUnitType); if (value.myUnitType != IndexTree.BYTECODE) { DataInputOutputUtil.writeINT(out, value.imports.length); for (IndexTree.Import anImport : value.imports) { - out.writeUTF(anImport.myFullname); - out.writeBoolean(anImport.myStaticImport); - out.writeBoolean(anImport.myOnDemand); + writeImport(out, anImport); } } // class Declaration @@ -47,12 +63,12 @@ public class JavaUnitDescriptor implements DataExternalizer { } private void saveClassDecl(@NotNull DataOutput out, IndexTree.ClassDecl value) throws IOException { - out.writeInt(value.myStubId); + DataInputOutputUtil.writeINT(out, value.myStubId); DataInputOutputUtil.writeINT(out, value.myMods); - out.writeUTF(value.myName == null ? "" : value.myName); + out.writeInt(value.myName); DataInputOutputUtil.writeINT(out, value.mySupers.length); - for (String aSuper : value.mySupers) { - out.writeUTF(aSuper); + for (int[] aSuper : value.mySupers) { + writeIntArray(out, aSuper); } DataInputOutputUtil.writeINT(out, value.myDecls.length); for (IndexTree.Decl def : value.myDecls) { @@ -76,13 +92,13 @@ public class JavaUnitDescriptor implements DataExternalizer { @Override public IndexTree.Unit read(@NotNull DataInput in) throws IOException { - String pid = in.readUTF(); + int[] pid = readIntArray(in); byte type = in.readByte(); IndexTree.Import[] imports = IndexTree.Import.EMPTY_ARRAY; if (type != IndexTree.BYTECODE) { imports = new IndexTree.Import[DataInputOutputUtil.readINT(in)]; for (int i = 0; i < imports.length; i++) { - imports[i] = new IndexTree.Import(in.readUTF(), in.readBoolean(), in.readBoolean(), null); + imports[i] = readImport(in); } } IndexTree.ClassDecl[] classes = new IndexTree.ClassDecl[DataInputOutputUtil.readINT(in)]; @@ -93,15 +109,12 @@ public class JavaUnitDescriptor implements DataExternalizer { } private IndexTree.ClassDecl readClassDecl(DataInput in) throws IOException { - int stubId = in.readInt(); + int stubId = DataInputOutputUtil.readINT(in); int mods = DataInputOutputUtil.readINT(in); - String name = in.readUTF(); - if (name.isEmpty()) { - name = null; - } - String[] supers = new String[DataInputOutputUtil.readINT(in)]; + int name = in.readInt(); + int[][] supers = new int[DataInputOutputUtil.readINT(in)][]; for (int i = 0; i < supers.length; i++) { - supers[i] = in.readUTF(); + supers[i] = readIntArray(in); } IndexTree.Decl[] decls = new IndexTree.Decl[DataInputOutputUtil.readINT(in)]; for (int i = 0; i < decls.length; i++) { @@ -124,4 +137,32 @@ public class JavaUnitDescriptor implements DataExternalizer { } } + interface ImportFlags { + int IS_STATIC = 1; + int IS_ON_DEMAND = 2; + int HAS_ALIAS = 4; + } + + private static void writeImport(@NotNull DataOutput out, IndexTree.Import anImport) throws IOException { + writeIntArray(out, anImport.myFullname); + boolean hasAlias = anImport.myAlias != 0; + int flags = 0; + flags = BitUtil.set(flags, IS_STATIC, anImport.myStaticImport); + flags = BitUtil.set(flags, IS_ON_DEMAND, anImport.myOnDemand); + flags = BitUtil.set(flags, HAS_ALIAS, hasAlias); + out.writeByte(flags); + if (hasAlias) { + out.writeInt(anImport.myAlias); + } + } + + @NotNull + private static IndexTree.Import readImport(@NotNull DataInput in) throws IOException { + int[] fullname = readIntArray(in); + int flags = in.readByte(); + return new IndexTree.Import(fullname, + BitUtil.isSet(flags, IS_STATIC), BitUtil.isSet(flags, IS_ON_DEMAND), + BitUtil.isSet(flags, HAS_ALIAS) ? in.readInt() : 0); + } + } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/hierarchy/IndexTree.java b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/hierarchy/IndexTree.java index fdf452e9af91..b7a148b21be1 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/hierarchy/IndexTree.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/hierarchy/IndexTree.java @@ -18,14 +18,18 @@ package com.intellij.psi.impl.java.stubs.hierarchy; import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.PsiNameHelper; +import com.intellij.util.ArrayUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Arrays; +import java.util.List; public class IndexTree { public static final boolean STUB_HIERARCHY_ENABLED = Registry.is("java.hierarchy.service"); + @SuppressWarnings("PointlessBitwiseExpression") public final static int PACKAGE = 1 << 0; public final static int CLASS = 1 << 1; public static final int STATIC = 1 << 3; @@ -39,17 +43,52 @@ public class IndexTree { public static final byte JAVA = 1; public static final byte GROOVY = 2; + private static int hashIdentifier(@Nullable String s) { + if (s == null) return 0; + + // not using String.hashCode because this way there's less collisions for short package names like 'com' + int hash = 0; + for (int i = 0; i < s.length(); i++) { + hash = hash * 239 + s.charAt(i); + } + return hash; + } + + public static int[] hashQualifiedName(@NotNull String qName) { + qName = PsiNameHelper.getQualifiedClassName(qName, true); + if (qName.isEmpty()) return ArrayUtil.EMPTY_INT_ARRAY; + + List components = StringUtil.split(qName, "."); + int[] result = new int[components.size()]; + for (int i = 0; i < components.size(); i++) { + result[i] = hashIdentifier(components.get(i)); + } + return result; + } + + private static int[][] hashQualifiedNameArray(String[] supers) { + int[][] superHashes = new int[supers.length][]; + for (int i = 0; i < supers.length; i++) { + superHashes[i] = hashQualifiedName(supers[i]); + } + return superHashes; + } + public static class Unit { - @NotNull public final String myPackageId; + @NotNull public final int[] myPackageName; public final byte myUnitType; public final Import[] imports; public final ClassDecl[] myDecls; - public Unit(@Nullable String packageId, byte unitType, Import[] imports, ClassDecl[] decls) { - this.myPackageId = StringUtil.notNullize(packageId); - this.myUnitType = unitType; + public Unit(@Nullable String packageName, byte unitType, Import[] imports, ClassDecl[] decls) { + this(hashQualifiedName(StringUtil.notNullize(packageName)), unitType, imports, decls); + } + + public Unit(@NotNull int[] packageName, byte unitType, Import[] imports, ClassDecl[] decls) { + myPackageName = packageName; + myUnitType = unitType; this.imports = imports; - this.myDecls = decls; + myDecls = decls; } @Override @@ -60,7 +99,7 @@ public class IndexTree { Unit unit = (Unit)o; if (myUnitType != unit.myUnitType) return false; - if (!myPackageId.equals(unit.myPackageId)) return false; + if (!Arrays.equals(myPackageName, unit.myPackageName)) return false; if (!Arrays.equals(imports, unit.imports)) return false; if (!Arrays.equals(myDecls, unit.myDecls)) return false; @@ -69,11 +108,11 @@ public class IndexTree { @Override public int hashCode() { - int hash = myUnitType * 31 + myPackageId.hashCode(); + int hash = myUnitType * 31 + Arrays.hashCode(myPackageName); for (ClassDecl decl : myDecls) { - String name = decl.myName; - if (name != null) { - return hash * 31 + name.hashCode(); + int name = decl.myName; + if (name != 0) { + return hash * 31 + name; } } return hash; @@ -82,16 +121,20 @@ public class IndexTree { public static class Import { public static final Import[] EMPTY_ARRAY = new Import[0]; - public final String myFullname; + public final int[] myFullname; public final boolean myStaticImport; public final boolean myOnDemand; - public final String myAlias; + public final int myAlias; - public Import(String fullname, boolean staticImport, boolean onDemand, String alias) { - this.myFullname = fullname; - this.myStaticImport = staticImport; - this.myOnDemand = onDemand; - this.myAlias = alias; + public Import(String fullname, boolean staticImport, boolean onDemand, @Nullable String alias) { + this(hashQualifiedName(fullname), staticImport, onDemand, hashIdentifier(alias)); + } + + public Import(int[] fullname, boolean staticImport, boolean onDemand, int alias) { + myFullname = fullname; + myStaticImport = staticImport; + myOnDemand = onDemand; + myAlias = alias; } @Override @@ -103,18 +146,18 @@ public class IndexTree { if (myStaticImport != anImport.myStaticImport) return false; if (myOnDemand != anImport.myOnDemand) return false; - if (!myFullname.equals(anImport.myFullname)) return false; - if (myAlias != null ? !myAlias.equals(anImport.myAlias) : anImport.myAlias != null) return false; + if (!Arrays.equals(myFullname, anImport.myFullname)) return false; + if (myAlias != anImport.myAlias) return false; return true; } @Override public int hashCode() { - int result = myFullname.hashCode(); + int result = Arrays.hashCode(myFullname); result = 31 * result + (myStaticImport ? 1 : 0); result = 31 * result + (myOnDemand ? 1 : 0); - result = 31 * result + (myAlias != null ? myAlias.hashCode() : 0); + result = 31 * result + myAlias; return result; } } @@ -132,16 +175,20 @@ public class IndexTree { public static final ClassDecl[] EMPTY_ARRAY = new ClassDecl[0]; public final int myStubId; public final int myMods; - public final String myName; - public final String[] mySupers; + public final int myName; + public final int[][] mySupers; - public ClassDecl(int stubId, int mods, String name, String[] supers, Decl[] decls) { + public ClassDecl(int stubId, int mods, @Nullable String name, String[] supers, Decl[] decls) { + this(stubId, mods, hashIdentifier(name), hashQualifiedNameArray(supers), decls); + } + + public ClassDecl(int stubId, int mods, int name, int[][] supers, Decl[] decls) { super(decls); assert stubId > 0; - this.myStubId = stubId; - this.myMods = mods; - this.myName = name; - this.mySupers = supers; + myStubId = stubId; + myMods = mods; + myName = name; + mySupers = supers; } @Override @@ -152,8 +199,8 @@ public class IndexTree { ClassDecl classDecl = (ClassDecl)o; if (myStubId != classDecl.myStubId) return false; if (myMods != classDecl.myMods) return false; - if (myName != null ? !myName.equals(classDecl.myName) : classDecl.myName != null) return false; - if (!Arrays.equals(mySupers, classDecl.mySupers)) return false; + if (myName != classDecl.myName) return false; + if (!Arrays.deepEquals(mySupers, classDecl.mySupers)) return false; if (!Arrays.equals(myDecls, classDecl.myDecls)) return false; return true; } @@ -162,7 +209,7 @@ public class IndexTree { public int hashCode() { int result = myStubId; result = 31 * result + myMods; - result = 31 * result + (myName != null ? myName.hashCode() : 0); + result = 31 * result + myName; return result; } } From 639181bedcbd06eb05a2ff7ee143bdc097544145 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 24 Jun 2016 18:00:21 +0300 Subject: [PATCH 099/107] rename after IDEA-CR-11745 --- .../src/com/intellij/psi/util/PsiSuperMethodUtil.java | 4 ++-- .../src/com/intellij/psi/impl/TypeCorrector.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java/java-psi-api/src/com/intellij/psi/util/PsiSuperMethodUtil.java b/java/java-psi-api/src/com/intellij/psi/util/PsiSuperMethodUtil.java index 641cb6e7ee88..ef0e11156650 100644 --- a/java/java-psi-api/src/com/intellij/psi/util/PsiSuperMethodUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/util/PsiSuperMethodUtil.java @@ -129,7 +129,7 @@ public class PsiSuperMethodUtil { for (HierarchicalMethodSignature hms : superClass.getVisibleSignatures()) { PsiMethod method = hms.getMethod(); if (MethodSignatureUtil.findMethodBySignature(aClass, method.getSignature(superClassSubstitutor), false) != null) continue; - final PsiClass containingClass = mapClass(method.getContainingClass(), resolveScope); + final PsiClass containingClass = correctClassByScope(method.getContainingClass(), resolveScope); if (containingClass == null) continue; method = containingClass.findMethodBySignature(method, false); if (method == null) continue; @@ -150,7 +150,7 @@ public class PsiSuperMethodUtil { } @Nullable - public static PsiClass mapClass(PsiClass psiClass, final GlobalSearchScope resolveScope) { + public static PsiClass correctClassByScope(PsiClass psiClass, final GlobalSearchScope resolveScope) { if (psiClass == null) return null; String qualifiedName = psiClass.getQualifiedName(); if (qualifiedName == null) { diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/TypeCorrector.java b/java/java-psi-impl/src/com/intellij/psi/impl/TypeCorrector.java index d9fcf6bc3c50..c6063e0b05bd 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/TypeCorrector.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/TypeCorrector.java @@ -55,7 +55,7 @@ class TypeCorrector extends PsiTypeMapper { final PsiClassType.ClassResolveResult classResolveResult = classType.resolveGenerics(); final PsiClass psiClass = classResolveResult.getElement(); if (psiClass != null && classResolveResult.getSubstitutor() == PsiSubstitutor.EMPTY) { - final PsiClass mappedClass = PsiSuperMethodUtil.mapClass(psiClass, myResolveScope); + final PsiClass mappedClass = PsiSuperMethodUtil.correctClassByScope(psiClass, myResolveScope); if (mappedClass == null || mappedClass == psiClass) return (T) classType; } } @@ -78,7 +78,7 @@ class TypeCorrector extends PsiTypeMapper { PsiUtilCore.ensureValid(psiClass); - final PsiClass mappedClass = PsiSuperMethodUtil.mapClass(psiClass, myResolveScope); + final PsiClass mappedClass = PsiSuperMethodUtil.correctClassByScope(psiClass, myResolveScope); if (mappedClass == null) return classType; PsiClassType mappedType = new PsiCorrectedClassType(classType.getLanguageLevel(), From fef88e6bc3d2a7f0674a348ff18143d06d9b26c4 Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Fri, 24 Jun 2016 17:27:21 +0300 Subject: [PATCH 100/107] update ping patch --- xml/relaxng/src/resources/patches/0004_ping.patch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xml/relaxng/src/resources/patches/0004_ping.patch b/xml/relaxng/src/resources/patches/0004_ping.patch index 4e47a934c7d6..1824e58d3b89 100644 --- a/xml/relaxng/src/resources/patches/0004_ping.patch +++ b/xml/relaxng/src/resources/patches/0004_ping.patch @@ -1,6 +1,6 @@ --- /Users/denofevil/Code/sandbox/checker/syntax/relaxng/phrase.rnc 2014-01-24 12:18:24.000000000 +0400 +++ html5/phrase.rnc 2014-01-24 14:08:26.000000000 +0400 -@@ -76,10 +76,6 @@ +@@ -78,10 +78,6 @@ attribute type { common.data.mimetype } From dd5cf93add7b160c3ee09259ff8427c032cb1439 Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Fri, 24 Jun 2016 17:51:50 +0300 Subject: [PATCH 101/107] update html5 schema #WEB-17992 fixed --- .../resources/html5-schema/html5/block.rnc | 3 -- .../resources/html5-schema/html5/common.rnc | 11 +++-- .../src/resources/html5-schema/html5/data.rnc | 29 ++++++++------ .../resources/html5-schema/html5/embed.rnc | 5 --- .../resources/html5-schema/html5/html5.rnc | 3 ++ .../src/resources/html5-schema/html5/meta.rnc | 40 ++++++++++--------- .../resources/html5-schema/html5/phrase.rnc | 1 + .../html5-schema/html5/structural.rnc | 4 +- .../html5-schema/html5/web-forms.rnc | 6 +-- .../html5-schema/html5/web-forms2.rnc | 33 ++++++++++----- .../resources/html5-schema/html5/xhtml5.rnc | 3 ++ .../src/resources/html5-schema/html5chars.ent | 2 +- .../html5-schema/svg11/svg-script.rnc | 2 +- 13 files changed, 81 insertions(+), 61 deletions(-) diff --git a/xml/relaxng/src/resources/html5-schema/html5/block.rnc b/xml/relaxng/src/resources/html5-schema/html5/block.rnc index 6d0eb0d80df1..6f06902115f5 100644 --- a/xml/relaxng/src/resources/html5-schema/html5/block.rnc +++ b/xml/relaxng/src/resources/html5-schema/html5/block.rnc @@ -242,9 +242,6 @@ datatypes w = "http://whattf.org/datatype-draft" element legend { legend.inner & legend.attrs } legend.attrs = ( common.attrs - & ( common.attrs.aria.role.presentation - | common.attrs.aria.role.menuitem - )? ) legend.inner = ( common.inner.phrasing ) diff --git a/xml/relaxng/src/resources/html5-schema/html5/common.rnc b/xml/relaxng/src/resources/html5-schema/html5/common.rnc index 68d9acc5f28f..0800048f2e38 100644 --- a/xml/relaxng/src/resources/html5-schema/html5/common.rnc +++ b/xml/relaxng/src/resources/html5-schema/html5/common.rnc @@ -93,10 +93,8 @@ datatypes w = "http://whattf.org/datatype-draft" ( text & common.elem.flow* ) common.inner.flow = - ( style.elem.scoped*, - ( text - & common.elem.flow* - ) + ( text + & common.elem.flow* ) # ##################################################################### @@ -414,6 +412,11 @@ common.attrs.other = common.data.functionbody = w:functionbody +## autocomplete + + common.data.autocomplete.any = + w:autocomplete-any + # ##################################################################### ## WF2 Module Hook # # ##################################################################### diff --git a/xml/relaxng/src/resources/html5-schema/html5/data.rnc b/xml/relaxng/src/resources/html5-schema/html5/data.rnc index 991f6987dfc3..24c2b110ca31 100644 --- a/xml/relaxng/src/resources/html5-schema/html5/data.rnc +++ b/xml/relaxng/src/resources/html5-schema/html5/data.rnc @@ -10,25 +10,30 @@ datatypes w = "http://whattf.org/datatype-draft" element time { time.inner & time.attrs } time.attrs = ( common.attrs - & time.attrs.datetime? + & common.attrs.aria? + ) + time.inner = + ( text ) #Cannot enforce textContent format here + + common.elem.phrasing |= time.elem + +## Time with datetime attribute: